Chapter 10 - Othello

Source Code

othello.py
  1. # Othello
  2. import random
  3. import sys
  4. def drawBoard(board):
  5.     # This function prints out the board that it was passed. Returns None.
  6.     hline = '  +---+---+---+---+---+---+---+---+'
  7.     vline = '  |   |   |   |   |   |   |   |   |'
  8.     print '    1   2   3   4   5   6   7   8'
  9.     print hline
  10.     for y in range(8):
  11.         print vline
  12.         print y+1,
  13.         for x in range(8):
  14.             print '| %s' % (board[x][y]),
  15.         print '|'
  16.         print vline
  17.         print hline
  18. def resetBoard(board):
  19.     # Blanks out the board it is passed, except for the original starting position.
  20.     for x in range(8):
  21.         for y in range(8):
  22.             board[x][y] = ' '
  23.     # Starting pieces:
  24.     board[3][3] = 'X'
  25.     board[3][4] = 'O'
  26.     board[4][3] = 'O'
  27.     board[4][4] = 'X'
  28.     return board
  29. def getNewBoard():
  30.     # Creates a brand new, blank board data structure.
  31.     board = []
  32.     for i in range(8):
  33.         board.append([' '] * 8)
  34.     return board
  35. def isValidMove(board, letter, startx, starty):
  36.     # Returns True if the move to space x,y is a valid one.
  37.     if not isOnBoard(startx, starty) or board[startx][starty] != ' ':
  38.         return False
  39.     directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]
  40.     if letter == 'X':
  41.         otherLetter = 'O'
  42.     else:
  43.         otherLetter = 'X'
  44.     for d in directions:
  45.         DX = d[0]
  46.         DY = d[1]
  47.         x, y = startx, starty
  48.         x += DX
  49.         y += DY
  50.         if isOnBoard(x, y):
  51.             if board[x][y] == otherLetter:
  52.                 # There is a piece belonging to the other player next to our piece.
  53.                 x += DX
  54.                 y += DY
  55.                 if not isOnBoard(x, y):
  56.                     continue
  57.                 while board[x][y] == otherLetter:
  58.                     x += DX
  59.                     y += DY
  60.                     if not isOnBoard(x, y): # double loop break
  61.                         break
  62.                 if not isOnBoard(x, y):
  63.                     continue
  64.                 if board[x][y] == letter:
  65.                     return True
  66.     return False
  67. def isOnBoard(x, y):
  68.     # Returns True if the coordinates are located on the board.
  69.     return x >= 0 and x <= 7 and y >= 0 and y <=7
  70. def getBoardWithValidMoves(board, letter):
  71.     # Returns a new board with . marking the valid moves the given player can make.
  72.     dupeBoard = getBoardCopy(board)
  73.     for x, y in getValidMoves(dupeBoard, letter):
  74.         dupeBoard[x][y] = '.'
  75.     return dupeBoard
  76. def getValidMoves(board, letter):
  77.     # Returns a list of [x,y] lists of valid moves for the given player on the given board.
  78.     validMoves = []
  79.     for x in range(8):
  80.         for y in range(8):
  81.             if isValidMove(board, letter, x, y):
  82.                 validMoves.append([x, y])
  83.     return validMoves
  84. def getScoreOfBoard(board):
  85.     # Determine the score. Returns a dictionary with keys 'X' and 'O'.
  86.     xscore = 0
  87.     oscore = 0
  88.     for x in range(8):
  89.         for y in range(8):
  90.             if board[x][y] == 'X':
  91.                 xscore += 1
  92.             if board[x][y] == 'O':
  93.                 oscore += 1
  94.     return {'X':xscore, 'O':oscore}
  95. def enterPlayerLetter():
  96.     # Let's the player type which letter they want to be.
  97.     # Returns a list with the player's letter as the first item, and the computer's letter as the second.
  98.     letter = ''
  99.     while not (letter == 'X' or letter == 'O'):
  100.         print 'Do you want to be X or O?'
  101.         letter = raw_input().upper()
  102.     # the first element in the tuple is the player's letter, the second is the computer's letter.
  103.     if letter == 'X':
  104.         return ['X', 'O']
  105.     else:
  106.         return ['O', 'X']
  107. def whoGoesFirst():
  108.     # Randomly choose the player who goes first.
  109.     if random.randint(0, 1) == 0:
  110.         return 'computer'
  111.     else:
  112.         return 'player'
  113. def playAgain():
  114.     # This function returns True if the player wants to play again, otherwise it returns False.
  115.     print 'Do you want to play again? (yes or no)'
  116.     return raw_input().lower().startswith('y')
  117. def makeMove(board, letter, startx, starty):
  118.     # Place the letter on the board at startx, starty, and flip any of the opponent's pieces.
  119.     # Returns False if this is an invalid move, returns True if it is valid.
  120.     if not isValidMove(board, letter, startx, starty):
  121.         return False
  122.     board[startx][starty] = letter
  123.     directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]
  124.     if letter == 'X':
  125.         otherLetter = 'O'
  126.     else:
  127.         otherLetter = 'X'
  128.     for d in directions:
  129.         DX = d[0]
  130.         DY = d[1]
  131.         x, y = startx, starty
  132.         x += DX
  133.         y += DY
  134.         if isOnBoard(x, y):
  135.             if board[x][y] == otherLetter:
  136.                 # There is a piece belonging to the other player next to our piece.
  137.                 x += DX
  138.                 y += DY
  139.                 if not isOnBoard(x, y):
  140.                     continue
  141.                 while board[x][y] == otherLetter:
  142.                     x += DX
  143.                     y += DY
  144.                     if not isOnBoard(x, y): # break, then continue
  145.                         break
  146.                 if not isOnBoard(x, y):
  147.                     continue
  148.                 if board[x][y] == letter:
  149.                     # There are pieces to flip over. Go in the reverse direction.
  150.                     while True:
  151.                         x -= DX
  152.                         y -= DY
  153.                         if x == startx and y == starty:
  154.                             break
  155.                         board[x][y] = letter
  156.     return True
  157. def getBoardCopy(board):
  158.     # Make a duplicate of the board list and return the duplicate.
  159.     dupeBoard = getNewBoard()
  160.     for x in range(8):
  161.         for y in range(8):
  162.             dupeBoard[x][y] = board[x][y]
  163.     return dupeBoard
  164. def isOnCorner(x, y):
  165.     # Returns True if the position is in one of the four corners.
  166.     return (x == 0 and y == 0) or (x == 7 and y == 0) or (x == 0 and y == 7) or (x == 7 and y == 7)
  167. def isSpaceFree(board, x, y):
  168.     # Return true if the passed move is free on the passed board.
  169.     return board[x][y] == ' '
  170. def getPlayerMove(board, playerLetter):
  171.     # Let the player type in their move.
  172.     # Returns the move as [x, y] (or returns the strings 'hints' or 'quits')
  173.     digits1to8 = '1 2 3 4 5 6 7 8'.split()
  174.     move = ''
  175.     while True:
  176.         print 'Enter your move, or type quit to end the game, or hints to turn off/on hints.'
  177.         move = raw_input()
  178.         if move.lower() == 'quit':
  179.             return 'quit'
  180.         if move.lower() == 'hints':
  181.             return 'hints'
  182.         if len(move) == 2 and move[0] in digits1to8 and move[1] in digits1to8:
  183.             x = int(move[0]) - 1
  184.             y = int(move[1]) - 1
  185.             if not isValidMove(board, playerLetter, x, y):
  186.                 continue
  187.             else:
  188.                 break
  189.         else:
  190.             print 'That is not a valid move. Type the x digit (1-8), then the y digit (1-8).'
  191.             print 'For example, 81 will be the top-right corner.'    
  192.     return [x, y]
  193. def getComputerMove(board, computerLetter):
  194.     # Given a board and the computer's letter, determine where to
  195.     # move and return that move as a [x, y] list.
  196.     if computerLetter == 'X':
  197.         playerLetter = 'O'
  198.     else:
  199.         playerLetter = 'X'
  200.     possibleMoves = getValidMoves(board, computerLetter)
  201.     # create a list of moves that are in the corners, and
  202.     # always go for a corner if available.
  203.     cornerMoves = []
  204.     for move in possibleMoves:
  205.         if isOnCorner(move[0], move[1]):
  206.             cornerMoves.append(move)
  207.     if len(cornerMoves) > 0:
  208.         return random.choice(getHighestScoringMoves(board, computerLetter, cornerMoves))
  209.     # From the list of highest scoring moves, choose one at random.
  210.     return random.choice(getHighestScoringMoves(board, computerLetter, possibleMoves))
  211. def getHighestScoringMoves(board, letter, moves):
  212.     # Returns a list of the highest scoring moves from the list of moves.
  213.     # For example, if out of the list of six moves, the highest scoring move gives
  214.     # five more points, but there are three different moves that give five more points,
  215.     # then return a list with those three moves.
  216.     if len(moves) == 1:
  217.         return moves
  218.     currentScore = getScoreOfBoard(board)[letter]
  219.     bestScore = -1
  220.     allScores = []
  221.     for i in range(len(moves)):
  222.         dupeBoard = getBoardCopy(board)
  223.         makeMove(dupeBoard, letter, moves[i][0], moves[i][1])
  224.         scoreIncrease = getScoreOfBoard(dupeBoard)[letter] - currentScore
  225.         allScores.append(scoreIncrease)
  226.         if scoreIncrease > bestScore:
  227.             bestScore = scoreIncrease
  228.     topMoves = []
  229.     for i in range(len(allScores)):
  230.         if allScores[i] == bestScore:
  231.             topMoves.append(moves[i])
  232.     return topMoves
  233. def isBoardDone(board, letter):
  234.     # Return True if the player with the given letter can make a move on the board. Otherwise return False.
  235.     if getValidMoves(board, letter) == []:
  236.         return True
  237.     for x in range(8):
  238.         for y in range(8):
  239.             if board[x][y] == ' ':
  240.                 return False
  241.     return True
  242. def showPoints(playerLetter, computerLetter):
  243.     # Prints out the current score.
  244.     scores = getScoreOfBoard(theBoard)
  245.     print 'You have %s points. The computer has %s points.' % (scores[playerLetter], scores[computerLetter])
  246. print 'Welcome to Othello!'
  247. while True:
  248.     # Reset the board and game.
  249.     theBoard = getNewBoard()
  250.     resetBoard(theBoard)
  251.     playerLetter, computerLetter = enterPlayerLetter()
  252.     showHints = False
  253.     turn = whoGoesFirst()
  254.     print 'The ' + turn + ' will go first.'
  255.     while True
  256.         if turn == 'player':
  257.             # Player's turn.
  258.             if showHints:
  259.                 validMovesBoard = getBoardWithValidMoves(theBoard, playerLetter)
  260.                 drawBoard(validMovesBoard)
  261.             else:
  262.                 drawBoard(theBoard)
  263.             showPoints(playerLetter, computerLetter)
  264.             move = getPlayerMove(theBoard, playerLetter)
  265.             if move == 'quit':
  266.                 print 'Thanks for playing!'
  267.                 sys.exit() # terminate the program
  268.             elif move == 'hints':
  269.                 showHints = not showHints
  270.                 continue
  271.             else:
  272.                 x, y = move
  273.             makeMove(theBoard, playerLetter, x, y)
  274.             if isBoardDone(theBoard, computerLetter): # computerLetter, not playerLetter
  275.                 break
  276.             else:
  277.                 turn = 'computer'
  278.         else:
  279.             # Computer's turn.
  280.             x, y = getComputerMove(theBoard, computerLetter)
  281.             drawBoard(theBoard)
  282.             showPoints(playerLetter, computerLetter)
  283.             raw_input('Press Enter to see the computer\'s move.')
  284.             makeMove(theBoard, computerLetter, x, y)
  285.             if isBoardDone(theBoard, playerLetter): # playerLetter, not computerLetter
  286.                 break
  287.             else:
  288.                 turn = 'player'
  289.     # Display the final score.
  290.     scores = getScoreOfBoard(theBoard)
  291.     print 'X scored %s points. O scored %s points.' % (scores['X'], scores['O'])
  292.     if scores[playerLetter] > scores[computerLetter]:
  293.         print 'You beat the computer by %s points! Congratulations!' % (scores[playerLetter] - scores[computerLetter])
  294.     elif scores[playerLetter] < scores[computerLetter]:
  295.         print 'You lost. The computer beat you by %s points.' % (scores[computerLetter] - scores[playerLetter])
  296.     else:
  297.         print 'The game was a tie!'
  298.     
  299.     if not playAgain():
  300.         break

