View this PageEdit this PageUploads to this PageVersions of this PageHomeRecent ChangesSearchHelp Guide

MP10

cs497rej - Homework10

Homework 10


An interactive application - dice

We will build an application modeling the properties of a dice (we will use the Model-View-Controller paradigm). We provide you with some of the code (load parcel "CS598rej-Dice" at the bottom of the page ) and you will enhance it by step-by-step exercises. We start with the abstract model, followed by the visible representation (the view) and finalizing with a controller that adds further functionality.                                                                                                                                                                                                                                                                                                                                             

1. Developing the model Dice

The function of a dice is to generate a random number, so the model is very simple.
Class Dice represents the model which acts as a holder for an integer between 1 and 6. It inherits from class Object. In Squeak every class is an example of the Observer pattern. Every object is a model that can have dependents. You can add a dependent by sending a message #addDependent: to an object. Whenever you change the state of an Object, by sending it #changed message all its dependents are automatically notified (they are sent an #update message). Class Dice does not use other special features from Object. It has an instance variable named 'value'.
Other objects will inquire about the value. This is given by the method value in the class' accessing instance protocol.
Instances of Dice respond to a message roll (in instance protocol modifying), which sets value to an integer between 1 and 6.
The method initialize in protocol initialize-release initializes the instance variable.
The method new in class protocol instance creation initializes instances of Dice when they are created.

You can test our model by creating and inspecting an instance of Dice using the expression:

Dice new inspect
and send it the message roll.

Exercise 1.1. The roll method generates integers from 1 to 6 in order each time the Dice is 'rolled'. Re-implement the method to use a random value (Hint: see method nextInt: in class Random).

Exercise 1.2. The instance initialization method always sets the Dice model to the same value on creation. Modify the initialization method to ensure that a Dice has a random value after creation. (Hint: you already have a method to set the state of dice randomly).

Exercise 1.3. Selecting self in an Inspector on a Dice displays 'aDice '; this uses the default implementation of printOn: defined in class Object. Add a method to Dice that overrides this method so that a Dice is printed with both its class name and its current value.

2. A simple view for Dice

Class DiceView is the simplest useful view for use with Dice. It is a subclass of Morph, like any other graphical objects in the Morphic system.  
The basic function of a view is to display some aspect of its model appropriately. We have overriden the displayOn: method to display the value from the model as a simple digit at the top-left of the view.

We will use the dependency mechanism to provide the communication from the model to its view. However, you need to modify the roll method in Dice class to ensure it notifies its dependents that it has changed. Add the following line to the end of the roll method:
    self changed

DiceView provides a method in the class protocol instance creation, conventionally called openOn:, which creates and displays an instance of DiceView as the component of a SystemWindow.

You can test the view-model combination by evaluating:

tempDice := Dice new.
DiceView openOn: tempDice
Once the Dice has been opened, the expression:
tempDice roll
causes the Dice to change and should be reflected in the inspector you opened on the Dice. But wait, why doesn't it update the view? It's because Morph inherits #update from class Object. The default implementation is to do nothing. You should provide an implementation of #update:anObject that does something useful. It's enough if you add "self changed" in the #update method. Now try rolling your tempDice - your DiceView should update fine. You can also open a second DiceView on the same tempDice and send the roll message to tempDice. That should cause both dependent views to be updated.

Exercise 2.1. Modify the drawOn: method so that the digit is displayed in the center of the view. (Hint:  sending bounds message to a morph returns its enclosing Rectangle.  You can place the string to a different position relative to the enclosing Rectangle ).

Exercise 2.2. The simple drawOn: method above does not put the digit in the exact center of the view. This is because the display reference point of the String displayed is in its top-left corner, which is aligned with the center of the view's bounds. Rewrite the drawOn: method to place the displayed digit in the exact center of the view.

Exercise 2.3. Try increasing the size of the digit displayed by the DiceView (Hint: browse the methods in protocol drawing-text of class Canvas)

Exercise 2.4. Create a new version of the drawOn: method in which the color displayed inside the rectangle is different for each side of the dice. (Hint: browse drawing-rectangle protocol of Canvas)

Exercise 2.5.  The 'roll' action is not very realistic at present, as it only changes value once. Modify the roll method in class Dice so that the dice goes through several intermediate values with a delay between each. (Hint: "(Delay forMilliseconds: 500) wait." will do it). Note: If the view does not refresh properly, try adding self refreshWorld code to the update: method in the DiceView class.

Optional Exercise 2.6. Try to give the DiceView a real 3D shape. Explore the Morph class hierarchy. You'll probably find this exercise useful for your project later. Note that this exercise is optional. You don't need to make it work, just try to play with the 3D classes.

3. The DiceController

Class Morph has capabilities of handling input events (that is, it is both a controller and a view). This is a variation of the classic Model-View-Controller but it's widely used (for instance Java Swing mixes the View and the Controller too).

Exercise 3.1.  We want to be able to roll the dice by clicking with your mouse over it. In order for the Morph to capture mouse clicks (say MouseDown event), you have to add two instance methods to your DiceView. Override #handlesMouseDown: anEvent to return <true>. Also override #mouseDown:anEvent to ask its dice to roll.

Exercise 3.2. It is often convenient to be able to send a message to an object to 'open a view' on that object, in the way in which, for example, the message inspect is interpreted by Object. Implement an open message in instance protocol viewing of Dice to open a system window on an instance of Dice .
 



Additional hints

  • the dice should not show the same value twice in a row
  • the color of dice's side should not be the same as the background



File


CS598rej-Dice.st



Deliverables


1. Fileout the entire package that contains the code.
2. Send me a picture of your dice.

You can make this dice as fancy as you want but if you include additional features, please describe them in your submission.

Link to this Page

  • Machine Problems last edited on 14 May 2008 at 4:25:53 pm by c-98-212-224-168.hsd1.il.comcast.net