-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathboard.py
More file actions
151 lines (131 loc) · 5.92 KB
/
board.py
File metadata and controls
151 lines (131 loc) · 5.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
import pygame
pygame.init()
from constants import *
# Class for representing the board game board
class Board:
"""
A class used to represent the game board. It handles the interaction of the player with
the board
Attributes:
- _window - The pygame window used for the UI
- _board - A 2D list used to represent the game board
"""
def __init__(self, newBoard, currentBoardState, window):
self._window = window
if newBoard: # Set the board to the initial state if a new game is started
self._resetBoard()
else: # Set the game to the existing state if it is not a new game
self._board = currentBoardState
# Set up the initial board state
def _resetBoard(self):
self._board = [[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 2, 1, 0, 0, 0],
[0, 0, 0, 1, 2, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 0]]
return 0
# Converts the array of the board into a string
def arrayToString(self):
boardString = []
for row in self._board:
for column in row:
boardString.append(str(column))
return "".join(boardString)
# Calculate and return the number counters that player 1 and player 2 have
def getScore(self):
p1Score = p2Score = 0
for row in self._board:
for cell in row:
if cell == 1:
p1Score += 1
elif cell == 2:
p2Score += 1
return p1Score, p2Score
# Return the winner of the game based on the scores of each player
def getWinner(self):
p1Score, p2Score = self.getScore()
if p1Score > p2Score:
return 1
elif p2Score > p1Score:
return 2
else:
return 0
# Check if the game is over by checking for any empty cells
def gameOver(self):
for row in self._board:
for cell in row:
if cell == 0:
return False
return self.getWinner()
# Make a move on the board for a specified player by placing the counter and flipping any
# relevant counters
def makeMove(self, player, row, column):
if (row, column) in self.getValidMoves(player):
self._board[row][column] = player
self._flipCounters(player, row, column)
return True
else:
return False
# Create a copy of the board with a simulated move for analysis by the AI
def makeMoveOnCopy(self, player, row, column):
boardCopy = [row[:] for row in self._board]
boardCopy[row][column] = player
copyOfBoard = Board(False, boardCopy, self._window)
return copyOfBoard.getBoard()
# Return all the available moves of a particular player
def getValidMoves(self, player):
cells = [(row, column) for row in range(8) for column in range(8)]
validMoves = []
# Iterate through all cells and check if it is a valid move
for row, column in cells:
if self._checkMove(player, row, column):
validMoves.append((row, column))
return validMoves
# Check if a move is valid by checking for counters to flip in all directions
def _checkMove(self, player, row, column):
if self._board[row][column] != 0:
return False
directions = [(rowDelta, colDelta) for rowDelta in range(-1, 2) for colDelta in range(-1, 2)
if rowDelta != 0 or colDelta != 0]
# Iterates through all directions checking if they are valid
for rowDelta, colDelta in directions:
if self._isValidDirection(row, column, rowDelta, colDelta, player):
return True
return False
# Checks if a direction is valid for placing a counter in by recursively calling itself unitl
# it is or isn't valid
def _isValidDirection(self, startRow, startCol, rowDelta, colDelta, player,
foundOpponent=False):
currentRow = startRow + rowDelta
currentCol = startCol + colDelta
if not (0 <= currentRow < 8 and 0 <= currentCol < 8): # Invalid if out of bounds
return False
currentPiece = self._board[currentRow][currentCol]
if currentPiece == 0: # Invalid if empty cell
return False
if currentPiece == player: # Valid if an opponenets piece is found
return foundOpponent
# If no conclusion is made, keep checking in the same direction
return self._isValidDirection(currentRow, currentCol, rowDelta, colDelta, player, True)
# Flips all the counters after a move is made
def _flipCounters(self, player, row, column):
directions = [(rowDelta, colDelta) for rowDelta in range(-1, 2) for colDelta in range(-1, 2)
if rowDelta != 0 or colDelta != 0]
for rowDelta, colDelta in directions:
# Only start flipping if the direction is valid for placing counters in
if self._isValidDirection(row, column, rowDelta, colDelta, player):
currentRow, currentCol = row + rowDelta, column + colDelta
while self._board[currentRow][currentCol] != player:
self._board[currentRow][currentCol] = player
currentRow += rowDelta
currentCol += colDelta
return 0
# Returns the board
def getBoard(self):
return self._board
# Returns the window
def getWindow(self):
return self._window