[Tutor] Reversi Game Logic

niyanaxx95 at gmail.com niyanaxx95 at gmail.com
Fri Mar 20 23:20:53 CET 2015


Thank you Danny Yoo for replying. 

I figured out what to do for the isLegalMove but I ran into another problem. I now get a traceback error every chip is black.

This is the traceback:

Traceback (most recent call last):
  File "C:\Python34\lib\tkinter\__init__.py", line 1487, in __call__
    return self.func(*args)
  File "u:\code\reversiguiapp.py", line 83, in _cbMouseClick
TypeError: makeMove() takes 2 positional arguments but 3 were given
Exception in Tkinter callback




Here is my code again just in case:

from ezarrays import Array2D




# Values representing the color of the chips on the board.
EMPTY = 0
BLACK = 1
WHITE = 2




class ReversiGameLogic :
  
  # Creates an instance of Reversi game logic with the board correctly
  # initialized and the current player set to black.
  def __init__(self) :
     # Use a 2-D array to represent the board.
    self._gameBoard = Array2D(8, 8)
    self._gameBoard.clear(EMPTY)
    
     # Set the initial configuration of the board.
    self._gameBoard[4,3] = BLACK
    self._gameBoard[3,4] = BLACK
    self._gameBoard[3,3] = WHITE
    self._gameBoard[4,4] = WHITE




     # Maintain the number of the current player.
    self._currentPlayer = BLACK
    
     # Keep track of the number of each players chips.
    self._numBlackChips = 2
    self._numWhiteChips = 2
    
     # A flag that is set when the game is over. That is, when there are
     # no empty squares on the board or neither player can make a move.
    self._gameOver = False
    
  # Returns a boolean indicating whether the game is over.
  def isOver(self) :
    isOver = 0
    for i in range(8) :
      for j in range(8) :
        if self._gameBoard[i, j] != 0 :
          isOver = isOver + 1
    if isOver == 64 :
        self._gameOver = True
        return True
    else:
        return False




    
  # Returns the player number of the current player.
  def whoseTurn(self) :
    if self._currentPlayer == 1:
      return 1
    else:
      self._curentPlayer == 2
    return 2
      
    
  # Returns the number of chips on the board for the given player.
  def numChips(self, player) :
    chipCounter = 0
    if player == 1 :
      for i in range(8) :
        for j in range(8) :
          if self._gameBoard[i, j] == BLACK :
            chipCounter = chipCounter + 1
    else : 
      for i in range(8) :
        for j in range(8) :
          if self._gameBoard[i, j] == WHITE :
            chipCounter = chipCounter + 1 
    return chipCounter
    
  # Returns the number of open squares on the board.
  def numOpenSquares(self) :
    numOpenSquares = 0
    for i in range(8) :
      for j in range(8) :
        if self._gameBoard[i, j] == EMPTY :
          numOpenSquares =  numOpenSquares + 1
    return numOpenSquares
    
  # Returns the player number of the winner or 0 if it's a draw.
  def getWinner( self ):
    player1 = 0
    player2 = 0
    if self._gameOver is True :
      for i in range(8) :
        for j in range(8) :
          if self._gameBoard[i, j] == BLACK :
            player1 = player1 + 1
          else :
            player2 = player2 + 1
      if player1 > player2 :
        return 1
      if player2 > player1 :
        return 2
      else:
        return 0
  
   # Returns the Return a Boolean indicating if the current player can place
   # their chip in the square at position (row, col). Both row and col must be
   # valid indices
  def isLegalMove( self, row, col ):
    if row < 0 or row >= 8 or col < 0 or col >= 8:
        return False
    if self._gameBoard[row,col] == EMPTY:
        return True
    else:
        return False
  
     
  
   # Returns the player number whose chip occupies the given square.
  def occupiedBy(self, row, col):
    if self._gameBoard[row, col] == BLACK :
      return 1
    if self._gameBoard[row, col] == WHITE :
      return 2
    else:
      return 0




  # Performs an actual move in the game. That is the current player places
  # one of his chips in the square at position (row, col).
  def makeMove( row, col ):
    if isALineOfAttack(row, col, 1, 1) is True :
      if self._currentPlayer == 1 :
        self._gameBoard[row, col] = BLACK
      else :
        self._gameBoard[row, col] = WHITE 
      
        
         
    

















   # Helper method that returns a Boolean indicating if there is a line of
   # attack from cell (row, col) in the direction offset given by rowInc
   # and colInc. The direction offsets should be, 0, 1, or -1.
  def _isALineOfAttack(self, row, col, rowInc, colInc) :
    row += rowInc
    col += colInc
     # The next cell in the line must contain the opponents chip.  
    if self.occupiedBy(row, col) == self._currentPlayer :
      return False
    
     # Traverse along the line and determine if it's a line of attack.
    while row >= 0 and col >= 0 and row < 8 and col < 8 :
      if self.occupiedBy(row, col) == self._currentPlayer :
        return True
      elif self.occupiedBy(row, col) == EMPTY :
        return False
      else :
        row += rowInc
        col += colInc
        if row < 0 or row > 7 or col < 0 or col > 7 :
              return False      
    return False







