# Play TicTacToe $define E " " # empty square $define X "X" # X piece $define O "O" # O piece # -- define a board record Board(a, b, c, d, e, f, g, h, i) procedure display_board (board, player) write ("\n===============") write (board.a || " | " || board.b || " | " || board.c) write ("---------") write (board.d || " | " || board.e || " | " || board.f) write ("---------") write (board.g || " | " || board.h || " | " || board.i) end # return a set of valid moves (empty positions) in given board procedure empty_fields (board) fields := set() every i := !fieldnames(board) do if (board[i] == E) then insert (fields, i) return fields end procedure game_start () return Board (E, E, E, E, E, E, E, E, E) end procedure game_is_drawn (board) return *empty_fields(board) = 0 end procedure game_won_by (board, player) return (board.a == board.b == board.c == player) | (board.d == board.e == board.f == player) | (board.g == board.h == board.i == player) | (board.a == board.d == board.g == player) | (board.b == board.e == board.h == player) | (board.c == board.f == board.i == player) | (board.a == board.e == board.i == player) | (board.g == board.e == board.c == player) end procedure game_over (board) return game_is_drawn (board) | game_won_by (board, O) | game_won_by (board, X) end # -- players make their move on the board # assume there is at least one empty square procedure human_move (board, player) choice := "z" options := empty_fields (board) # keep prompting until player selects a valid square until member (options, choice) do { writes ("Choose one of: ") every writes (!options || " ") writes ("\n> ") choice := read () } board[choice] := player end # pick and make a move at random from empty positions procedure random_move (board, player) board[?empty_fields(board)] := player end # -- manage the game play procedure play_game () # hold procedures for players' move in variables player_O := random_move player_X := human_move # randomly determine if human or computer moves first if (?2 = 0) then { write ("Human plays first as O") player_O := human_move player_X := random_move } else write ("Computer plays first, human is X") # set up the game to start board := game_start () player := O display_board (board, player) # loop until the game is over, getting each player to move in turn until game_over (board) do { write (player || " to play next") # based on player, prompt for the next move if (player == O) then (player_O (board, player)) else (player_X (board, player)) # change player to move player := if (player == O) then X else O display_board (board, player) } # finish by writing out result if game_won_by (board, O) then write ("O won") else if game_won_by (board, X) then write ("X won") else write ("draw") # neither player won, so must be a draw end # -- get things started procedure main () play_game () end