<<Previous | ToC
| Next >>
Since we are looking for only one of two marks (X or O) we can do the counting by making those marks to be +1 and -1 (with unplayed locations =0), then just adding the three cells and return true if the sum is +3 or -3. That would be very efficient, but not very perspicuous.
The most obvious implementation, which is favored by Unix programmers
because of that, is to make everything text (as I did in English) and then
compare the characters in those positions. If you want to do that, then
your game board should be an array of type char (not int).
Then your Java code will look very much like my (non-English) English.
if (ThreeInaRow(who,3,5,7)) won = true;or maybe:
else if ...
won = ThreeInaRow(who,3,5,7);or even:
if (won) return true;
won = (board[3]==who) && (board[5]==who) && (board[7]==who);and eliminate ThreeInaRow as a subroutine ("method" in Java) entirely. But if you keep the method, it needs to return a boolean result (true if it found three in a row) and take the mark you are looking (who) for as a parameter of type char, as well as the numbers indexing the three cells in the row, column or diagonal being tested.
if (won) return true;
It is not obvious to you now in the small programs you are working on this month, but using parameters instead of global variables is like strong typing: it reduces the chances of undetected errors, because the parameter is set in the call and used only within the method, and cannot be accidentally altered elsewhere. Classes in Java do the same thing by eliminating global variables entirely, although "instance variables" (declared out at the class level) are like globals within the class. You always want to restrict data access to those parts of the code with (as they say in the military) "a need to know." Less unnecessary access means more robust (less easily broken) code. You want that.
Some variables need to be persistent across subroutine calls: the game
board, who is playing, stuff like that (basically everything that is initialized
in the Initialize method) you need to move them out to be class
variables (declared and possibly initialized before the first subroutine).
If you choose a 2D array, you can index the board in the display routine using the for-loop index variables for the rows and columns directly, but it won't help you at all in ThreeInaRow, you'd need to pass it both a row and column for each cell to be considered in each test. Initializing either a character or integer array with constant values can be done in the declaration with no extra code in Java (not even 2D), as we saw in the Seaman (ASCII Graphics) program.
No matter which internal representation you choose, you may need to convert between the two representations, one way or the other, because both formats are considered at one stage or the other during the program. The display routine needs to access the data by rows and columns. We linearized that with a secondary index variable step in "Iterating the Board" by carefully stepping through the board in numerical order. Otherwise we would need to do the conversion
index = row*3+column+kwhere k is some constant that depends on the starting index values of your row, column, and final index ranges. If all the ranges start at 0 (like Java and C arrays), then k=0.
The conversion the other direction is the inverse of this, but (again, you wouldn't know this) much more expensive in processing time, because the hardware people have not figured out how to do integer division as fast as addition or subtraction; multiplication can be "pipelined" which overlaps the slower multiplication steps with other instructions in the hardware for effective (but not always) single-cycle operation:
row = (index-ki)/3+kr;
column = index-row*3+kc;
After you have it working with ASCII graphics, you can stop here (perhaps browse some of the other chapters you nave not yet read), or else go on to making the same program run in the GameEngine (turn the page) or skip the GameEngine part and program the computer to play "O" intelligently.
<<Previous | ToC | Next >>
Revised: 2021 August 30