def test_MakeMoveInvalid(self): #Arrange myBoard = OthelloBoard(8,"_") expBoard = copy.deepcopy(myBoard.GameBoard) expCnt = {"B":2,"W":2,"_":60} #Act myBoard.makeMove("B",[5,3]) actBoard = myBoard.GameBoard actCnt = myBoard.PieceCount #Assert self.assertEqual(expBoard, actBoard, "An invalid move made a move") self.assertEqual(expCnt, actCnt, "Invalid piece count")
def test_ValidHorizL(self): #Arrange myBoard = OthelloBoard(8,"_") expBoard = copy.deepcopy(myBoard.GameBoard) expBoard[4][5] = "B" expBoard[4][4] = "B" expCnt = {"B":4,"W":1,"_":59} #Act myBoard.makeMove("B",[4,5]) actBoard = myBoard.GameBoard actCnt = myBoard.PieceCount #Assert self.assertEqual(expBoard, actBoard, "Invalid board") self.assertEqual(expCnt, actCnt, "Invalid piece count")
def test_GameEnd(self): #Arrange myBoard = OthelloBoard(8,"_") myBoard.PieceCount["W"] = 32 myBoard.PieceCount["B"] = 32 myBoard.PieceCount["_"] = 0 expWinner = "D" #Act actWinner = myBoard.checkWinner() #Assert self.assertEqual(expWinner, actWinner)
def test_ValidDiagUpR(self): #Arrange myBoard = OthelloBoard(8,"_") myBoard.GameBoard[2][5] = "W" myBoard.PieceCount["W"] = 3 myBoard.PieceCount["_"] = 59 expBoard = copy.deepcopy(myBoard.GameBoard) expBoard[4][3] = "W" expBoard[3][4] = "W" expBoard[5][2] = "W" expCnt = {"B":0,"W":6,"_":58} #Act myBoard.makeMove("W",[5,2]) actBoard = myBoard.GameBoard actCnt = myBoard.PieceCount #Assert self.assertEqual(expBoard, actBoard, "Invalid board") self.assertEqual(expCnt, actCnt, "Invalid piece count")
def test_Winner2(self): #Arrange myBoard = OthelloBoard(8,"_") myBoard.GameBoard[0] = ["B","B","B","B","B","B","W","W"] myBoard.GameBoard[1] = ["B","B","B","B","B","B","W","W"] myBoard.GameBoard[2] = ["B","W","B","B","B","B","W","W"] myBoard.GameBoard[3] = ["W","B","B","W","B","B","W","W"] myBoard.GameBoard[4] = ["W","W","W","W","B","B","W","W"] myBoard.GameBoard[5] = ["B","W","W","W","W","B","W","B"] myBoard.GameBoard[6] = ["B","B","W","W","W","W","B","_"] myBoard.GameBoard[7] = ["B","B","B","B","B","B","B","B"] myBoard.PieceCount["W"] = 25 myBoard.PieceCount["B"] = 38 myBoard.PieceCount["_"] = 1 expWinner = "B" #Act myBoard.makeMove("W",[6,7]) actWinner = myBoard.checkWinner() #Assert self.assertEqual(expWinner, actWinner)
def test_ValidFourDir(self): #Arrange myBoard = OthelloBoard(8,"_") myBoard.GameBoard[0] = ["_","_","_","_","_","_","_","_"] myBoard.GameBoard[1] = ["_","_","_","_","_","_","_","_"] myBoard.GameBoard[2] = ["_","_","_","_","_","W","_","_"] myBoard.GameBoard[3] = ["W","_","W","W","B","_","_","_"] myBoard.GameBoard[4] = ["_","B","B","B","W","_","_","_"] myBoard.GameBoard[5] = ["W","B","_","B","W","_","_","_"] myBoard.GameBoard[6] = ["_","B","B","B","_","_","_","_"] myBoard.GameBoard[7] = ["W","_","W","_","W","_","_","_"] myBoard.PieceCount["W"] = 10 myBoard.PieceCount["B"] = 9 myBoard.PieceCount["_"] = 45 expBoard = [] expBoard.append(["_","_","_","_","_","_","_","_"]) expBoard.append(["_","_","_","_","_","_","_","_"]) expBoard.append(["_","_","_","_","_","W","_","_"]) expBoard.append(["W","_","W","W","W","_","_","_"]) expBoard.append(["_","W","W","W","W","_","_","_"]) expBoard.append(["W","W","W","W","W","_","_","_"]) expBoard.append(["_","W","W","W","_","_","_","_"]) expBoard.append(["W","_","W","_","W","_","_","_"]) expCnt = {"B":0,"W":20,"_":44} #Act myBoard.makeMove("W",[5,2]) actBoard = myBoard.GameBoard actCnt = myBoard.PieceCount #Assert self.assertEqual(expBoard, actBoard, "Invalid board") self.assertEqual(expCnt, actCnt, "Invalid piece count")
class Othello(Game): turn = "B" delimeter = "_" boardSize = 8 # CONSTRUCTORS @MyLogger.log(["File"]) def __init__(self, gameMode=None, skipPlay=False): """ Create Othello game class. Optional to pass in gameMode (1 to play vs CPU, 2 to play vs Humans), dont't pass for user prompt """ print("\nWelcome to Othello!") # Get and validate game parameters from user or init try: self.numPlayers = self.getGameMode(gameMode, '^[1-2]$') except InvalidParameterException as IPEx: # Log and Quit MyLogger.logException(["DB"], IPEx) print(IPEx) raise self._initGame() # For testing dont want to start user prompts so skip if not skipPlay: self._playGame() # DEPRECATED, use __init__ with kwargs, leaving for info purposes only # ClassMethod constructor that does not call __init__ # used for testing to get around user input @classmethod @MyLogger.log(["File"]) def init(cls, gameMode): """ Alternate Othello constructor to pass in gameMode (1 to play vs CPU, 2 to play vs Humans) """ objOT = cls.__new__(cls) objOT.numPlayers = gameMode # cant do kwargs.get("gameMode", self.getGameMode()) because getGameMode method still runs to get default value #super(Othello, objOT).__init__(Othello.turn, Othello.boardSize, Othello.delimeter) objOT._initGame() return objOT # PROTECTED METHODS # Method to init game parameters common to all constructors @MyLogger.log(["File"]) def _initGame(self): super().__init__(Othello.turn, Othello.boardSize, Othello.delimeter) self.board = OthelloBoard(self.boardSize, self.delimeter) self._addPlayer("B", "Black") self._addPlayer("W", "White") # get next move from user or generate for cpu until game has ended @MyLogger.log(["File"]) def _playGame(self): self.board.printBoard() gameEnd = 0 while (not (gameEnd)): if self.numPlayers == 2 or self.turn == "B": coord = self._getMoveHuman() else: coord = self._getMoveCPU() print( f"{self.players[self.turn]} placed piece at {coord[0]} {coord[1]}\n" ) self.board.makeMove(self.turn, coord) self.board.printBoard() gameEnd = self.board.checkWinner() if gameEnd == "D": print("It's a DRAW!\n") elif gameEnd: print(f"{self.players[gameEnd]} WINS!\n") else: self.turn = self.board.Opp(self.turn) # Player chooses next move @MyLogger.log(["File"]) def _getMoveHuman(self): success = 0 while (not (success)): userInput = input( f"Enter coordinates for {self.players[self.turn]}: ") coord = userInput.split() if len(coord) != 2: print("You didnt enter 2 coordinates") else: Y = coord[0] X = coord[1] if (not (X.isdigit()) or int(X) >= self.boardSize): print( f"First coordinate is not an integer or less than {str(self.boardSize)}" ) elif (not (Y.isdigit()) or int(Y) >= self.boardSize): print( f"Second coordinate is not an integer or less than {str(self.boardSize)}" ) elif (not (self.board.validateMove(self.turn, coord))): print(f"Invalid move at coordinates: {str(coord)}") else: success = 1 return coord # get CPU move @MyLogger.log(["File"]) def _getMoveCPU(self): return self.board.getBestMove(self.turn)
def _initGame(self): super().__init__(Othello.turn, Othello.boardSize, Othello.delimeter) self.board = OthelloBoard(self.boardSize, self.delimeter) self._addPlayer("B", "Black") self._addPlayer("W", "White")