Tic-Tac-Toe

Tags: short, boardgame, game, twoplayer

Tic-tac-toe is a classic pencil-and-paper game played on a 3 × 3 grid. Players take turns placing their X or O marks, trying to get three in a row. Most games of tic-tac-toe end in a tie, but it is possible to outsmart your opponent if they’re not careful.

tic-tac-toe.py
 1"""Tic-Tac-Toe, by Al Sweigart al@inventwithpython.com
 2The classic board game.
 3This code is available at https://nostarch.com/big-book-small-python-programming
 4Tags: short, board game, game, two-player"""
 5
 6ALL_SPACES = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
 7X, O, BLANK = 'X', 'O', ' '  # Constants for string values.
 8
 9
10def main():
11    print('Welcome to Tic-Tac-Toe!')
12    gameBoard = getBlankBoard()  # Create a TTT board dictionary.
13    currentPlayer, nextPlayer = X, O  # X goes first, O goes next.
14
15    while True:  # Main game loop.
16        # Display the board on the screen:
17        print(getBoardStr(gameBoard))
18
19        # Keep asking the player until they enter a number 1-9:
20        move = None
21        while not isValidSpace(gameBoard, move):
22            print('What is {}\'s move? (1-9)'.format(currentPlayer))
23            move = input('> ')
24        updateBoard(gameBoard, move, currentPlayer)  # Make the move.
25
26        # Check if the game is over:
27        if isWinner(gameBoard, currentPlayer):  # Check for a winner.
28            print(getBoardStr(gameBoard))
29            print(currentPlayer + ' has won the game!')
30            break
31        elif isBoardFull(gameBoard):  # Check for a tie.
32            print(getBoardStr(gameBoard))
33            print('The game is a tie!')
34            break
35        # Switch turns to the next player:
36        currentPlayer, nextPlayer = nextPlayer, currentPlayer
37    print('Thanks for playing!')
38
39
40def getBlankBoard():
41    """Create a new, blank tic-tac-toe board."""
42    # Map of space numbers: 1|2|3
43    #                       -+-+-
44    #                       4|5|6
45    #                       -+-+-
46    #                       7|8|9
47    # Keys are 1 through 9, the values are X, O, or BLANK:
48    board = {}
49    for space in ALL_SPACES:
50        board[space] = BLANK  # All spaces start as blank.
51    return board
52
53
54def getBoardStr(board):
55    """Return a text-representation of the board."""
56    return '''
57      {}|{}|{}  1 2 3
58      -+-+-
59      {}|{}|{}  4 5 6
60      -+-+-
61      {}|{}|{}  7 8 9'''.format(board['1'], board['2'], board['3'],
62                                board['4'], board['5'], board['6'],
63                                board['7'], board['8'], board['9'])
64
65def isValidSpace(board, space):
66    """Returns True if the space on the board is a valid space number
67    and the space is blank."""
68    return space in ALL_SPACES and board[space] == BLANK
69
70
71def isWinner(board, player):
72    """Return True if player is a winner on this TTTBoard."""
73    # Shorter variable names used here for readablility:
74    b, p = board, player
75    # Check for 3 marks across 3 rows, 3 columns, and 2 diagonals.
76    return ((b['1'] == b['2'] == b['3'] == p) or  # Across top
77            (b['4'] == b['5'] == b['6'] == p) or  # Across middle
78            (b['7'] == b['8'] == b['9'] == p) or  # Across bottom
79            (b['1'] == b['4'] == b['7'] == p) or  # Down left
80            (b['2'] == b['5'] == b['8'] == p) or  # Down middle
81            (b['3'] == b['6'] == b['9'] == p) or  # Down right
82            (b['3'] == b['5'] == b['7'] == p) or  # Diagonal
83            (b['1'] == b['5'] == b['9'] == p))    # Diagonal
84
85def isBoardFull(board):
86    """Return True if every space on the board has been taken."""
87    for space in ALL_SPACES:
88        if board[space] == BLANK:
89            return False  # If any space is blank, return False.
90    return True  # No spaces are blank, so return True.
91
92
93def updateBoard(board, space, mark):
94    """Sets the space on the board to mark."""
95    board[space] = mark
96
97
98if __name__ == '__main__':
99    main()  # Call main() if this module is run, but not when imported.

https://inventwithpython.com/bigbookpython/project76.html