diff --git a/classes/__init__.py b/classes/__init__.py old mode 100644 new mode 100755 diff --git a/classes/board.py b/classes/board.py old mode 100644 new mode 100755 index 371f696..15649df --- a/classes/board.py +++ b/classes/board.py @@ -8,11 +8,12 @@ def __init__(self, cols = 6, rows = 7, required_to_win = 4): self.cols = cols self.rows = rows self.win = required_to_win + #set all the squares to none symbol self.board = [[self.NONE] * rows for col in range(cols)] def __str__(self): b = '\n' - for row in self.board: + for row in self.board: #we add all the rows from the board to b b += ''.join(row) + '\n' - b += " 0 1 2 3 4 5 6 \n" + b += " 0 1 2 3 4 5 6 \n" #add labels to each of the columns return b diff --git a/classes/exceptions.py b/classes/exceptions.py old mode 100644 new mode 100755 diff --git a/classes/game.py b/classes/game.py old mode 100644 new mode 100755 index 1f458f5..43cabc5 --- a/classes/game.py +++ b/classes/game.py @@ -1,87 +1,83 @@ from sys import exit - from . import winchecker - +#in this class we are defining all the general movement functions for the game class Game: - P1 = 'P1' P2 = 'P2' - - def __init__(self, board): - self.current_player = self.P1 - self.board = board - self.winchecker = winchecker.WinChecker(game=self, board=self.board) + + def __init__(self, board): #function used to initially setup the game + + self.current_player = self.P1 #set the first player to move as P1 + self.board = board #set local board to equal the input board + self.winchecker = winchecker.WinChecker(game=self, board=self.board) #initiate the winchecker class and pass in the current game and board print("Welcome to connect four! ") - self.make_move() - - def make_move(self): - print("{}\n{}, you're up! ".format(self.board, self.current_player)) - column_choice = self.get_column_choice() + self.make_move() #start game by calling for the first move - valid_column = self.place_checker(column=column_choice) - if not valid_column: - print("That column is full. Please enter a non-full column. ") - self.make_move() + def make_move(self): #this function will be used to get user input and make the necessary changes to the board + print("{}\n{}, you're up! ".format(self.board, self.current_player)) # ask current player to make a move + column_choice = self.get_column_choice() #get players move from function get_column_choice and store it + valid_column = self.place_checker(column=column_choice) #place the piece using place_checker function with the selected column + if not valid_column: #make sure it is legal + print("That column is full. Please enter a non-full column. ") #if column is not legal, tell the user + self.make_move() #call make_move again in order to make the user make a legal move return False - win = True if self.check_for_win() else False - if not win: + win = True if self.check_for_win() else False #check if a player has won the game using check_for_win function + if not win: #if they did not win then change players and begin their turn self.toggle_players() self.make_move() - if win: + if win: #if a player has won then print the board and congratulate the winner print(self.board) print("\ncongratulations {}, you win!\n".format(self.current_player)) - - def get_column_choice(self): + + def get_column_choice(self): #function used to get the users move print("What column what you like to place your piece?\n") column_choice = input("Valid choices are columns 0 through 6: ") try: - if column_choice == "exit": exit() - column_choice = int(column_choice) - return column_choice if 0 <= column_choice <= 6 else self.get_column_choice() - except ValueError: + if column_choice == "exit": exit() #if player hits exit then quit + column_choice = int(column_choice) #otherwise store the column they chose + return column_choice if 0 <= column_choice <= 6 else self.get_column_choice() #if the user chose a location outside the board then get new input + except ValueError: #if player entered incorrect character then restart function return self.get_column_choice() - - def place_checker(self, column): - print("You've selected column {}".format(column)) - - if(self.board.board[0][column] != ' . '): + + def place_checker(self, column): #this function will find the location for the piece the user has placed and put a piece there + print("You've selected column {}".format(column)) #tell the player what column they selected + if(self.board.board[0][column] != ' . '): #check to see if that column is full # column is full, force player to re-choose return False - lowest_available_row = self.find_lowest_row_in_column(column=column) + lowest_available_row = self.find_lowest_row_in_column(column=column) #find the lowest position in the chosen column try: - self.board.board[lowest_available_row][column] = self.players_piece() + self.board.board[lowest_available_row][column] = self.players_piece() #place the players piece in that position return True - except IndexError: + except IndexError: #just in case there is a array error we can catch it # this should never happen print("Array out of bounds error! Exiting...") exit() - - def find_lowest_row_in_column(self, column): + + def find_lowest_row_in_column(self, column): #this function actually finds the next location in the selected column column_as_list = [] - for row in self.board.board: - column_as_list.append(row[column]) - + for row in self.board.board: #loop through all the rows in the board + column_as_list.append(row[column]) #add all these values to the array try: - first_red = column_as_list.index(self.board.RED) - 1 + first_red = column_as_list.index(self.board.RED) - 1 #find location above first red piece in the column except ValueError: - first_red = None + first_red = None #set it to none if there are no red pieces try: - first_blue = column_as_list.index(self.board.BLUE) - 1 + first_blue = column_as_list.index(self.board.BLUE) - 1 #find the location above first blue piece in the column except ValueError: - first_blue = None + first_blue = None #set it to none if there are no blue pieces if first_blue == None and first_red == None: - return 5 - elif first_blue == None or first_red == None: - return first_blue if first_blue != None else first_red + return 5 #if there are no pieces in the column then our row value is 5 + elif first_blue == None or first_red == None: + return first_blue if first_blue != None else first_red # if there is only one colour then send the location above the highest one else: - return min(first_blue, first_red) + return min(first_blue, first_red) #if there are two colours then send the location above the highest piece - def check_for_win(self): + def check_for_win(self): #this function simply checks to see if there is a winner using the winchecker class return self.winchecker.check_for_win() - def toggle_players(self): + def toggle_players(self): #this function changes which player's turn it is self.current_player = self.P2 if self.current_player == self.P1 else self.P1 - def players_piece(self): + def players_piece(self): #this function returns the colour of the current players pieces return self.board.RED if self.current_player == self.P1 else self.board.BLUE diff --git a/classes/winchecker.py b/classes/winchecker.py old mode 100644 new mode 100755 index b9a8a7c..5fb0807 --- a/classes/winchecker.py +++ b/classes/winchecker.py @@ -1,37 +1,37 @@ class WinChecker: - + #this class is used to see if a player has connected four pieces def __init__(self, game, board): self.game = game self.board = board - def check_for_win(self): + def check_for_win(self): #function is used to call the functions that check for different ways of winning results = [] - results.append(self.check_win_horizontally()) + results.append(self.check_win_horizontally()) #append true if there is a win or append false if there is not results.append(self.check_win_vertically()) results.append(self.check_win_diagonally_1()) results.append(self.check_win_diagonally_2()) try: results.index(True) - # if the above statement does not generate a ValueError, then a win exists + # if the above statement does not generate a ValueError, then a win exists with except ValueError return True except ValueError: return False - def check_win_horizontally(self): + def check_win_horizontally(self): #this functions checks to see if 4 are connected in any of the rows win = False - for i in range(self.board.rows): + for i in range(self.board.rows): #we must loop through each of the rows row = i cols = [0, 1, 2, 3] - while not win: + while not win: #keep looping until win is changed to true try: # seq will represent the current 4 squares being examined seq = [] for i in range(len(cols)): # append current 4 squares to seq list seq.append(self.board.board[row][cols[i]]) - if self.check_equal(seq): - return True + if self.check_equal(seq): #check to see if all 4 pieces are the same + return True #if they are then we have a winner else: # increment each value in cols, this is how the horizontal # win checking progresses from left to right @@ -46,7 +46,7 @@ def check_win_horizontally(self): def check_win_vertically(self): win = False - for i in range(self.board.cols): + for i in range(self.board.cols):#we must check all the columns col = i rows = [0, 1, 2, 3] while not win: @@ -56,7 +56,7 @@ def check_win_vertically(self): for i in range(len(rows)): # append current 4 squares to seq list seq.append(self.board.board[rows[i]][col]) - if self.check_equal(seq): + if self.check_equal(seq): #if all 4 are the same then we have a winner return True else: # increment each value in rows, this is how the horizontal @@ -70,10 +70,10 @@ def check_win_vertically(self): return win - def check_win_diagonally_1(self): + def check_win_diagonally_1(self):#this function checks for diagonals from top left toward bottom right win = False - for i in range(self.board.cols): + for i in range(self.board.cols): col = i cols = [col, col+1, col+2, col+3] rows = [0, 1, 2, 3] @@ -84,13 +84,13 @@ def check_win_diagonally_1(self): for i in range(len(rows)): # append current 4 squares to seq list seq.append(self.board.board[rows[i]][cols[i]]) - if self.check_equal(seq): + if self.check_equal(seq): #check to see if all the squares match return True else: # increment each value in rows, this is how the diagonal # win checking progresses from top to bottom for i in range(len(rows)): - rows[i] += 1 + rows[i] += 1 #we must increment all the row values as we move our diagonal toward the bottom of the board continue except IndexError: # we've hit the end of this col, break the loop and move to the next col @@ -98,7 +98,7 @@ def check_win_diagonally_1(self): return win - def check_win_diagonally_2(self): + def check_win_diagonally_2(self): #this function checks for diagonals from bottom left toward top right win = False for i in range(self.board.cols): @@ -112,13 +112,13 @@ def check_win_diagonally_2(self): for i in range(len(rows)): # append current 4 squares to seq list seq.append(self.board.board[rows[i]][cols[i]]) - if self.check_equal(seq): + if self.check_equal(seq): #check to see if all the squares match return True else: # increment each value in rows, this is how the diagonal # win checking progresses from top to bottom for i in range(len(rows)): - rows[i] -= 1 + rows[i] -= 1 #we must decrement all the row values as we move our diagonal toward the top of the board continue except IndexError: # we've hit the end of this col, break the loop and move to the next col @@ -126,5 +126,5 @@ def check_win_diagonally_2(self): return win - def check_equal(self, lst): + def check_equal(self, lst): #this function checks to see if all the pieces in the array are equal and not None return lst[1:] == lst[:-1] if lst[0] != self.board.NONE else False diff --git a/connectfour.py b/connectfour.py old mode 100644 new mode 100755 index 85fed80..83d30f2 --- a/connectfour.py +++ b/connectfour.py @@ -1,9 +1,11 @@ from classes import board, game, exceptions - play_again = "yes" +#This file initiates the first game and board +#once the game is done, it will see if the player would like to continue playing -# game loop while play_again == "yes": b = board.Board() + #initiate a game with board b g = game.Game(board=b) + #check to see if the player would like to play again and store answer to play_again play_again = input("Would you like to play again? Enter yes to replay: ").lower().strip()