CS230 Data Structures, Wellesley College, Fall 1999

Problem Set 4

Due 11:59 pm on Thursday, October 7

[CS230 Home Page] [Assignments] [Documentation] [Software Installation] [FAQ] [CS Dept.] [CWIS]


Important Notes:

Reading: Bailey's book does not cover GUIs. I recommend the following if you want to read up on GUIs:

You can find copies of both books in the E101 library and in the Science Center library.

Submission details: You should submit a single softcopy (electronic) and hardcopy (paper) solution packet to these problems. See the individual problems for details about what should be submitted for that problem. Your hardcopy solution should begin with a cover sheet that can be found here.


Mancala

The problems on this assignment all involve creating a graphical user interface (GUI) for the game of mancala. Mancala is an ancient game that is widely played throughout the world, but is especially popular in Africa. There are many variants of the game. Here we describe one of the most popular forms. (The February 1998 issue of Natural History magazine has an interesting article on bao, a game in the mancala family.)

Mancala Rules

Mancala is a two player game. Being Java programmers, we will refer to the two players as Player0 (P0) and Player1 (P1). Below is a crude depiction of a mancala board:

P0: mancala

P0: bin 1

P0: bin 2

P0: bin 3

P0: bin 4

P0: bin 5

P0: bin 6

P1: mancala

P1: bin 6

P1: bin 5

P1: bin 4

P1: bin 3

P1: bin 2

P1: bin 1

The board consists of 12 small wells (we will call them "bins") and two large wells (called "mancalas") that can contain stones. Each player "owns" 6 bins on one side of the board and one mancala, as shown above. The yellow bins belong to P0 and the red bins belong to P1. The bins belonging to a player are numbered from 1 to 6 in increasing distance from the associated mancala. (The number of bins per player need not be 6. Later we will consider variants of the game in which the number of bins per player can be determined at the start of each game.)

The game begins by placing the same number of stones (typically four) in each of the bins. Play involves moving stones in a counterclockwise direction around the board. The goal of the game is to end up with more stones in your mancala that your opponent.

We will assume that P0 always moves first. A player moves by picking up all of the stones in one of her bins, and distributing the stones one at at time in a counterclockwise fashion around the board starting at the bin or mancala to the right of the chosen bin until all stones have been distributed. The player puts stones into her own bins and mancala and into her opponent's bins, but she never puts a stone into her opponent's mancala.

If the last stone is placed in the player's mancala, the player moves again without the other player taking a turn. Otherwise, the player's turn ends, and the next player takes her move.

If the last stone is placed in an otherwise empty bin belonging to the player, both that stone and all stones in the opponent's bin immediately opposite the previously empty bin are moved to the player's mancala. The player's turn ends as usual in this case.

Moves alternate between the two players until a player is faced with all empty bins at the beginning of her move. At this point, the opponent puts all stones on her side of the board into her mancala, and the game ends. The winner is the player with the most stones in her mancala at the end of the game. It is not always a good idea to be the first player to go out, since your opponent gets to keep all stones on her side at that point.

A Text-Based Mancala Program

The Mancala folder in the CS230 download folder contains several files relevant to this assignment. The file Mancala.java defines an abstraction for a mancala game. The documentation of the interface to this class appears in Appendix A.

Additionally, the static main method of the Mancala class executes a text-based interface to a program that plays mancala. You should play with this program before starting the rest of the assignment. When you double-click on Mancala.class, you will be prompted for various pieces of information; it is helpful to reposition your stderr widow above the stdin window and your stdout window below the stdin window in order to be able to view all relevant information at the same time.

In particular, you will be prompted for:

  1. The number of bins per player (6 is traditional).
  2. The number of stones initially in each bin. 4 is traditional, but for purposes of initial testing you probably want a smaller number.
  3. A strategy for Player0. There are four choices, numbered 0 through 3:
    1. The Ask User strategy asks the user to select which of Player0's bins to move.
    2. The Random strategy picks a random non-empty bin of Player0.
    3. The Low strategy picks the non-empty bin of Player0 with the lowest index.
    4. The Again strategy attempts to pick a move that will allow it to take another turn. If there is more than one such move, it chooses the one with the smallest index. If there is no such move, it defers to the Low strategy.
  4. A strategy for Player1. It is chosen from the same list as the Player0 strategy.

After entering the above information, the mancala game will begin. If both strategies are computer strategies (i.e., they are not Ask User), then the game will run by itself until one player wins. Any time a player with the Ask User strategy has a move, you will be prompted to select a non-empty bin of that player to move.