Code Explanation

  1. # Othello
  2. import random
  3. import sys
  1. def drawBoard(board):
  2.     # This function prints out the board that it was passed. Returns None.
  3.     hline = '  +---+---+---+---+---+---+---+---+'
  4.     vline = '  |   |   |   |   |   |   |   |   |'
  5.     print '    1   2   3   4   5   6   7   8'
  1.     print hline
  2.     for y in range(8):
  3.         print vline
  4.         print y+1,
  5.         for x in range(8):
  6.             print '| %s' % (board[x][y]),
  7.         print '|'
  8.         print vline
  9.         print hline
  1. def resetBoard(board):
  2.     # Blanks out the board it is passed, except for the original starting position.
  3.     for x in range(8):
  4.         for y in range(8):
  5.             board[x][y] = ' '
  1.     # Starting pieces:
  2.     board[3][3] = 'X'
  3.     board[3][4] = 'O'
  4.     board[4][3] = 'O'
  5.     board[4][4] = 'X'
  6.     return board
  1. def getNewBoard():
  2.     # Creates a brand new, blank board data structure.
  3.     board = []
  4.     for i in range(8):
  5.         board.append([' '] * 8)
  6.     return board
  1. def isValidMove(board, letter, startx, starty):
  2.     # Returns True if the move to space x,y is a valid one.
  3.     if not isOnBoard(startx, starty) or board[startx][starty] != ' ':
  4.         return False
  1.     directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]
  2.     if letter == 'X':
  3.         otherLetter = 'O'
  4.     else:
  5.         otherLetter = 'X'
  1.     for d in directions:
  2.         DX = d[0]
  3.         DY = d[1]
  4.         x, y = startx, starty
  5.         x += DX
  6.         y += DY
  1.         if isOnBoard(x, y):
  2.             if board[x][y] == otherLetter:
  3.                 # There is a piece belonging to the other player next to our piece.
  4.                 x += DX
  5.                 y += DY
  6.                 if not isOnBoard(x, y):
  7.                     continue
  1.                 while board[x][y] == otherLetter:
  2.                     x += DX
  3.                     y += DY
  4.                     if not isOnBoard(x, y): # double loop break
  5.                         break
  1.                 if not isOnBoard(x, y):
  2.                     continue
  3.                 if board[x][y] == letter:
  4.                     return True
  5.     return False
  1. def isOnBoard(x, y):
  2.     # Returns True if the coordinates are located on the board.
  3.     return x >= 0 and x <= 7 and y >= 0 and y <=7
  1. def getBoardWithValidMoves(board, letter):
  2.     # Returns a new board with . marking the valid moves the given player can make.
  3.     dupeBoard = getBoardCopy(board)
  4.     for x, y in getValidMoves(dupeBoard, letter):
  5.         dupeBoard[x][y] = '.'
  6.     return dupeBoard
  1. def getValidMoves(board, letter):
  2.     # Returns a list of [x,y] lists of valid moves for the given player on the given board.
  3.     validMoves = []
  4.     for x in range(8):
  5.         for y in range(8):
  6.             if isValidMove(board, letter, x, y):
  7.                 validMoves.append([x, y])
  8.     return validMoves
  1. def getScoreOfBoard(board):
  2.     # Determine the score. Returns a dictionary with keys 'X' and 'O'.
  3.     xscore = 0
  4.     oscore = 0
  5.     for x in range(8):
  6.         for y in range(8):
  1.             if board[x][y] == 'X':
  2.                 xscore += 1
  3.             if board[x][y] == 'O':
  4.                 oscore += 1
  5.     return {'X':xscore, 'O':oscore}
  1. def enterPlayerLetter():
  2.     # Let's the player type which letter they want to be.
  3.     # Returns a list with the player's letter as the first item, and the computer's letter as the second.
  4.     letter = ''
  5.     while not (letter == 'X' or letter == 'O'):
  6.         print 'Do you want to be X or O?'
  7.         letter = raw_input().upper()
  1.     # the first element in the tuple is the player's letter, the second is the computer's letter.
  2.     if letter == 'X':
  3.         return ['X', 'O']
  4.     else:
  5.         return ['O', 'X']
  1. def whoGoesFirst():
  2.     # Randomly choose the player who goes first.
  3.     if random.randint(0, 1) == 0:
  4.         return 'computer'
  5.     else:
  6.         return 'player'
  1. def playAgain():
  2.     # This function returns True if the player wants to play again, otherwise it returns False.
  3.     print 'Do you want to play again? (yes or no)'
  4.     return raw_input().lower().startswith('y')
  1. def makeMove(board, letter, startx, starty):
  2.     # Place the letter on the board at startx, starty, and flip any of the opponent's pieces.
  3.     # Returns False if this is an invalid move, returns True if it is valid.
  4.     if not isValidMove(board, letter, startx, starty):
  5.         return False
  1.     board[startx][starty] = letter
  2.     directions = [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]
  3.     if letter == 'X':
  4.         otherLetter = 'O'
  5.     else:
  6.         otherLetter = 'X'
  1.     for d in directions:
  2.         DX = d[0]
  3.         DY = d[1]
  4.         x, y = startx, starty
  5.         x += DX
  6.         y += DY
  1.         if isOnBoard(x, y):
  2.             if board[x][y] == otherLetter:
  3.                 # There is a piece belonging to the other player next to our piece.
  4.                 x += DX
  5.                 y += DY
  1.                 if not isOnBoard(x, y):
  2.                     continue
  1.                 while board[x][y] == otherLetter:
  2.                     x += DX
  3.                     y += DY
  1.                     if not isOnBoard(x, y): # break, then continue
  2.                         break
  3.                 if not isOnBoard(x, y):
  4.                     continue
  1.                 if board[x][y] == letter:
  2.                     # There are pieces to flip over. Go in the reverse direction.
  3.                     while True:
  4.                         x -= DX
  5.                         y -= DY
  6.                         if x == startx and y == starty:
  7.                             break
  8.                         board[x][y] = letter
  9.     return True
  1. def getBoardCopy(board):
  2.     # Make a duplicate of the board list and return the duplicate.
  3.     dupeBoard = getNewBoard()
  4.     for x in range(8):
  5.         for y in range(8):
  6.             dupeBoard[x][y] = board[x][y]
  7.     return dupeBoard
  1. def isOnCorner(x, y):
  2.     # Returns True if the position is in one of the four corners.
  3.     return (x == 0 and y == 0) or (x == 7 and y == 0) or (x == 0 and y == 7) or (x == 7 and y == 7)
  1. def isSpaceFree(board, x, y):
  2.     # Return true if the passed move is free on the passed board.
  3.     return board[x][y] == ' '
  1. def getPlayerMove(board, playerLetter):
  2.     # Let the player type in their move.
  3.     # Returns the move as [x, y] (or returns the strings 'hints' or 'quits')
  4.     digits1to8 = '1 2 3 4 5 6 7 8'.split()
  5.     move = ''
  1.     while True:
  2.         print 'Enter your move, or type quit to end the game, or hints to turn off/on hints.'
  3.         move = raw_input()
  4.         if move.lower() == 'quit':
  5.             return 'quit'
  6.         if move.lower() == 'hints':
  7.             return 'hints'
  1.         if len(move) == 2 and move[0] in digits1to8 and move[1] in digits1to8:
  2.             x = int(move[0]) - 1
  3.             y = int(move[1]) - 1
  4.             if not isValidMove(board, playerLetter, x, y):
  5.                 continue
  6.             else:
  7.                 break
  1.         else:
  2.             print 'That is not a valid move. Type the x digit (1-8), then the y digit (1-8).'
  3.             print 'For example, 81 will be the top-right corner.'    
  1.     return [x, y]
  1. def getComputerMove(board, computerLetter):
  2.     # Given a board and the computer's letter, determine where to
  3.     # move and return that move as a [x, y] list.
  4.     if computerLetter == 'X':
  5.         playerLetter = 'O'
  6.     else:
  7.         playerLetter = 'X'
  8.     possibleMoves = getValidMoves(board, computerLetter)
  1.     # create a list of moves that are in the corners, and
  2.     # always go for a corner if available.
  3.     cornerMoves = []
  4.     for move in possibleMoves:
  5.         if isOnCorner(move[0], move[1]):
  6.             cornerMoves.append(move)
  7.     if len(cornerMoves) > 0:
  8.         return random.choice(getHighestScoringMoves(board, computerLetter, cornerMoves))
  1.     # From the list of highest scoring moves, choose one at random.
  2.     return random.choice(getHighestScoringMoves(board, computerLetter, possibleMoves))
  1. def getHighestScoringMoves(board, letter, moves):
  2.     # Returns a list of the highest scoring moves from the list of moves.
  3.     # For example, if out of the list of six moves, the highest scoring move gives
  4.     # five more points, but there are three different moves that give five more points,
  5.     # then return a list with those three moves.
  6.     if len(moves) == 1:
  7.         return moves
  8.     currentScore = getScoreOfBoard(board)[letter]
  9.     bestScore = -1
  10.     allScores = []
  1.     for i in range(len(moves)):
  2.         dupeBoard = getBoardCopy(board)
  3.         makeMove(dupeBoard, letter, moves[i][0], moves[i][1])
  4.         scoreIncrease = getScoreOfBoard(dupeBoard)[letter] - currentScore
  5.         allScores.append(scoreIncrease)
  6.         if scoreIncrease > bestScore:
  7.             bestScore = scoreIncrease
  1.     topMoves = []
  2.     for i in range(len(allScores)):
  3.         if allScores[i] == bestScore:
  4.             topMoves.append(moves[i])
  1.     return topMoves
  1. def isBoardDone(board, letter):
  2.     # Return True if the player with the given letter can make a move on the board. Otherwise return False.
  3.     if getValidMoves(board, letter) == []:
  4.         return True
  1.     for x in range(8):
  2.         for y in range(8):
  3.             if board[x][y] == ' ':
  4.                 return False
  5.     return True
  1. def showPoints(playerLetter, computerLetter):
  2.     # Prints out the current score.
  3.     scores = getScoreOfBoard(theBoard)
  4.     print 'You have %s points. The computer has %s points.' % (scores[playerLetter], scores[computerLetter])
  1. print 'Welcome to Othello!'
  2. while True:
  3.     # Reset the board and game.
  4.     theBoard = getNewBoard()
  5.     resetBoard(theBoard)
  6.     playerLetter, computerLetter = enterPlayerLetter()
  7.     showHints = False
  8.     turn = whoGoesFirst()
  9.     print 'The ' + turn + ' will go first.'
  1.     while True
  2.         if turn == 'player':
  3.             # Player's turn.
  4.             if showHints:
  5.                 validMovesBoard = getBoardWithValidMoves(theBoard, playerLetter)
  6.                 drawBoard(validMovesBoard)
  7.             else:
  8.                 drawBoard(theBoard)
  1.             showPoints(playerLetter, computerLetter)
  2.             move = getPlayerMove(theBoard, playerLetter)
  1.             if move == 'quit':
  2.                 print 'Thanks for playing!'
  3.                 sys.exit() # terminate the program
  4.             elif move == 'hints':
  5.                 showHints = not showHints
  6.                 continue
  7.             else:
  8.                 x, y = move
  9.             makeMove(theBoard, playerLetter, x, y)
  1.             if isBoardDone(theBoard, computerLetter): # computerLetter, not playerLetter
  2.                 break
  3.             else:
  4.                 turn = 'computer'
  1.         else:
  2.             # Computer's turn.
  3.             x, y = getComputerMove(theBoard, computerLetter)
  4.             drawBoard(theBoard)
  5.             showPoints(playerLetter, computerLetter)
  6.             raw_input('Press Enter to see the computer\'s move.')
  7.             makeMove(theBoard, computerLetter, x, y)
  1.             if isBoardDone(theBoard, playerLetter): # playerLetter, not computerLetter
  2.                 break
  3.             else:
  4.                 turn = 'player'
  1.     # Display the final score.
  2.     scores = getScoreOfBoard(theBoard)
  3.     print 'X scored %s points. O scored %s points.' % (scores['X'], scores['O'])
  4.     if scores[playerLetter] > scores[computerLetter]:
  5.         print 'You beat the computer by %s points! Congratulations!' % (scores[playerLetter] - scores[computerLetter])
  6.     elif scores[playerLetter] < scores[computerLetter]:
  7.         print 'You lost. The computer beat you by %s points.' % (scores[computerLetter] - scores[playerLetter])
  8.     else:
  9.         print 'The game was a tie!'
  1.     if not playAgain():
  2.         break

Things Covered In This Chapter: