connect_four
unknown
python
3 years ago
6.4 kB
2
Indexable
Never
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("")