connect_four
unknown
python
4 years ago
6.4 kB
11
Indexable
class Connect_N_State:
# Define all the required attributes to be private
def __init__(self,wid,hei, target, players):
self.__width = wid
self.__height = hei
self.__target = target
self.__players = players
self.__board = [["." for _ in range(self.__width)] for _ in range(self.__height)]
self.__player_char = dict(zip(list(map(lambda x:x[0],self.__players)),self.__players))
self.__current_player_idx = 0
# define the methods
def get_size(self):
return (self.__width,self.__height)
def get_target(self):
return self.__target
def get_player_list(self):
return self.__players.copy()
# helper methods for simplifing the code in the required methods
def get_player_idx(self,char):
idxs = [(rowIdx,colIdx) for rowIdx,row in enumerate(self.__board) for colIdx,column in enumerate(row) if column == char]
return idxs
def is_game_over(self):
for player_char,player in self.__player_char.items():
# Check if current player has acheived the target
player_idx = self.get_player_idx(player_char)
target = self.__target
for y,x in player_idx:
# Check across rows and columns if there are any matches for the palyer
if x+self.__target < self.__width:
check_win = set(self.__board[y][x:x+target]) == set(player_char)
if check_win:
return True
if y+self.__target < self.__height:
# zip(*self.__board) iterates along columns
# so mapping to list gives us transposed version of board
transpose_board = list(map(list, zip(*self.__board)))
check_win = set(transpose_board[x][y:y+target]) == set(player_char)
if check_win:
return True
if x-self.__target>=0:
check_win = set(self.__board[y][x:x-target]) == set(player_char)
if check_win:
return True
if y-self.__target >= 0:
transpose_board = list(map(list, zip(*self.__board)))
check_win = set(transpose_board[x][y:y-target]) == set(player_char)
if check_win:
return True
# check along diagnols
diag_steps = [[(1,1),(-1,-1)],[(-1,1),(1,-1)]]
for diagnol in diag_steps:
current_x = x
current_y = y
seen = []
for step_x,step_y in diagnol:
diag_seen = []
while current_x>=0 and current_x<self.__width and current_y>=0 and current_y<self.__height and self.__board[current_y][current_x] == player_char:
if self.__board[current_y][current_x] == player_char:
diag_seen.append(self.__board[current_y][current_x])
current_x+=step_x
current_y+=step_y
else:
break
seen=diag_seen+seen
if all(set(seen[i:i+target]) == set(player_char ) for i in range(len(seen)-target)) and len(seen) >= target:
# print("From here")
return True
# check is board is full
return self.is_board_full()
def get_winner(self):
for player_char,player in self.__player_char.items():
# Check if current player has acheived the target
player_idx = self.get_player_idx(player_char)
target = self.__target
for y,x in player_idx:
# Check across rows and columns if there are any matches for the palyer
if x+self.__target < self.__width:
check_win = set(self.__board[y][x:x+target]) == set(player_char)
if check_win:
return player
if y+self.__target < self.__height:
transpose_board = list(map(list, zip(*self.__board)))
check_win = set(transpose_board[x][y:y+target]) == set(player_char)
if check_win:
return player
if x-self.__target>=0:
check_win = set(self.__board[y][x:x-target]) == set(player_char)
if check_win:
return player
if y-self.__target >= 0:
transpose_board = list(map(list, zip(*self.__board)))
check_win = set(transpose_board[x][y:y-target]) == set(player_char)
if check_win:
return player
# check across diagnols
diag_steps = [[(1,1),(-1,-1)],[(-1,1),(1,-1)]]
for diagnol in diag_steps:
current_x = x
current_y = y
seen = []
for step_x,step_y in diagnol:
diag_seen = []
while current_x>=0 and current_x<self.__width and current_y>=0 and current_y<self.__height and self.__board[current_y][current_x] == player_char:
diag_seen.append(self.__board[current_y][current_x])
current_x+=step_x
current_y+=step_y
seen=diag_seen+seen
if all(seen[i:i+target] == player_char for i in range(len(seen)-target)):
return player
# return None in case of no winner
return None
# Check board is full
def is_board_full(self):
return not any(column == "." for row in self.__board for column in row)
# Check column is full
def is_column_full(self,col):
# *self.__board iterates along columns
# so mapping to list gives us transposed version of board
transposed_board = list(map(list, zip(*self.__board)))
return all(value!="." for value in transposed_board[col])
# Get the current cell player character
def get_cell(self, x,y):
return self.__player_char[self.__board[y][x]] if self.__board[y][x] != "." else None
# return the current player index
def get_cur_player(self):
if not self.is_game_over() :
return self.__players[self.__current_player_idx]
def move(self,col):
# check column is full
if not self.is_column_full(col):
# Get the current player
player_char = self.get_cur_player()[0]
transposed_board = list(map(list, zip(*self.__board)))
# Place the player char as per the move
col_data = reversed(transposed_board[col])
for idx,col_value in enumerate(col_data):
if col_value == ".":
# print(idx)
self.__board[self.__height-idx-1][col] = player_char
self.__current_player_idx = ((self.__current_player_idx+1)%len(self.get_player_list()))
return True
return False
# Print the board as stated in requirements
def print(self):
for row in self.__board:
for column in row:
print(column,end="")
print("")
Editor is loading...