Programming Tic-Tac-Toe in Java


<<Previous | ToC | Next >>
 

Three-In-a-Row Details

Here's my English for ThreeInaRow:
"ThreeInaRow"
  won = false
  if board[first]=who
    if board[mid]=who
      if board[last]=who let won = true
  Done
Then we add eight calls to this subroutine to our "Test for win" subroutine. Here is the first and last:
"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

When we do this in Java it will be one line each call, because we can use parameters. English has no such thing, so it's a little more tedious than it needs to be. In English -- this would be less perspicuous than plain English English, but also more compact and maybe even easier to read (which is important) -- I can pack those three numbers into one, then take it apart inside the subroutine:
let prms = 123
ThreeInaRow
if won exit
...
Then 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"
  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"
  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
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.

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