The core of the text-based interface to the mancala program is the following play method, which can be found in Mancala.java. This method uses many of the methods in the Mancala programming interface documented in Appendix A. (Note: a programming interface tells you how to use a black-box abstraction. It is very different from a user interface, which lets you interact with a program.) You should study the play method and the documentation in Appendix A before proceeding. You will have to have a good understanding of the Mancala programming interface in order to implement Video Mancala.

	public static void play (int bins, int stones, Strategy s0, Strategy s1) {
		Mancala board = new Mancala(bins, stones, s0, s1);
 
		System.out.println(board);
		while (! board.isGameOver()) {
			int currentPlayer = board.currentPlayer();
			System.out.println("Player " + currentPlayer + "\'s move.");
			int bin = board.move();
			System.out.println("Player " + currentPlayer + " selects bin " + bin + ".");
			System.out.println(board);
		}
		// currentPlayer cannot move, so game is over.
		// Move all of other player's stones to here Mancala.
		System.out.println("Final board configuration:\n");
		System.out.println(board);
		if (board.getBin(0,0) == board.getBin(1,0)) {
			System.out.println("The game ends in a tie!");
		} else if (board.getBin(0,0) > board.getBin(1,0)) {
			System.out.println("Player0 wins!");
		} else {
			System.out.println("Player1 wins!");
		}
	}

A Video Mancala Program

The text-based mancala program is awkward to use. An alternative graphical user interface to mancala, which we shall call Video Mancala, can be tested by running the applet in VideoMancalaTest.html. Note: The Mancala folder contains the compiled version (.class file) of the VideoMancalaTest class but it does not contain the source code (.java file). Your goal in this problem set is to write source code for a program with the same look and feel as the VideoMancalaTest applet.

Here are a few notes on running the Video Mancala applet. The initial layout of the applet is as follows:

The green panel contains a button that starts a new game, plus parameters for the new game. The names "Player0" an "Player1" initially in the text fields can be replaced by the names of the two players. The strategies for the players can be chosen via the pull-down choice box, which allows the same four strategy choices as the text-based program. The initial number of stones per bin is specified by selecting a number in a list of numbers from 1 to 10; the initial value is 3.

The cyan area is used to give the user feedback about the game.

The gameboard itself appears in the bottom half of the window. The two sides have the names of the two players. The mancalas are inactive labels, while the bins are represented by buttons. Initially, all buttons are disabled (greyed out) and cannot be selected. For now your should ignore the buttons labelled "Next Move" and concentrate on the buttons numbered "0".

Warning: the disablement mechanism in our version of Java is somewhat flaky. Note that the text in the mancalas, as well as the "Player1" label, are also greyed out. This is not intentional. In fact, there is nothing in my program that requests for these elements to be greyed out. I tried for several hours to pinpoint exactly what was greying out this elements, but was unsuccessful. The moral of this story is that you should not be surprised or upset if some of your labels are unintentionally greyed out. Just leave them that way. (This warning applies only to labels. All your buttons should be disabled and enabled correctly.)

Suppose we name our players "Abby" and "Georgia", give both of them the Ask User strategy, and choose 3 stones per bin. Then pushing the New Game button changes the board area as follows:

Abby's buttons are now enabled because it is her turn to go (play always begins with Player0). You can now select any of the bold buttons to indicate Abby's move. Suppose we select the button at index 3 from the left. According to the rules of mancala, we should place one stone in Abby's bin 2, bin 1, and her mancala. Because the last stone is place in Abby's mancala, she gets to move again. This is indicated by the fact that the buttons for her bins are still enabled (except for the disabled 0 button, which would be an illegal move).

Selecting Abby's bin 6 yields the following results. Note how the feedback area indicates who took how many stones from what bin. The feedback area should have this information after every move, regardless of the strategy involved. Since Abby's turn is over, her bin buttons are now disabled, and Georgia's bin buttons are enabled. (Side note: by now, many, but not all, of the greyed out labels are no longer greyed out. I have no explanation for why this is the case. Again: you should not worry if you observe this behavior in your program.)

Georgia can now select a bin, such as bin 3:

Play continues in this fashion until either (1) one player acquires more than half the stones in her mancala, in which case she wins, or (2) the player that is supposed to move cannot move because no stones are in here bin. This also ends the game, but the blocked player is not necessarily the winner. The other player puts all the stones on her side into her mancala, and the winner is judged by the mancala with the most stones.

The only other major feature of the program that needs explanation is the computer-based strategies (Random, Low, and Again). Suppose we specify that Player0 should use the Low strategy and be named HAL. Pushing the New Game button yields the following window. Note that none of Hal's bin buttons are enabled. This is because we will not be choosing the bin; instead, the strategy will automatically choose the bin. The Next Move button for HAL is enabled. This is always the case when it is a computer strategy's turn to move. Pushing the Next Move button causes the player to move with the bin selected by the strategy.

 

