├── README.md ├── codegenerator └── generate_ttt.py ├── generate_code_for_tictactoe.py ├── hehhehhehlizard.jpg └── tictactoe.py /README.md: -------------------------------------------------------------------------------- 1 | # my_first_tic_tac_toe 2 | My first Tic Tac Toe program. I welcome any code reviews and pull requests! 3 | 4 | ![Heh heh heh lizard](hehhehhehlizard.jpg "Heh heh heh") 5 | 6 | ... 7 | 8 | ... 9 | 10 | ... 11 | 12 | ... 13 | 14 | ... 15 | 16 | (This project is a joke.) -------------------------------------------------------------------------------- /codegenerator/generate_ttt.py: -------------------------------------------------------------------------------- 1 | # This script is... less than ideal. 2 | # It was cobbled together just to one-off generate the tictactoe.py file. 3 | 4 | # This is a Python 3 script which generates a Python 3 script. 5 | 6 | # Seriously, this code is not at all polished and I tinkered with it for a couple hours just to get it to output right. That did not improve things, code readability-wise. 7 | 8 | import logging 9 | logging.basicConfig(level=logging.DEBUG) 10 | logging.disable(logging.CRITICAL) 11 | 12 | import copy 13 | import random 14 | 15 | boardTemplate = """print('%s|%s|%s\\n-+-+-\\n%s|%s|%s\\n-+-+-\\n%s|%s|%s\\n')""" 16 | 17 | enterMoveMessage = """print('Enter the number of your move:') 18 | print(' 789\\n 456\\n 123')""" 19 | 20 | ''' 21 | boardTemplate = """print(' | | ') 22 | print(' %s | %s | %s ') 23 | print(' | | ') 24 | print('---+---+---') 25 | print(' | | ') 26 | print(' %s | %s | %s ') 27 | print(' | | ') 28 | print('---+---+---') 29 | print(' | | ') 30 | print(' %s | %s | %s ') 31 | print(' | | \\n') 32 | """ 33 | 34 | enterMoveMessage = """print('Enter the number of your move:') 35 | print(' 7|8|9') 36 | print(' -+-+-') 37 | print(' 4|5|6') 38 | print(' -+-+-') 39 | print(' 1|2|3')""" 40 | ''' 41 | 42 | # ===== start of copy-pasted tic tac toe code ======================= 43 | def isWinner(bo, le): 44 | # Given a board and a player's letter, this function returns True if that player has won. 45 | # We use bo instead of board and le instead of letter so we don't have to type as much. 46 | return ((bo[7] == le and bo[8] == le and bo[9] == le) or # across the top 47 | (bo[4] == le and bo[5] == le and bo[6] == le) or # across the middle 48 | (bo[1] == le and bo[2] == le and bo[3] == le) or # across the bottom 49 | (bo[7] == le and bo[4] == le and bo[1] == le) or # down the left side 50 | (bo[8] == le and bo[5] == le and bo[2] == le) or # down the middle 51 | (bo[9] == le and bo[6] == le and bo[3] == le) or # down the right side 52 | (bo[7] == le and bo[5] == le and bo[3] == le) or # diagonal 53 | (bo[9] == le and bo[5] == le and bo[1] == le)) # diagonal 54 | 55 | 56 | def isSpaceFree(board, move): 57 | # Return true if the passed move is free on the passed board. 58 | return board[move] == ' ' 59 | 60 | 61 | def chooseRandomMoveFromList(board, movesList): 62 | # Returns a valid move from the passed list on the passed board. 63 | # Returns None if there is no valid move. 64 | possibleMoves = [] 65 | for i in movesList: 66 | if isSpaceFree(board, i): 67 | possibleMoves.append(i) 68 | 69 | if len(possibleMoves) != 0: 70 | return random.choice(possibleMoves) 71 | else: 72 | return None 73 | 74 | def getComputerMove(board, computerLetter): 75 | # Given a board and the computer's letter, determine where to move and return that move. 76 | if computerLetter == 'X': 77 | playerLetter = 'O' 78 | else: 79 | playerLetter = 'X' 80 | 81 | # Here is our algorithm for our Tic Tac Toe AI: 82 | # First, check if we can win in the next move 83 | for i in range(1, 10): 84 | boardCopy = copy.copy(board) 85 | if isSpaceFree(boardCopy, i): 86 | boardCopy[i] = computerLetter 87 | if isWinner(boardCopy, computerLetter): 88 | return i 89 | 90 | # Check if the player could win on their next move, and block them. 91 | for i in range(1, 10): 92 | boardCopy = copy.copy(board) 93 | if isSpaceFree(boardCopy, i): 94 | boardCopy[i] = playerLetter 95 | if isWinner(boardCopy, playerLetter): 96 | return i 97 | 98 | # Try to take one of the corners, if they are free. 99 | move = chooseRandomMoveFromList(board, [1, 3, 7, 9]) 100 | if move != None: 101 | return move 102 | 103 | # Try to take the center, if it is free. 104 | if isSpaceFree(board, 5): 105 | return 5 106 | 107 | # Move on one of the sides. 108 | return chooseRandomMoveFromList(board, [2, 4, 6, 8]) 109 | 110 | def isBoardFull(board): 111 | # Return True if every space on the board has been taken. Otherwise return False. 112 | for i in range(1, 10): 113 | if isSpaceFree(board, i): 114 | return False 115 | return True 116 | 117 | # ===== end of copy-pasted tic tac toe code ======================= 118 | 119 | 120 | 121 | allComputerMoveMessages = ['', 122 | "print('O moves on the bottom-left space.')", 123 | "print('O moves on the bottom-center space.')", 124 | "print('O moves on the bottom-right space.')", 125 | "print('O moves on the left space.')", 126 | "print('O moves on the center space.')", 127 | "print('O moves on the right space.')", 128 | "print('O moves on the top-left space.')", 129 | "print('O moves on the top-center space.')", 130 | "print('O moves on the top-right space.')", 131 | ] 132 | 133 | def getPrintedBoard(board, indent): 134 | printedBoard = boardTemplate % (board[7], board[8], board[9], board[4], board[5], board[6], board[1], board[2], board[3]) 135 | printedBoard = printedBoard.replace('\n', '\n' + (' ' * indent)) 136 | printedBoard = (' ' * indent) + printedBoard # add indent to first line 137 | return printedBoard 138 | 139 | def getPrintedMoveMessage(indent): 140 | printedMessage = enterMoveMessage .replace('\n', '\n' + (' ' * indent)) 141 | printedMessage = (' ' * indent) + printedMessage # add indent to first line 142 | return printedMessage 143 | 144 | def printMove(originalBoard, indent=0): 145 | for move in range(1, 10): 146 | board = copy.copy(originalBoard) 147 | 148 | if not isSpaceFree(board, move): 149 | logging.debug('skipping %s' % (move)) 150 | continue 151 | 152 | print(' ' * indent + "if move == '%s':" % (move)) 153 | #if computerMoveMsg != '': 154 | # print(' ' * (indent+1) + computerMoveMsg) 155 | #import pdb; pdb.set_trace() 156 | 157 | #print(getPrintedBoard(board, indent)) 158 | 159 | logging.debug('moving on %s' % (move)) 160 | board[move] = 'X' 161 | 162 | if isWinner(board, 'X'): 163 | print(getPrintedBoard(board, (indent+1))) 164 | print(' ' * (indent+1) + "print('You have won!')") 165 | print(' ' * (indent+1) + "sys.exit()") 166 | continue 167 | 168 | if isBoardFull(board): 169 | logging.debug('board full') 170 | print(getPrintedBoard(board, (indent+1))) 171 | print(' ' * (indent+1) + "print('It\\'s a tie!')") 172 | print(' ' * (indent+1) + "sys.exit()") 173 | continue 174 | 175 | compMove = getComputerMove(board, 'O') 176 | board[compMove] = 'O' 177 | if isWinner(board, 'O'): 178 | print(' ' * (indent+1) + allComputerMoveMessages[compMove]) 179 | print(getPrintedBoard(board, (indent+1))) 180 | print(' ' * (indent+1) + "print('The computer wins!')") 181 | print(' ' * (indent+1) + "sys.exit()") 182 | continue 183 | 184 | print(' ' * (indent+1) + allComputerMoveMessages[compMove]) 185 | 186 | print(getPrintedBoard(board, indent + 1)) 187 | print(getPrintedMoveMessage(indent + 1)) 188 | print(' ' * (indent+1) + "move = input()\n") 189 | #printMove(copy.copy(board), indent + 1, allComputerMoveMessages[compMove]) 190 | printMove(copy.copy(board), indent + 1) 191 | 192 | 193 | print('''# My first tic-tac-toe program, by Al Sweigart al@inventwithpython.com 194 | # This sure was a lot of typing, but I finally finished it! 195 | 196 | # (This is a joke program.) 197 | 198 | import sys 199 | if sys.version_info[0] == 2: 200 | input = raw_input # python 2 compatibility 201 | print('Welcome to Tic Tac Toe!') 202 | print('You are X.\\n') 203 | ''') 204 | 205 | board = [' '] * 10 206 | print(getPrintedBoard(board, 0)) 207 | print(getPrintedMoveMessage(0)) 208 | print("move = input()\n") 209 | printMove(board, 0) 210 | -------------------------------------------------------------------------------- /hehhehhehlizard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asweigart/my_first_tic_tac_toe/13a8b81c796ccff4c7328e8272d12df0fb45ef56/hehhehhehlizard.jpg --------------------------------------------------------------------------------