[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