Sent from Windows Mail





From: Danny Yoo
Sent: ‎Friday‎, ‎March‎ ‎20‎, ‎2015 ‎2‎:‎22‎ ‎PM
To: Ni'Yana Morgan
Cc: tutor at python.org





>
> So let's say that in the unit tests.  Add assertions that we want
> those four starred points to be legal moves.
>
> #############################################
> import unittest
>
> class ReversiTests(unittest.TestCase):
>     def testIslegalMoveOnExistingSpots(self):
>         logic = ReversiGameLogic()
>         # Placing on existing spots should not be legal.
>         self.assertFalse(logic.isLegalMove(4, 3))
>         self.assertFalse(logic.isLegalMove(3, 4))
>         self.assertFalse(logic.isLegalMove(3, 3))
>         self.assertFalse(logic.isLegalMove(4, 4))
>
>
>     def testIsLegalMoveGood(self):
>         logic = ReversiGameLogic()
>         # But here are spots that should be legal.
>         self.assertTrue(logic.isLegalMove(2, 3))
>         ...  ## fill me in with the other three legal moves!
>
>
> if __name__ == '__main__':
>     unittest.main()
> ##############################################


Sorry: I sent this draft a bit too early!  There really should be at
least one more test that we need to have;  we need to check for moves
that are not legal, but for fundamental Reversi-based reasons.

For example, we *know* that playing on (1, 1) can't be legal when the
game is starting: it's an empty spot on the board, but it's not
adjacent to a line of white pieces.

This is the sort of thing that would be an appropriate to write as a test:

###################################################
import unittest

class ReversiTests(unittest.TestCase):
    def testIslegalMoveOnExistingSpots(self):
        logic = ReversiGameLogic()
        # Placing on existing spots should not be legal.
        self.assertFalse(logic.isLegalMove(4, 3))
        self.assertFalse(logic.isLegalMove(3, 4))
        self.assertFalse(logic.isLegalMove(3, 3))
        self.assertFalse(logic.isLegalMove(4, 4))


    def testIsLegalMoveGood(self):
        logic = ReversiGameLogic()
        # But here are spots that should be legal.
        self.assertTrue(logic.isLegalMove(2, 3))
        ## ... fill me in with the other three legal moves!


    def testIsLegalMoveNotAdjacentAttackLine(self):
        logic = ReversiGameLogic()
        # But here is a spot that should be illegal.
        self.assertTrue(logic.isLegalMove(1, 1))


if __name__ == '__main__':
    unittest.main()
####################################################


You'll should see that one of the tests is succeeding, which is great!
 That's what you want to see: partial success.   It means that you're
going in the right direction, and that you just need to amend what
you've got so far.


It should also point out two concrete ways in which your program isn't
quite working yet.


More information about the Tutor mailing list