# Bingo Game Lab

For week two, you wrote a program that put the letters on a grid so that it resembled a Bingo Card. In this lab and follow-up programming project you will implement a working Bingo Game from an existing skeleton.

What is the game of Bingo?
The rules of Bingo are quite simple. A Bingo game consists of a series of rounds. Within each round, a caller repeatedly pulls numbers, in the range from 1 to 75, from a contraption similar to lottery ball holders. He or she puts the number up on a screen, then calls out the number. Players have a certain number of seconds to find the number on their Bingo cards. Each card has a random selection of numbers. The "B column contains random numbers between 1 - 15, the "I" column has numbers between 16 - 30, the "N" column has numbers between 31 - 45 (with a free space in the center), the "G" column has numbers between 46 - 59, and the "O" column has numbers between 60 - 75. When a player finds a matching number on their card, they mark it as found (for example, with a marker or pen). Whoever is the first to fill a complete line of numbers on their card, whether horizontally, vertically, or diagonally, yells "BINGO!" loudly and wins the round. Then everyone clears their cards (or takes new cards), and a new round starts.

The skeleton program provided for this lab creates a graphical user interface for a Bingo Card (without the "BINGO" column headings), fills the card with some numbers, and then chooses 5 random numbers and looks for them on the card. It "marks" each number it finds on the card by changing its color.

The program needs several enhancements to act like a real Bingo game. One problem is that the card should be initialized with a different set of random numbers every time the game is played; instead, this version places the same pre-defined numbers in each column every time. This is one of the improvements you will make in the follow-up programming project. The focus of the lab will be on a more important problem: the "game" currently consists of calling out only 5 random numbers, whereas it should continue to call out random numbers until there is a winning Bingo pattern on the card. (A real game with multiple cards would continue until one of the cards has a winning pattern, but our game has only one card.) There are a variety of patterns that could be considered a winning pattern in Bingo, such as a complete row of marked numbers, a complete column of marked numbers, marked numbers in the four corners, etc. Each of these could be considered a separate strategy for winning.

#### Lab: Defining and Implementing Interfaces, Using the Strategy Design Pattern

In this lab you will create an interface for classes that implement different winning strategies, and then create two strategy classes. In the follow-up programming project you will implement additional winning strategies and make several other improvements to the program.

Become familiar with the program.

• Download and unzip the BingoGame zip file. Open the project and run it several times, comparing its behavior with the description above. (You can get the effect of running it multiple times just by repeatedly clicking on the `Play` button.)
• The skeleton program from which you will start consists of 5 classes. Look at the source code for the `BingoGameApp`, `BingoGame`, and `BingoCard` classes, and the class documentation for the `BingoValueCell` class.

• `BingoGameApp`: contains the `main` method, which merely creates an instance of the `BingoGame` class.
• `BingoGame`: creates a `BingoCard` object and a `BingoGUI` graphical user interface. The game object also provides the code that is executed when the user clicks on the `Play` button. Find the code that causes the program to choose 5 random numbers and then stop, which is one of the segments you will be modifying. By the end of lab, you will also write code to be executed when the user clicks on the existing `CompleteRowWins` strategy button or a new `CompleteColumnWins` strategy button.
• `BingoCard`: a `BingoCard` object is a `Grid` object with a number of extra methods for initializing the numbers on a card (you will modify these later as part of the follow-up programming project), and finding and marking called numbers.
• `BingoValueCell`: this class is very similar to the `TextCell` class, but allows programmers to change the color of the object in the cell after it has been constructed, which `TextCell` does not allow.
• `BingoGUI`: this graphical user interface is similar to the `GridPlotterGUI` graphical user interface, in that it provides color choosers and action buttons that allow the user to direct the behavior of the game.

Create a `WinningStrategy` interface.

• Create a WinningStrategy interface with the two methods below. Make sure to document your interface and its methods with appropriate javadoc comments.

• `description`: a method that takes no parameters and returns a `String` with a strategy description.
• `isWinner`: a method that takes a `BingoCard` object as a parameter and returns `true` or `false`, depending on whether the strategy detects that the card has a winning Bingo pattern.
• You cannot really test your interface in a meaningful way until you create your first class that implements it, but you can test that code using it will compile. For temporary testing purposes:

• Create a new `WinningStrategy` instance variable in the `BingoGame` class. You won't be able to initialize it yet, but you can test that the declaration compiles.
• Create a new method in the `BingoGame` class that prints the strategy instance variable's description, and returns `true` or `false` depending on whether the strategy's `isWinner` method returns `true` or `false`. Test your temporary method and the `WinningStrategy` interface by compiling your code. (Stop and Think: Why is compiling your code enough of a test? What will happen if you run the program? Run it to confirm your prediction.)
• Delete your temporary test method.

Implement a `WinningStrategy` class.

