11.2: Source Code for Flippy
- Page ID
- 13626
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\( \newcommand{\id}{\mathrm{id}}\) \( \newcommand{\Span}{\mathrm{span}}\)
( \newcommand{\kernel}{\mathrm{null}\,}\) \( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\) \( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\) \( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\id}{\mathrm{id}}\)
\( \newcommand{\Span}{\mathrm{span}}\)
\( \newcommand{\kernel}{\mathrm{null}\,}\)
\( \newcommand{\range}{\mathrm{range}\,}\)
\( \newcommand{\RealPart}{\mathrm{Re}}\)
\( \newcommand{\ImaginaryPart}{\mathrm{Im}}\)
\( \newcommand{\Argument}{\mathrm{Arg}}\)
\( \newcommand{\norm}[1]{\| #1 \|}\)
\( \newcommand{\inner}[2]{\langle #1, #2 \rangle}\)
\( \newcommand{\Span}{\mathrm{span}}\) \( \newcommand{\AA}{\unicode[.8,0]{x212B}}\)
\( \newcommand{\vectorA}[1]{\vec{#1}} % arrow\)
\( \newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow\)
\( \newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vectorC}[1]{\textbf{#1}} \)
\( \newcommand{\vectorD}[1]{\overrightarrow{#1}} \)
\( \newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}} \)
\( \newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}} \)
\( \newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} } \)
\( \newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}} \)
\(\newcommand{\avec}{\mathbf a}\) \(\newcommand{\bvec}{\mathbf b}\) \(\newcommand{\cvec}{\mathbf c}\) \(\newcommand{\dvec}{\mathbf d}\) \(\newcommand{\dtil}{\widetilde{\mathbf d}}\) \(\newcommand{\evec}{\mathbf e}\) \(\newcommand{\fvec}{\mathbf f}\) \(\newcommand{\nvec}{\mathbf n}\) \(\newcommand{\pvec}{\mathbf p}\) \(\newcommand{\qvec}{\mathbf q}\) \(\newcommand{\svec}{\mathbf s}\) \(\newcommand{\tvec}{\mathbf t}\) \(\newcommand{\uvec}{\mathbf u}\) \(\newcommand{\vvec}{\mathbf v}\) \(\newcommand{\wvec}{\mathbf w}\) \(\newcommand{\xvec}{\mathbf x}\) \(\newcommand{\yvec}{\mathbf y}\) \(\newcommand{\zvec}{\mathbf z}\) \(\newcommand{\rvec}{\mathbf r}\) \(\newcommand{\mvec}{\mathbf m}\) \(\newcommand{\zerovec}{\mathbf 0}\) \(\newcommand{\onevec}{\mathbf 1}\) \(\newcommand{\real}{\mathbb R}\) \(\newcommand{\twovec}[2]{\left[\begin{array}{r}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\ctwovec}[2]{\left[\begin{array}{c}#1 \\ #2 \end{array}\right]}\) \(\newcommand{\threevec}[3]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\cthreevec}[3]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \end{array}\right]}\) \(\newcommand{\fourvec}[4]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\cfourvec}[4]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \end{array}\right]}\) \(\newcommand{\fivevec}[5]{\left[\begin{array}{r}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\cfivevec}[5]{\left[\begin{array}{c}#1 \\ #2 \\ #3 \\ #4 \\ #5 \\ \end{array}\right]}\) \(\newcommand{\mattwo}[4]{\left[\begin{array}{rr}#1 \amp #2 \\ #3 \amp #4 \\ \end{array}\right]}\) \(\newcommand{\laspan}[1]{\text{Span}\{#1\}}\) \(\newcommand{\bcal}{\cal B}\) \(\newcommand{\ccal}{\cal C}\) \(\newcommand{\scal}{\cal S}\) \(\newcommand{\wcal}{\cal W}\) \(\newcommand{\ecal}{\cal E}\) \(\newcommand{\coords}[2]{\left\{#1\right\}_{#2}}\) \(\newcommand{\gray}[1]{\color{gray}{#1}}\) \(\newcommand{\lgray}[1]{\color{lightgray}{#1}}\) \(\newcommand{\rank}{\operatorname{rank}}\) \(\newcommand{\row}{\text{Row}}\) \(\newcommand{\col}{\text{Col}}\) \(\renewcommand{\row}{\text{Row}}\) \(\newcommand{\nul}{\text{Nul}}\) \(\newcommand{\var}{\text{Var}}\) \(\newcommand{\corr}{\text{corr}}\) \(\newcommand{\len}[1]{\left|#1\right|}\) \(\newcommand{\bbar}{\overline{\bvec}}\) \(\newcommand{\bhat}{\widehat{\bvec}}\) \(\newcommand{\bperp}{\bvec^\perp}\) \(\newcommand{\xhat}{\widehat{\xvec}}\) \(\newcommand{\vhat}{\widehat{\vvec}}\) \(\newcommand{\uhat}{\widehat{\uvec}}\) \(\newcommand{\what}{\widehat{\wvec}}\) \(\newcommand{\Sighat}{\widehat{\Sigma}}\) \(\newcommand{\lt}{<}\) \(\newcommand{\gt}{>}\) \(\newcommand{\amp}{&}\) \(\definecolor{fillinmathshade}{gray}{0.9}\)This source code can be downloaded from http://invpy.com/flippy.py.
The image files that Flippy uses can be downloaded from http://invpy.com/flippyimages.zip.
# Flippy (an Othello or Reversi clone) # By Al Sweigart al@inventwithpython.com # http://inventwithpython.com/pygame # Released under a "Simplified BSD" license # Based on the "reversi.py" code that originally appeared in "Invent # Your Own Computer Games with Python", chapter 15: # http://inventwithpython.com/chapter15.html import random, sys, pygame, time, copy from pygame.locals import * FPS = 10 # frames per second to update the screen WINDOWWIDTH = 640 # width of the program's window, in pixels WINDOWHEIGHT = 480 # height in pixels SPACESIZE = 50 # width & height of each space on the board, in pixels BOARDWIDTH = 8 # how many columns of spaces on the game board BOARDHEIGHT = 8 # how many rows of spaces on the game board WHITE_TILE = 'WHITE_TILE' # an arbitrary but unique value BLACK_TILE = 'BLACK_TILE' # an arbitrary but unique value EMPTY_SPACE = 'EMPTY_SPACE' # an arbitrary but unique value HINT_TILE = 'HINT_TILE' # an arbitrary but unique value ANIMATIONSPEED = 25 # integer from 1 to 100, higher is faster animation # Amount of space on the left & right side (XMARGIN) or above and below # (YMARGIN) the game board, in pixels. XMARGIN = int((WINDOWWIDTH - (BOARDWIDTH * SPACESIZE)) / 2) YMARGIN = int((WINDOWHEIGHT - (BOARDHEIGHT * SPACESIZE)) / 2) # R G B WHITE = (255, 255, 255) BLACK = ( 0, 0, 0) GREEN = ( 0, 155, 0) BRIGHTBLUE = ( 0, 50, 255) BROWN = (174, 94, 0) TEXTBGCOLOR1 = BRIGHTBLUE TEXTBGCOLOR2 = GREEN GRIDLINECOLOR = BLACK TEXTCOLOR = WHITE HINTCOLOR = BROWN def main(): global MAINCLOCK, DISPLAYSURF, FONT, BIGFONT, BGIMAGE pygame.init() MAINCLOCK = pygame.time.Clock() DISPLAYSURF = pygame.display.set_mode((WINDOWWIDTH, WINDOWHEIGHT)) pygame.display.set_caption('Flippy') FONT = pygame.font.Font('freesansbold.ttf', 16) BIGFONT = pygame.font.Font('freesansbold.ttf', 32) # Set up the background image. boardImage = pygame.image.load('flippyboard.png') # Use smoothscale() to stretch the board image to fit the entire board: boardImage = pygame.transform.smoothscale(boardImage, (BOARDWIDTH * SPACESIZE, BOARDHEIGHT * SPACESIZE)) boardImageRect = boardImage.get_rect() boardImageRect.topleft = (XMARGIN, YMARGIN) BGIMAGE = pygame.image.load('flippybackground.png') # Use smoothscale() to stretch the background image to fit the entire window: BGIMAGE = pygame.transform.smoothscale(BGIMAGE, (WINDOWWIDTH, WINDOWHEIGHT)) BGIMAGE.blit(boardImage, boardImageRect) # Run the main game. while True: if runGame() == False: break def runGame(): # Plays a single game of reversi each time this function is called. # Reset the board and game. mainBoard = getNewBoard() resetBoard(mainBoard) showHints = False turn = random.choice(['computer', 'player']) # Draw the starting board and ask the player what color they want. drawBoard(mainBoard) playerTile, computerTile = enterPlayerTile() # Make the Surface and Rect objects for the "New Game" and "Hints" buttons newGameSurf = FONT.render('New Game', True, TEXTCOLOR, TEXTBGCOLOR2) newGameRect = newGameSurf.get_rect() newGameRect.topright = (WINDOWWIDTH - 8, 10) hintsSurf = FONT.render('Hints', True, TEXTCOLOR, TEXTBGCOLOR2) hintsRect = hintsSurf.get_rect() hintsRect.topright = (WINDOWWIDTH - 8, 40) while True: # main game loop # Keep looping for player and computer's turns. if turn == 'player': # Player's turn: if getValidMoves(mainBoard, playerTile) == []: # If it's the player's turn but they # can't move, then end the game. break movexy = None while movexy == None: # Keep looping until the player clicks on a valid space. # Determine which board data structure to use for display. if showHints: boardToDraw = getBoardWithValidMoves(mainBoard, playerTile) else: boardToDraw = mainBoard checkForQuit() for event in pygame.event.get(): # event handling loop if event.type == MOUSEBUTTONUP: # Handle mouse click events mousex, mousey = event.pos if newGameRect.collidepoint( (mousex, mousey) ): # Start a new game return True elif hintsRect.collidepoint( (mousex, mousey) ): # Toggle hints mode showHints = not showHints # movexy is set to a two-item tuple XY coordinate, or None value movexy = getSpaceClicked(mousex, mousey) if movexy != None and not isValidMove(mainBoard, playerTile, movexy[0], movexy[1]): movexy = None # Draw the game board. drawBoard(boardToDraw) drawInfo(boardToDraw, playerTile, computerTile, turn) # Draw the "New Game" and "Hints" buttons. DISPLAYSURF.blit(newGameSurf, newGameRect) DISPLAYSURF.blit(hintsSurf, hintsRect) MAINCLOCK.tick(FPS) pygame.display.update() # Make the move and end the turn. makeMove(mainBoard, playerTile, movexy[0], movexy[1], True) if getValidMoves(mainBoard, computerTile) != []: # Only set for the computer's turn if it can make a move. turn = 'computer' else: # Computer's turn: if getValidMoves(mainBoard, computerTile) == []: # If it was set to be the computer's turn but # they can't move, then end the game. break # Draw the board. drawBoard(mainBoard) drawInfo(mainBoard, playerTile, computerTile, turn) # Draw the "New Game" and "Hints" buttons. DISPLAYSURF.blit(newGameSurf, newGameRect) DISPLAYSURF.blit(hintsSurf, hintsRect) # Make it look like the computer is thinking by pausing a bit. pauseUntil = time.time() + random.randint(5, 15) * 0.1 while time.time() < pauseUntil: pygame.display.update() # Make the move and end the turn. x, y = getComputerMove(mainBoard, computerTile) makeMove(mainBoard, computerTile, x, y, True) if getValidMoves(mainBoard, playerTile) != []: # Only set for the player's turn if they can make a move. turn = 'player' # Display the final score. drawBoard(mainBoard) scores = getScoreOfBoard(mainBoard) # Determine the text of the message to display. if scores[playerTile] > scores[computerTile]: text = 'You beat the computer by %s points! Congratulations!' % \ (scores[playerTile] - scores[computerTile]) elif scores[playerTile] < scores[computerTile]: text = 'You lost. The computer beat you by %s points.' % \ (scores[computerTile] - scores[playerTile]) else: text = 'The game was a tie!' textSurf = FONT.render(text, True, TEXTCOLOR, TEXTBGCOLOR1) textRect = textSurf.get_rect() textRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2)) DISPLAYSURF.blit(textSurf, textRect) # Display the "Play again?" text with Yes and No buttons. text2Surf = BIGFONT.render('Play again?', True, TEXTCOLOR, TEXTBGCOLOR1) text2Rect = text2Surf.get_rect() text2Rect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2) + 50) # Make "Yes" button. yesSurf = BIGFONT.render('Yes', True, TEXTCOLOR, TEXTBGCOLOR1) yesRect = yesSurf.get_rect() yesRect.center = (int(WINDOWWIDTH / 2) - 60, int(WINDOWHEIGHT / 2) + 90) # Make "No" button. noSurf = BIGFONT.render('No', True, TEXTCOLOR, TEXTBGCOLOR1) noRect = noSurf.get_rect() noRect.center = (int(WINDOWWIDTH / 2) + 60, int(WINDOWHEIGHT / 2) + 90) while True: # Process events until the user clicks on Yes or No. checkForQuit() for event in pygame.event.get(): # event handling loop if event.type == MOUSEBUTTONUP: mousex, mousey = event.pos if yesRect.collidepoint( (mousex, mousey) ): return True elif noRect.collidepoint( (mousex, mousey) ): return False DISPLAYSURF.blit(textSurf, textRect) DISPLAYSURF.blit(text2Surf, text2Rect) DISPLAYSURF.blit(yesSurf, yesRect) DISPLAYSURF.blit(noSurf, noRect) pygame.display.update() MAINCLOCK.tick(FPS) def translateBoardToPixelCoord(x, y): return XMARGIN + x * SPACESIZE + int(SPACESIZE / 2), YMARGIN + y * SPACESIZE + int(SPACESIZE / 2) def animateTileChange(tilesToFlip, tileColor, additionalTile): # Draw the additional tile that was just laid down. (Otherwise we'd # have to completely redraw the board & the board info.) if tileColor == WHITE_TILE: additionalTileColor = WHITE else: additionalTileColor = BLACK additionalTileX, additionalTileY = translateBoardToPixelCoord(additionalTile[0], additionalTile[1]) pygame.draw.circle(DISPLAYSURF, additionalTileColor, (additionalTileX, additionalTileY), int(SPACESIZE / 2) - 4) pygame.display.update() for rgbValues in range(0, 255, int(ANIMATIONSPEED * 2.55)): if rgbValues > 255: rgbValues = 255 elif rgbValues < 0: rgbValues = 0 if tileColor == WHITE_TILE: color = tuple([rgbValues] * 3) # rgbValues goes from 0 to 255 elif tileColor == BLACK_TILE: color = tuple([255 - rgbValues] * 3) # rgbValues goes from 255 to 0 for x, y in tilesToFlip: centerx, centery = translateBoardToPixelCoord(x, y) pygame.draw.circle(DISPLAYSURF, color, (centerx, centery), int(SPACESIZE / 2) - 4) pygame.display.update() MAINCLOCK.tick(FPS) checkForQuit() def drawBoard(board): # Draw background of board. DISPLAYSURF.blit(BGIMAGE, BGIMAGE.get_rect()) # Draw grid lines of the board. for x in range(BOARDWIDTH + 1): # Draw the horizontal lines. startx = (x * SPACESIZE) + XMARGIN starty = YMARGIN endx = (x * SPACESIZE) + XMARGIN endy = YMARGIN + (BOARDHEIGHT * SPACESIZE) pygame.draw.line(DISPLAYSURF, GRIDLINECOLOR, (startx, starty), (endx, endy)) for y in range(BOARDHEIGHT + 1): # Draw the vertical lines. startx = XMARGIN starty = (y * SPACESIZE) + YMARGIN endx = XMARGIN + (BOARDWIDTH * SPACESIZE) endy = (y * SPACESIZE) + YMARGIN pygame.draw.line(DISPLAYSURF, GRIDLINECOLOR, (startx, starty), (endx, endy)) # Draw the black & white tiles or hint spots. for x in range(BOARDWIDTH): for y in range(BOARDHEIGHT): centerx, centery = translateBoardToPixelCoord(x, y) if board[x][y] == WHITE_TILE or board[x][y] == BLACK_TILE: if board[x][y] == WHITE_TILE: tileColor = WHITE else: tileColor = BLACK pygame.draw.circle(DISPLAYSURF, tileColor, (centerx, centery), int(SPACESIZE / 2) - 4) if board[x][y] == HINT_TILE: pygame.draw.rect(DISPLAYSURF, HINTCOLOR, (centerx - 4, centery - 4, 8, 8)) def getSpaceClicked(mousex, mousey): # Return a tuple of two integers of the board space coordinates where # the mouse was clicked. (Or returns None not in any space.) for x in range(BOARDWIDTH): for y in range(BOARDHEIGHT): if mousex > x * SPACESIZE + XMARGIN and \ mousex < (x + 1) * SPACESIZE + XMARGIN and \ mousey > y * SPACESIZE + YMARGIN and \ mousey < (y + 1) * SPACESIZE + YMARGIN: return (x, y) return None def drawInfo(board, playerTile, computerTile, turn): # Draws scores and whose turn it is at the bottom of the screen. scores = getScoreOfBoard(board) scoreSurf = FONT.render("Player Score: %s Computer Score: %s %s's Turn" % (str(scores[playerTile]), str(scores[computerTile]), turn.title()), True, TEXTCOLOR) scoreRect = scoreSurf.get_rect() scoreRect.bottomleft = (10, WINDOWHEIGHT - 5) DISPLAYSURF.blit(scoreSurf, scoreRect) def resetBoard(board): # Blanks out the board it is passed, and sets up starting tiles. for x in range(BOARDWIDTH): for y in range(BOARDHEIGHT): board[x][y] = EMPTY_SPACE # Add starting pieces to the center board[3][3] = WHITE_TILE board[3][4] = BLACK_TILE board[4][3] = BLACK_TILE board[4][4] = WHITE_TILE def getNewBoard(): # Creates a brand new, empty board data structure. board = [] for i in range(BOARDWIDTH): board.append([EMPTY_SPACE] * BOARDHEIGHT) return board def isValidMove(board, tile, xstart, ystart): # Returns False if the player's move is invalid. If it is a valid # move, returns a list of spaces of the captured pieces. if board[xstart][ystart] != EMPTY_SPACE or not isOnBoard(xstart, ystart): return False board[xstart][ystart] = tile # temporarily set the tile on the board. if tile == WHITE_TILE: otherTile = BLACK_TILE else: otherTile = WHITE_TILE tilesToFlip = [] # check each of the eight directions: for xdirection, ydirection in [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]: x, y = xstart, ystart x += xdirection y += ydirection if isOnBoard(x, y) and board[x][y] == otherTile: # The piece belongs to the other player next to our piece. x += xdirection y += ydirection if not isOnBoard(x, y): continue while board[x][y] == otherTile: x += xdirection y += ydirection if not isOnBoard(x, y): break # break out of while loop, continue in for loop if not isOnBoard(x, y): continue if board[x][y] == tile: # There are pieces to flip over. Go in the reverse # direction until we reach the original space, noting all # the tiles along the way. while True: x -= xdirection y -= ydirection if x == xstart and y == ystart: break tilesToFlip.append([x, y]) board[xstart][ystart] = EMPTY_SPACE # make space empty if len(tilesToFlip) == 0: # If no tiles flipped, this move is invalid return False return tilesToFlip def isOnBoard(x, y): # Returns True if the coordinates are located on the board. return x >= 0 and x < BOARDWIDTH and y >= 0 and y < BOARDHEIGHT def getBoardWithValidMoves(board, tile): # Returns a new board with hint markings. dupeBoard = copy.deepcopy(board) for x, y in getValidMoves(dupeBoard, tile): dupeBoard[x][y] = HINT_TILE return dupeBoard def getValidMoves(board, tile): # Returns a list of (x,y) tuples of all valid moves. validMoves = [] for x in range(BOARDWIDTH): for y in range(BOARDHEIGHT): if isValidMove(board, tile, x, y) != False: validMoves.append((x, y)) return validMoves def getScoreOfBoard(board): # Determine the score by counting the tiles. xscore = 0 oscore = 0 for x in range(BOARDWIDTH): for y in range(BOARDHEIGHT): if board[x][y] == WHITE_TILE: xscore += 1 if board[x][y] == BLACK_TILE: oscore += 1 return {WHITE_TILE:xscore, BLACK_TILE:oscore} def enterPlayerTile(): # Draws the text and handles the mouse click events for letting # the player choose which color they want to be. Returns # [WHITE_TILE, BLACK_TILE] if the player chooses to be White, # [BLACK_TILE, WHITE_TILE] if Black. # Create the text. textSurf = FONT.render('Do you want to be white or black?', True, TEXTCOLOR, TEXTBGCOLOR1) textRect = textSurf.get_rect() textRect.center = (int(WINDOWWIDTH / 2), int(WINDOWHEIGHT / 2)) xSurf = BIGFONT.render('White', True, TEXTCOLOR, TEXTBGCOLOR1) xRect = xSurf.get_rect() xRect.center = (int(WINDOWWIDTH / 2) - 60, int(WINDOWHEIGHT / 2) + 40) oSurf = BIGFONT.render('Black', True, TEXTCOLOR, TEXTBGCOLOR1) oRect = oSurf.get_rect() oRect.center = (int(WINDOWWIDTH / 2) + 60, int(WINDOWHEIGHT / 2) + 40) while True: # Keep looping until the player has clicked on a color. checkForQuit() for event in pygame.event.get(): # event handling loop if event.type == MOUSEBUTTONUP: mousex, mousey = event.pos if xRect.collidepoint( (mousex, mousey) ): return [WHITE_TILE, BLACK_TILE] elif oRect.collidepoint( (mousex, mousey) ): return [BLACK_TILE, WHITE_TILE] # Draw the screen. DISPLAYSURF.blit(textSurf, textRect) DISPLAYSURF.blit(xSurf, xRect) DISPLAYSURF.blit(oSurf, oRect) pygame.display.update() MAINCLOCK.tick(FPS) def makeMove(board, tile, xstart, ystart, realMove=False): # Place the tile on the board at xstart, ystart, and flip tiles # Returns False if this is an invalid move, True if it is valid. tilesToFlip = isValidMove(board, tile, xstart, ystart) if tilesToFlip == False: return False board[xstart][ystart] = tile if realMove: animateTileChange(tilesToFlip, tile, (xstart, ystart)) for x, y in tilesToFlip: board[x][y] = tile return True def isOnCorner(x, y): # Returns True if the position is in one of the four corners. return (x == 0 and y == 0) or \ (x == BOARDWIDTH and y == 0) or \ (x == 0 and y == BOARDHEIGHT) or \ (x == BOARDWIDTH and y == BOARDHEIGHT) def getComputerMove(board, computerTile): # Given a board and the computer's tile, determine where to # move and return that move as a [x, y] list. possibleMoves = getValidMoves(board, computerTile) # randomize the order of the possible moves random.shuffle(possibleMoves) # always go for a corner if available. for x, y in possibleMoves: if isOnCorner(x, y): return [x, y] # Go through all possible moves and remember the best scoring move bestScore = -1 for x, y in possibleMoves: dupeBoard = copy.deepcopy(board) makeMove(dupeBoard, computerTile, x, y) score = getScoreOfBoard(dupeBoard)[computerTile] if score > bestScore: bestMove = [x, y] bestScore = score return bestMove def checkForQuit(): for event in pygame.event.get((QUIT, KEYUP)): # event handling loop if event.type == QUIT or (event.type == KEYUP and event.key == K_ESCAPE): pygame.quit() sys.exit() if __name__ == '__main__': main()