After HAL's move, it is Georgia's turn. Since Georgia is a human (i.e., she uses the Ask User strategy), her bin buttons are enabled, not her Next Move button. But if Georgia were a computer strategy, the opposite would be true.

After Georgia makes her selection, it is HAL's move again, so his Next Move button is enabled.

Play continues in this fashion until one player wins.


Problem 1: Video Mancala Layout

Your first task in this assigment is to implement the layout of the Video Mancala applet so that the applet window appears like the first image above when you invoke the applet. To do this, you will flesh out the skeleton for the init() method in the file VideoMancala.java within the Mancala folder. You will want to declare many of your user interface components as instance variables. In fact, you must declare such a component as an instance variable if you want to use it elsewhere in your program.

It is possible to determine the decomposition of the interface into components from its appearance. However, there are many ambiguities when this method is used. To avoid such ambiguities, below is an explicit summary of how the user interface should be decomposed. Your goal in this problem is to implement this decomposition.



 Notes:


Problem 2: Creating New Games

Your second task is to make your VideoMancala applet create new games in the same manner as the VideoMancalaTest applet. That is, pressing the New Game button should label the sides of the board with the players names and initialize the bin buttons with the appropriate number of stones. Don't worry yet about disabling any of the components.

Here are some highlights about some of the things you should do to accomplish this task:


Problem 3: Making Ask User Work

Your third task is to make your VideoMancala applet correctly implement the Ask User strategy. In fact, for the purpose of this part, you should ignore whatever strategies the user chose when creating the game and instead assume that both players use the Ask User strategy.

The goals of this part are to (1) enable exactly those buttons that correspond to legal moves of the current player; (2) carry out the appropriate move on the underlying Mancala instance when an enabled button is pressed; and (3) stop the game (printing out a win/lose/tie message in the feedback area) when the game has ended. Again, you should study the public static void play() method in the Mancala class as an example of code that interfaces with a Mancala instance.

For goal 1, helpful methods include:

The hard part about goal 2 is figuring out which of the bin buttons hass been pressed. The problem is that they are not distinguished by their labels, so you must actually rely on testing for equality with the object itself. It is recommend that you include the following code in your action method to handle this case:

   else if (evt.target instanceof Button) {
	binButtonAction((Button) evt.target);
   } else ...

The instanceof construct indicates whether an object is an instance of a class. The (Button) cast is needed to make the typechecker happy. A stub of the binButtonAction method is included in VideoMancala.java. You should flesh it out to enumerate the buttons to determine which button is == to the one in the event. When you determine the button that was pressed, you should also know its index, so you should be able to update the underlying Mancala index appropriately. For goal 2, helpful methods include:

For goal 3, helpful methods include:

Again, always feel free to write any auxiliary method definitions that you find helpful.


Problem 4: Making Other Strategies Work

Your final task is to implement the three computer-based strategies. Recall that these strategies use the Next Move buttons next to the names of the players. Among the helpful methods for this part are:


Appendix A: API for the Mancala Class

public Mancala (int bins, int stonesPerBin, Strategy s0, Strategy s1)
Create a Mancala game. The game will be played on a board with bins bins per player, each of which initially has stonesPerBin stones. Player0 will play with strategy s0 and Player1 will play with strategy s1. The game "knows" all the rules of Mancala. The state of the game can be queried and stepped forward by using the instance methods below.

public int getBins()
Returns the number of bins per player.

public int getStonesPerBin()
Returns the number of stones initially in each bin.

public int getTotalStones()
Returns the total number of stones in the game.

public int stonesMoved()
Returns the number of stones moved during the last move. If no move has yet been made, returns 0.

public int currentPlayer ()
Returns 0 if Player0 has the next turn, and 1 if Player1 has the next turn.

public boolean isCurrentPlayerHuman ()
Returns true if the current player needs human input to determine a move -- i.e., if the strategy of the current player is Ask User. Note: this is not used by text-based interface, but is needed by the video interface.

public int getBin(int player, int bin)
Returns the number of stones in the bin numbered bin of player player. Bin number 0 is the player's mancala.

public int getBin(int bin)
Returns the number of stones in the bin number bin of the current player.

public boolean isGameOver ()
Returns true if the game is over. This happens when either (1) one player has more than half of the total stones in her mancala; or (2) current player cannot move.

public void move (int bin)
Performs the basic Mancala move: removes stones from the specified bin of the current player, and and places them around board. If the last stone is placed in an empty bin on the current player's side, that stone and opposing stones are placed in player's mancala. If last stone goes in player's mancala, current player stays the same and so goes again. Otherwise, current player becomes other player. Bin should be a bin index for current player that holds one or more stones.

public int move ()
Invokes strategy of current player to determine which bin to select, and makes a move with that bin . Returns the number of the bin selected.

public String toString ()
Return a string-based representation of this game.