3.1 Yahtzee
Write a very simple Yahtzee program based on the Die class. Yahtzee is played by use of five dice that are tossed simultaneously. The players are supposed to fill out a table of results. The table should allow registration of ones, ..., sixes, three-of-a-kind, four-of-a-kind, full-house, small-straight, large-straight, yahtzee, and chance. See wikipedia for more details and inspiration. Be sure to use the version of the Die class that shares the Random class with the other dice. This version of the Die class is produced in another exercise in this lecture. This program is for a single player, who tosses the five dice repeatedly. Each time the five dice are tossed a table cell is filled. No re-tossing is done with less than five dice. The first category that fits a given toss is filled. (Try yahtzee first, Chance last). Keep it simple! You may consider to write a YahtzeeTable class which represents the single user table used to register the state of the game. Consider the interface and operations of this class. |
3.2 Time Classes
This is not a programming exercise, but an exercise which asks you to consider data and operations of classes related to time. Time is very important in our everyday life. Therefore, many of the programs we write somehow deal with time. Design a class PointInTime, which represents a single point in time. How do we represent a point in time? Which variables (data) should be encapsulated in the class? Design the variables in terms of their names and types. Which operations should constitute the client interface of the class? Design the operations in terms of their names, formal parameters (and their types), and the types of their return values. Can you imagine other time-related classes than PointInTime? Avoid looking at the time-related types in the C# library before you solve this exercise. During the course we will come back the time related types in C#. |
3.3 Public data representation
In the accompanying Point and Point client classes the data representation of Point is available to the client class. This may be tempting for the programmer, because we most likely wish to make the x and y coordinates of points available to clients. Why is it a bad solution? It is very important that you can express and explain the problem to fellow programmers. Give it a try! Now assume that we are forced (by the boss) to change the data representation of Point. As a realistic scenario, we may introduce polar coordinates instead of the rectangular x and y coordinates. Recall that polar coordinates consist of a radius and an angle (in radians or degrees). What will happen to client classes, such as this client, when this change is introduced? Is it an easy or a difficult modification to the given client class? Imagine that in a real-life situation we can have thousands of similar lines of code in client programs that refer to x and y coordinates. Rewrite selected parts of class Point such that the client "survives" the change of data representation. In your solution, the instance variables should be private in the Point class. Are you able to make a solution such that the client class should not be changed at all? The private static methods at the bottom of this version of class Point will most likely be helpful. In addition, this version of class Point serves as an initial (but incomplete and somewhat problematic) template of the Point class that you are supposed to write. The client class of Point calculates the distances between pairs of points. This is not a good idea because far too many details occur repeatedly in the client. Suggest a reorganization and implement it. |
Solution
The solution below is programmed with C# properties // A versatile version with Rotation and internal methods // for rectangular and polar coordinates. using System; public class Point { public enum PointRepresentation {Polar, Rectangular} // public double x, y; // previous public data repr. private double r, a; // new, private data repr: radius, angle public Point(double x, double y){ r = RadiusGivenXy(x,y); a = AngleGivenXy(x,y); } public Point(double par1, double par2, PointRepresentation pr){ if (pr == PointRepresentation.Polar){ r = par1; a = par2; } else { r = RadiusGivenXy(par1,par2); a = AngleGivenXy(par1,par2); } } public double x { get {return XGivenRadiusAngle(r,a);} } public double y { get {return YGivenRadiusAngle(r,a);} } public double Radius { get {return r;} } public double Angle{ get {return a;} } public void Move(double dx, double dy){ double x, y; x = XGivenRadiusAngle(r,a); y = XGivenRadiusAngle(r,a); r = RadiusGivenXy(x+dx, y+dy); a = AngleGivenXy(x+dx, y+dy); } public void Rotate(double angle){ a += angle; } public override string ToString(){ return "(" + XGivenRadiusAngle(r,a) + "," + YGivenRadiusAngle(r,a) + ")"; } private static double RadiusGivenXy(double x, double y){ return Math.Sqrt(x * x + y * y); } private static double AngleGivenXy(double x, double y){ return Math.Atan2(y,x); } private static double XGivenRadiusAngle(double r, double a){ return r * Math.Cos(a); } private static double YGivenRadiusAngle(double r, double a){ return r * Math.Sin(a); } } |
3.4 How private are private instance variables?
The purpose of this exercise is to find out how private private instance variables are in C#. Given the BankAccount class. Now modify this class such that each bank account has a backup account. For the backup account you will need a new (private) instance variable of type BankAccount. Modify the Withdraw method, such that if there is not enough money available in the current account, then withdraw the money from the backup account. As an experiment, access the balance of the backup account directly, in the following way: backupAccount.balance -= ... Is it possible to modify the private state of one BankAccount from another BankAccount? Discuss and explain your findings. Are you surprised? |
Solution
It is possible for one BankAccount object to modify the balance of another BankAccount object. The version of class BankAccount shown below demonstrates this. Please notice the line backupAccount.balance -= amount - balance; in the method withdraw. Is this reasonable? Yes. Our observations pertain to objects in the running program - the dynamic situation. Our attention to firewalls (icebergs and representation independence) is oriented towards the source program - the static situation. In relation to programmers, who write the BankAccount class and related classes, it is important to enforce the discipline that the data representation of foreign classes is invisible. Without such a policy the idea of representation independence will be shipwrecked. This is a software engineering concern. It causes no software engineering problems if one BankAccount object can modify the data of another BankAccount object in the way sketched above. Here follows my programmed solution to this exercises:
|
3.5 The method LogTransaction in class BankAccount
In the accompanying BankAccount class we have sketched and used a private method named LogTransaction. Implement this private method and test it with the BankAccount client class. |
Solution
Here is my version of BankAccount class with logging:
Note to the solution: Instead of passing the current time as a parameter to LogTransaction, I found it more reasonable to capture the time inside the body of LogTransaction. |
3.6 Course and Project classes
In this exercise you are asked to program three simple classes which keep track of the grading of a sample student. The classes are called BooleanCourse, GradedCourse, and Project. A BooleanCourse encapsulates a course name and a registration of passed/not passed for our sample student. A GradedCourse encapsulates a course name and the grade of the student. For grading we use the Danish 7-step, numerical grades 12, 10, 7, 4, 2, 0 and -3. You are also welcome use the enumeration type ECTSGrade from an earlier exercise. The grade 2 is the lowest passing grade. In both BooleanCourse and GradedCourse you should write a method called Passed. The method is supposed to return whether our sample student passes the course. The class Project aggregates two boolean courses and two graded courses. You can assume that a project is passed if at least three out of the four courses are passed. Write a method Passed in class Project which implements this passing policy. Make a project with four courses, and try out your solution. In this exercise you are supposed to make a simple and rather primitive solution. We will come back to this exercise when we have learned about inheritance and collection classes. |
Solution
Here is my solution:
In several respects, the program shown above is tedious:
|
3.7 Sharing the Random Generator
In the Die class shown in the start of this lecture, each Die object creates its own Random object. We observed that tosses of two or more instances of class Die will be identical. Explain the reason of this behavior. Modify the Die class such that all of them share a single Random object. Consider different ways to implement this sharing. Rerun the Die program and find out if "the parallel tossing pattern" observed above has been alleviated. |
Solution
The solution which I provide is based on the Singleton design pattern, which we will discuss later in the teaching material. I make my own Random class, which cannot be instantiated because it is a singleton. Thus, you should use Random.Instance() instead of new Random(...).
Notice that uniqueInstance is a class class variable (static variable) in class Random. Notice also that the method called Instance is a class method (static method). |
Generated: Monday February 7, 2011, 12:13:42