Solution (source code)

= Solution

Keep the same player until an occupied, in-range cell is supplied:
``
val board = new Chomps(6)
var player = 1
while (board.Count() > 0) {
  board.Display()
  var x = -1
  var y = -1
  while (!board.Legal(x, y)) {
    println("Player " + player + ": enter x, then y")
    try {
      x = scala.io.StdIn.readInt()
      y = scala.io.StdIn.readInt()
    } catch {
      case _: NumberFormatException =>
        x = -1
        y = -1
    }
    if (!board.Legal(x, y)) println("Choose an occupied cell")
  }
  board.Move(x, y)
  if (board.Count() == 0)
    println("Player " + player + " loses; player " + (3 - player) + " wins")
  else player = 3 - player
}
``
The outer <loop invariant> is that `player` is the next player's number, either one or two, and the board is the result of the accepted moves. The inner <loop invariant> says that the board and player have not changed; rejected inputs do not consume a turn. Assuming the input source continues and eventually supplies a legal coordinate pair, the inner loop finishes. No program can guarantee that a user stops entering illegal moves, so that interaction assumption is necessary.

Every accepted move removes at least its selected token, so the outer <loop variant> is `Count()`, a decreasing nonnegative <integer>. In a nonempty <order ideal>, $(0,0)$ is occupied. Removing it removes the entire board, whereas a move at any other cell leaves it. Therefore \b[the player making the final move is exactly the loser]; the code reports that player before changing the turn. At most $36$ legal moves occur.