<<Previous | ToC
| Next >>
"ThreeInaRow"Then we add eight calls to this subroutine to our "Test for win" subroutine. Here is the first and last:
won = false
if board[first]=who
if board[mid]=who
if board[last]=who let won = true
Done
"Test for win"
print "Test for win"
let first = 1
let mid = 2
let last = 3
ThreeInaRow
if won exit
...
let first = 3
let mid = 5
let last = 7
ThreeInaRow
if won exit
Done
let prms = 123Then unpack them inside the subroutine -- you can do this in English but not Java, but we can pass separate parameters there, so it's not a problem:
ThreeInaRow
if won exit
...
"ThreeInaRow"
let won = false
Substring first = prms,0
Substring mid = prms,1
Substring last = prms,2
While I'm doing this in English, I might as well get rid of the
non-English array notation "board[first]" for testing in English,
which I can translate as "Substring tmp = board,first" (read this
as "skip over first characters of board, then take (default
one) character and put it into tmp"). Or maybe better:
"ThreeInaRow"In Java all that would be one line -- or maybe just eliminate the ThreeInaRow subroutine entirely, because each call would be replaced a single line in the Java code for the "Test for win" subroutine -- as we shall shortly see. However, doing this out the long way (at least this once) helps us appreciate what is going on. Later we can remove the scaffolding, leaving just the finished beautiful edifice for everyone to admire.
let won = false
Substring tmp = prms,0
Substring first = board,tmp
Substring tmp = prms,1
Substring mid = board,tmp
Substring tmp = prms,2
Substring last = board,tmp
if first=who if mid=who if last=who let won = true
Done
Anyway, you can fill in the rest of the ThreeInaRow calls in the "Test for win" subroutine -- I did it with copy & paste, then adjusted the three numbers (now a single 3-digit number); you can do that, right? -- then (if you are so inclined) test it in English.
If you did that, you probably noticed that it didn't run at all, because I/we used "exit" to get out of the subroutine, but in English it means get out of an iteration, and (guess what?) there's no iteration to get out of. So I'm going to let you in on a programming trick I use often -- you don't need it here when you do this in Java, because you can use "return" to get out -- but it's a very useful tool anyway, for situations where you have more processing to do before you leave the subroutine, and that is that we wrap an iteration around a large chunk of code that we might want out of early, several times (if only once, use an ordinary conditional), in this case the whole subroutine, but tell the iteration to run only once. Then all those exits get out of the iteration early, but not out of the subroutine
"Test for win"
print "Test for win"
Repeat 1
let prms = 123
ThreeInaRow
if won exit
...
if won exit
Next
Done
Now it takes your input and displays the updated board, then notices
if somebody won, just like we wanted. Are we finished? What happens if
X (or O) tries to play on top of a square that has already been played?
Or if they try to play some non-existing square? A good program needs to
test for input errors. Sometimes we also test for errors in the variables
the computer calculated, just in case there's a bug that gave a wrong result.
But the program has no control over the user input, except to reject it
and request a replacement -- or if that's not possible, at least report
the error so the user can fix the data.
Why don't you try adding an input error check yourself, before you turn the page.
<<Previous | ToC | Next >>
Revised: 2022021 August 30