• Create a class that implements the `WinningStrategy` interface. Objects of this class will not have any state, so the class won't have any instance variables and does not need to have a constructor either. (When you leave the constructor out, Java provides a default zero-parameter constructor that just constructs the object itself.) Eventually this strategy should test for a row with all values marked (any row), but for now just have your `isWinner` method always return `true`. Give your class a meaningful name and description (based on its eventual behavior, not its current behavior). Make sure to document your class and its methods with appropriate javadoc comments. Make sure your class compiles.
• As a quick, initial test of your class, update the `BingoGame` constructor to initialize your strategy instance variable to an object of your new class. Compile and run your program, comparing your expected and actual results. (Stop and Think: What do you expect the behavior of the program to be?)
• Next modify the `reportStrategies` method to print your new strategy's description rather than "none." Compile and run your program, comparing your expected and actual results.
• Modify the `gameOver` method and the loop in `onPlayButtonClick` to loop continuously until there is a winning row on the card. (Stop and Think: What modification should you make to the `gameOver` method? Once you have decided on that, think about what modification you should make to the `onPlayButtonClick` method. ) Compile and run your program, comparing your expected and actual results. (Stop and Think: Since your strategy returns `true` the very first time it is called, what do you expect the behavior of the program to be? Play the game multiple times to confirm your expectation.)
• Modify your new class to implement the correct strategy: test for a row with all values marked (any row). You may find the `getCellAt` method in the `BingoCard` class and the `isMarked` method in the `BingoValueCell` class useful. Compile and run your program, playing multiple games to make sure that your program acts as you expect. (You may wish to adjust the speed of the program, since it may often take between 30 and 130 called numbers before the game is won.)
• Once your program continues until the game is won, change the final printed statement to say "Took X called numbers to win." (where X should be the appropriate number) rather than "Played X numbers." Test this modification.
• Add the method below as an extra method to your new class, replacing `WinWithMarkedRow` with whatever name you gave your class. This method will cause any two objects of this strategy class to be treated as equal. (This method will be useful in the future.)
```    public boolean equals(Object obj)
{
if ( obj instanceof WinWithMarkedRow )
return true;
return false;
}```

Implement a second `WinningStrategy` class.

• Create a second class that implements the `WinningStrategy` interface. (Once you have created a new, generic class, you can copy and paste the contents of your first strategy class into it.) This strategy should test for a column with all values marked (any column). Give your class a meaningful name and description, and update the `equals` method to test for the correct class type. Make sure to document your class and its methods with appropriate javadoc comments. Make sure your class compiles.
• As a quick, initial test of your class, modify your `BingoGame` constructor to initialize your strategy instance variable to an object of your new class. Compile and run your program, playing multiple times to verify that a win consists of a completely marked column rather than a completely marked row.

Support wins based on multiple strategies.

• In order to allow users to choose the strategies to use for winning the game, replace your single-strategy instance variable with an `ArrayList` of registered or chosen strategies. (Stop and Think: Why is it important to use the `WinningStrategy` interface when creating your list rather than one of your strategy classes?) Construct the list in the `BingoGame` constructor and, for now, initialize it to contain an object of each of your strategy classes. Modify the `reportStrategies` method to report on all strategies in the list (however many there may be). Modify the `gameOver` method to return `true` when any strategy in the list identifies a win.
• Compile and run your program, playing multiple times to verify that a completely marked row or a completely marked column represents a win.
• Uncomment the `toggle` method in the `BingoGame` class. If you didn't name your strategy list `registeredStrategies`, modify the method to use your instance variable name. Modify the `OnCompleteRowWinsButtonClick` method to call the toggle method, passing it a newly-constructed object of your row-wins strategy class. (The reason you added the `equals` implementation provided above to your strategy classes is so that the `ArrayList` `remove` method will recognize a newly-constructed strategy object passed to `toggle` as a parameter as equivalent to an existing strategy object of the same type in the list, if there is one.) Finally, modify the `BingoGame` constructor so that it constructs an empty list, without adding any strategy objects to it. Users will now choose which strategy or strategies to use by clicking on the appropriate button.
• Compile and run your program, clicking on the `CompleteRowWins` button before the `Play` button. Verify that the program acts as you expect it to.
• Once your program works correctly for the row-winning strategy, add a new `onCompleteColumnWinsButtonClick` method to the `BingoGame` class, calling the `toggle` method with a newly-constructed object of the appropriate class. Compile and run your program. If you named your new method correctly, you should see a new button created automatically on the graphical user interface. Play the game multiple times, changing which strategies you use each time. (Note that each time you click on a strategy-choosing button it either adds that strategy or removes it from the list of strategies to use.) Make sure that you test it several times using just the row-winning strategy, several times using the column-winning strategy, and several times using both strategies. See the picture below for an example of sample output from the various `System.out.println` statements in the program. (Stop and Think: What would you expect to happen if you play the game with no registered winning strategies? Test it once to see what happens.)
• To protect your program from the possibility of running with no winning strategies available, add code to the `onPlayButtonClick` method (just before the call to `reportStrategies`) that adds both of your basic strategies to the list if it is empty. Test your program without registering any strategies and confirm that it runs with both strategies in effect.