top of page

The Python program runs a session of tic-tac-toe that can be played on the command line, displaying the game board after each move made. The program can be found here. Some screenshots of the game in progress are shown below. There is also a video below to give a brief overview. More details about the capabilities of the program and its implementation are given below too.

This was a Python program to run games of tic-tac-toe on the command line. The program consists of 3 scripts. There is the main game_runner script that acts as an entry point for the program, the tic_tac_toe script that handles the game itself and test_tic_tac_toe, which runs a suite of test cases relating to the program. The game uses a 3X3 board to play, and when a player wins the game (or if there is a draw) the user is prompted to play another game. When a game is in progress, the board is displayed on the command line after each new move has been made, with its existing state.  By default, the game starts with player X, and prompts the player to enter a move on the board. The program expects a specific format to be entered in order to process a move. It expects a number followed by a space followed by another number, to represent the row and column to populate on the board. The expected value for the row or column is an integer between 1 and 3, and the program reads from the top left of the board.

The program uses input handling to ensure that an entered move is valid and can be used. If the user enters the wrong format for a move (i.e. if only one number is entered or the delimiter is an underscore instead of a space), the program will display the following and prompt again for an input “The input must be a row value followed by a space followed by a column value”. If the user enters values other than positive integers (i.e. a float value or a string), the program will display the following and prompt again for an input “The row/column must be an integer value”. In this case, the message will display row or column depending on the first value that it detects as invalid. If both are invalid it will defer to the row. If the user enters values that are out of range of the board (less than one or greater than 3), program will display the following and prompt again for an input “The row/column must be a value between 1 and 3”. Likewise, row or column will be displayed depending on which part of the input is out of range. Finally, if the game is in progress and a player enters a position on the board that has already been entered, program will display the following and prompt again for an input “the move has already been made”.

If a session of the game is finished (either a player has successfully drawn a line across the board or there are no positions left on the board), the program will prompt the user to play again. If the player enters ‘N’ or ‘n’, the program will exit, but if the player enters ‘Y’ or ‘y’ a new session of the game will begin. Input handling also exits here to ensure that one of the above values gets entered. If any other input is entered, the program will display the following and prompt again for a valid input “Value must be ‘Y’ or ‘N’. Before the new session begins, the program will also give the user the option to play against the AI. ‘N’ or ’n’ results in the same type of session, but if ‘Y’ or ‘y’ is entered, then the AI will play as player O (input handling exists for this prompt also). In this case, player X starts. However, once a valid move has been entered, player O will automatically enter a move (“Player O has entered a move in row x and column x”) and the new board state will be displayed. Once the game session is finished, the player will again be prompted whether to finish the program and when to play against the AI.

The program was designed modularly, separating various aspects into separate functions. There are functions to compute a valid move for the AI, to work out whether the current state of the game is still in play or finished, to check if a user input is valid, to convert a move input to a valid format for the program, to set a move on the board and to reset the board state before a new session. The board state is stored as a list of 9 values, which can be either ‘X’, ‘O’ or None. There is also a visual representation of this board stored in order to be displayed in the game when a valid move is made.

The game itself runs in an indefinite loop. This loop only breaks and the program only exits if the player specifies to exit at the end of a session of the game. Before each move, the program checks that the current state of the board is still in play. If so, an input is prompted for (or generated if the current player is the AI) and its validity is checked. Once a valid move is entered, the move list is updated and the board display is updated and printed. The current move is also displayed by converting the index of the current position recently updated in the move list to a row and column value. If, before a move, the program realises that the game session is over, it checks whether or not the game is a draw and displays the valid result. This is when the player is prompted whether or not to exit the loop and whether or not to specify that the new game is against the AI.

The AI is basic, generating moves on the board at random. The moves generated by the AI and input by the player are checked with the is_valid function. This also checks any other input to the program. One of the input parameters to the function, input_type, specified one of 3 different types of input to validate (“move”, “replay” and “ai”). The function acts as a catch-all to ensure that any input is valid, and return false if this is not the case. Another input parameter, debug, specifies whether or not to display output statements when the input is valid. This is useful to disable when running the test suite. To work out whether the game session is still in progress, a set of winning states is used. Each winning state consists of a list of indexes in the move list. If all index in the set are the same value, and they are not None (i.e., they are “X” or “O”), then a player has won the game. Otherwise, if all the moves in the move list have a value that is not None, then the game is a draw. If neither cases exit, then the game is still in progress.

The test_tic_tact_toe script runs 14 tests that test different valid and invalid inputs, AI generated moves and different states of the game when it is in progress and finished. This provides some level of robustness for the main program. The unittest Python module was used to generate these tests, which provides a visual display when run to inform which of the tests have passed successfully and which haven’t.

bottom of page