In this assignment you will implement a game to be played by a human player against the computer. The central idea is that during a player’s turn, randomly generated 9X9 grids of integers ranging from 1 through 9 will be examined for points according to point rules (given below). In each turn a player will receive two different grids. The points for that turn will be the sum of the points received for the two grids presented in this turn. After each user has three such turns, the winner will be determined and displayed. If there is a tie, another entire game will played until there is no tie.
Details of the rules and the playing of the game will now be discussed. There are also several different execution logs linked to this assignment (below). Reading through these logs will show you the flow of the game in different executions of the program. Eventually, your program output should look EXACTLY like these logs and only the random numbers in the grids would be different. So be sure to read through these logs as they are part of the requirements for this project.
The Game Flow
After the welcome message the user is asked for the human player’s name to be used in the game’s output. Then, before the first turn begins, the console output is held until the user presses the ENTER key. Do not use an operating system-dependent call for this. Rather use interactive input to accomplish this:
System.out.print(“Press ENTER to continue. . .”);
keyboard.nextLine(); // keyboard is a Scanner object
You can see the effects of this in the log. In general this is used so that the program doesn’t output too much of the game until the user is ready.
When ENTER is pressed at this point in the game, the first turn begins in which the human and the computer each get their turn. The human always plays first and the computer always plays second in each of the game’s three turns.
During each turn the player is presented with a total of two grids followed by a listing of the points scored for each grid. You can see how the grids are displayed and how the scored points are listed after each grid. Your program is required to display this information in the same format. Note that the grids are displayed showing the column and row numbers, as well as the number of horizontal points scored on each of the nine rows. This is done to help the user decide which row, if any, to regenerate (see below).
Once the three turns for each player have been completed, a display tells the user who the winner was (see format and wording of these messages in logs). If the game ended in a tie, another game is played. Every time a game ends in a tie, another game is played. Your design should allow for this. You should test it out by contriving the score during testing so as to simulate a tie so that you can see how your code responds.
The Human’s Turn
When the computer plays, the points are scored on each grid as it is generated. The human, however, has options after seeing each generated grid. The first option is that the human can request an entirely new grid be generated to replace the last grid displayed. For example, the human might do this if the grid just displayed scored a negative number of points. The second option for the human is to have only one specific row regenerated. If this option is chosen, 9 new random values are chosen for whichever row the users wants to replace. The user selects a row by entering the row number as 1 through 9 (NOT by entering the programmer’s subscript values of 0 through 8!). You can see this happening in several of the game logs. After the new row values are generated, the grid is re-displayed to show the new values in the chosen row and then the points scores are re-assessed and re-displayed to the player. Reading through the logs is the best way to see this happening in a game.
The human’s third choice is to accept the grid the way it was first generated. When this option is chosen, the game displays the message: “No regeneration requested . . .”. The logs show examples of this also, for example, when the original grid scores well, the player will usually choose not to regenerate any of its values.
The Grid
Each grid generated is a 9X9 two-dimensional array of integers with values ranging from 1 through 9. Each time a grid is generated it is displayed in row-major order. You will create this two dimensional array (9X9) in a method at a high level within the application and then pass it as a parameter to all methods that need to access it or change it. You should carefully note that when the grids are displayed, the display method adds the column numbers across the top of the grid, adds the row numbers to the left of each grid, and displays the points for each row after an equal sign (=) to the right of each row. Note that the column numbers, the row numbers, and the point values are NOT part of the 9X9 array that stores the random values. The method that generates a random grid always and only generates a 9X9 array. The column numbers, the row numbers, and the point values are merely added to the display by the method that displays a 9X9 grid,
Remember: you are not allowed to use global variables, i.e., variables declared in the class but outside of any methods. ALL variables should be declared inside a method.
Scoring Points
The program will need to be capable of counting four (4) kinds of points: horizontal, vertical, bonus, and rare. The points scored within a round by a grid are calculated as follows:
roundPoints = verticalPoints – horizontalPoints + bonusPoints + rarePoints
Horizontal Points
Horizontal points are scored when the same value appears in two or more adjacent cells in the same row of the grid. For example. the following row:
4 4 7 2 4 7 7 7 2
results in 29 points. There are two 4s in adjacent cells; so this is 4 (the value) times 2 (cells) for a subtotal of 8 points. There are also 3 adjacent 7s; so this is 7 times 3 for a subtotal of 21. The two subtotals yield a total of 29 points.
To determine the number of horizontal points scored by a grid, the horizontal points for each row (as described in the preceding paragraph) are added together.
Vertical Points
Vertical points are scored when the same value appears in two or more adjacent cells in the same column of the grid. For example, consider column 7 in the following grid:
v
8 1 9 8 3 7 8 5 4
5 5 6 6 2 3 8 7 3
3 1 6 8 4 6 9 8 1
7 4 7 4 4 7 8 6 1
6 3 2 9 6 2 8 8 4
3 6 4 7 5 6 8 2 1
3 2 9 1 2 8 9 2 5
6 6 4 9 9 3 2 3 8
1 7 4 5 8 8 2 7 8
^
Column 7 of this grid contains the following points:
2 adjacent 8’s (rows 1 and 2) = 18 pts: 2 * (8+1)
3 adjacent 8’s (rows 4, 5, and 6) = 27 pts: 3 * (8+1)
2 adjacent 2’s (rows 8 and 9) = 6 pts: 2 * (2+1)
Total Points for this column: 51
So, the vertical scoring is similar to the way horizontal scoring works, except that one is added to the value that appears multiple times in the column.
To determine the number of vertical points scored by a grid, the vertical points for each column (as described in the preceding paragraph) are added together.
Note that only adjacent, equal values score points.
Bonus Points
Bonus points are awarded when one of the nine random values appears 15 or more times in the grid. So, when you count the number of 1’s in the grid, if that count is 15 or higher then the bonus points are 1 * 1 (the square of the value appearing). For example, if there were 15 occurrences of 7 in a grid and 16 occurrences of 3, then the bonus points would be 49 (7 squared) plus 9 (3 squared) or 58. You can see this in several places in the example execution logs.
Rare Points
The final type of point value that can be scored adds 100 points for each time it occurs in a grid. A 100 point rare bonus is added to the points scored by a grid for each 3X3 sub-grid within it that contains all nine of the possible random values. The program will only look at nine such sub-grids. The first 3 are in the first 3 rows and each is 3 columns wide. The second 3 such sub-grids are in rows 4, 5, and 6, each being 3 columns wide. the final set of 3 such sub-grids occupies the bottom 3 rows, each sub-grid being 3 columns wide. The following grid shows exactly how each of the 9 sub-grids are divided:
1 2 3 | 1 2 3 | 1 2 3
4 5 6 | 4 5 6 | 4 5 6
7 8 9 | 7 8 9 | 7 8 9
——|——-|——
1 2 3 | 1 2 3 | 1 2 3
4 5 6 | 4 5 6 | 4 5 6
7 8 9 | 7 8 9 | 7 8 9
——|——|——
1 2 3 | 1 2 3 | 1 2 3
4 5 6 | 4 5 6 | 4 5 6
7 8 9 | 7 8 9 | 7 8 9
If the grid above were actually generated randomly (extremely unlikely, but theoretically possible!), the player would receive 900 rare points: 100 for each of the nine sub-grids since each one contains each of the 9 possible values exactly once.
Design
Your design should be modular, meaning that by reading the main method, one should see the high-level plan for doing the work of the program. Think in terms of methods that do the work for the various tasks. For example, there should be a method that generates the random grid, another method that displays a grid, another method that calculates horizontal points using a method that determines the points on a single row, etc. These are just a few of the many possible method that can be employed in accomplishing the overall task.
Do not try to get all the code in place AND THEN begin compiling and testing. Instead, decide on a small subset of tasks to implement, code them, compile them, test them. Then, when you are satisfied that the implemented parts work, add more method to get more of the requirements done. For example, 1) implement the highest level of just getting the human player’s name; 2) add to that the generation of a full 9X9 grid, 3) display that grid, 4) add a method to determine grid points, 5) have that method call a method to determine horizontal points, 6) add a call to another method to determine vertical points,7) . . . (there WILL be more steps, but this should give you an idea of how to solve one small part before moving on to solve more. When you can determine the points scored by a grid, implement a turn for just one of the players, etc. Grow your implementation a little at a time – this is the way the pro’s do it!
NOTE: As you design and implement methods for various tasks, plan on passing them what ever data they need from the caller. Plan on using in the caller whatever values the called methods return or the arrays they modify. Remember: you are not allowed to use global variables, i.e., variables declared outside of any functions. ALL variables should be declared inside a method.
When you have designed and implemented a method, make sure it does ONE, simple, easily-identified task. DO NOT burden it later by adding work to it that is not part of that one, easily-identified. task. There are approximately 12 to 15 easily identified tasks that make for great methods within this application. No method should be longer than 40 lines of code.
Example Execution Logs
Please study these logs carefully by downloading these text files and viewing them on your computer. (Note Canvas adds dots into the preview thereby distorting the display of the grids. See note at end of this page.) Reading carefully through these logs should fill in any gaps remaining in your understanding of the requirements. If not, email your question to your instructor. These logs are considered part of the requirements and your program is expected to act exactly like the program that created the logs: format, flow, wording, etc. Your program will generate different random values in filling the grids, but everything else should follow the likeness of the five logs linked below.
There are five logs linked here. A tie is simulated in LogD; bonus points appear throughout; some rare points were seen in LogE.
LogA.txtPreview the document
LogB.txtPreview the document
LogC.txtPreview the document
LogD-TIE.txtPreview the document – shows a tie game
LogE-Rare.txtPreview the document – shows rare points being scored
Canvas distorts the correct display of the grids by adding dots into the grid displays. The following picture show the Canvas-added dot on the left and the correct grid display on the right.
Canvas Distortion of Correct Grid Display