commit d9d64e4bab68c9e69afa248458fde404b5ad6a94 Author: wildscotsmen Date: Mon Apr 10 04:02:31 2017 -0400 First version. diff --git a/ConnectFour.py b/ConnectFour.py new file mode 100644 index 0000000..03d1dd1 --- /dev/null +++ b/ConnectFour.py @@ -0,0 +1,156 @@ +from GameLogic import * +from Parser import * + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" @author Jacob McCloughan +" @version 3/30/2017 +" @see GameLogic.py +" @see Parser.py +" +" This .py file includes the main method for our Connect +" Four game. +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +""" +" Main method for our Connect Four Game. Drives the entire +" game with a while loop, while also reading in command line +" arguments and initializing the game data. +""" +def main(): + # Variables + input = "" + chip = '' + setPlayer(1) + + # Checks command line arguments + if (results.height <= 0): + print "Error, height is invalid value. Setting to default." + else: + setHeight(results.height) + if (results.width <= 0): + print "Error, width is invalid value. Setting to default." + else: + setWidth(results.width) + if (results.connect <= 0): + print "Error, width is invalid value. Setting to default." + else: + setWinLength(results.connect) + if (results.square < -1 or results.square == 0): + print "Error, square is invalid value. Setting to default." + elif (results.square == -1): + pass + else: + setWidth(results.square) + setHeight(results.square) + if (results.loadName != None): + try: + loadGame(results.loadName) + except IOError: + print "Error reading file from command line." + return + else: + populateBoard() + + # Introductory game message + print "Welcome to Connect Four! Type 'stop' to stop, 'save' to save and 'load' to load." + + # The game loop + while(True): + # Sets the current chip based on the current player + if getPlayer() == 1: + chip = 'o' + if getPlayer() == 2: + chip = 'x' + printBoard() + + # Receives player input + print "\nIt is Player " + str(getPlayer()) + "'s turn." + input = raw_input("Input a column (from 1 to " + str(getWidth()) + + ") to place a token:\n") + + # Checks for any commands + if (str(input) == 'stop'): + return + if (str(input) == 'save'): + print "Type a filename to save to:" + input = raw_input() + saveGame(input) + print "Game saved." + continue + if (str(input) == 'load'): + print "Type a filename to load from:" + input = raw_input() + try: + loadGame(input) + except IOError: + print "Error loading file." + else: + print "Game loaded." + continue + try: + input = int(input) + except ValueError: + print "Invalid input. Try again." + continue + + # Attempts to place chip in desired column + input = input - 1 + if placeChip(input, chip) == False: + print "Invalid input. Try again." + continue + else: + if checkEnd(chip): + printBoard() + while (True): + print "Would you like to play again? Say 'yes' for yes and 'no' for no." + + input = raw_input() + + if (str(input) == 'yes'): + populateBoard() + setPlayer(1) + print "Welcome to Connect Four! Type 'stop' at any time to stop." + break + elif (str(input) == 'no'): + return + else: + print "Invalid input." + continue + + continue + + # Gives turn to the next player + if getPlayer() == 1: + setPlayer(2) + continue + if getPlayer() == 2: + setPlayer(1) + continue + +""" +" Helper function that uses the checkWin() function +" from the GameLogic file to check for a win. Prints +" a message if the player whose chip is passed as a +" parameter won the game. +" +" @param c, the chip being checked for. +" @return a bool, based on whether or not the player won. +""" +def checkEnd(c): + p = "" + + if c == 'o': + p = "1" + if c == 'x': + p = "2" + + if checkWin(c): + print "\nPlayer " + p + " wins!" + return True + else: + return False + +if __name__ == "__main__": + main() + + diff --git a/GameLogic.py b/GameLogic.py new file mode 100644 index 0000000..fbde84d --- /dev/null +++ b/GameLogic.py @@ -0,0 +1,258 @@ +import cPickle as pickle + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" @author Jacob McCloughan +" @version 3/30/2017 +" @see https://docs.python.org/2/library/pickle.html +" +" This .py file includes the function needed to play the +" Connect Four game. It includes methods for saving and +" loading files along with the basic logic for the game +" rules. +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +# The game board. +board = [] + +# The height of the game board. +height = 7 + +# The width of the game board. +width = 6 + +# The win length for the game rules. +winLength = 4 + +# The current player. +player = 1 + +""" +" Sets the height of the game board to the passed parameter. +" +" @param h, the new height of the game board. +""" +def setHeight(h): + global height + height = h + +""" +" Sets the width of the game board to the passed parameter. +" +" @param w, the new width of the game board. +""" +def setWidth(w): + global width + width = w + +""" +" Sets the number of chips in a row needed to win the game. +" +" @param l, the new win length for the game rules. +""" +def setWinLength(l): + global winLength + winLength = l + +""" +" Sets the game's turn to the player who is passed as a parameter. +" +" @param p, the new current player. +""" +def setPlayer(p): + global player + player = p + +""" +" Returns the height of the game board. +" +" @return height, the height of the game board. +""" +def getWidth(): + global width + return width + +""" +" Returns the width of the game board. +" +" @return width, the width of the game board. +""" +def getHeight(): + global height + return height + +""" +" Returns the length to win the game. +" +" @return winLength, the length to win. +""" +def getWinLength(): + global winLength + return winLength + +""" +" Returns the current turn's player. +" +" @return player, the current player. +""" +def getPlayer(): + global player + return player + +""" +" Resets the board with the current parameters +" to start a new game. +""" +def populateBoard(): + global board, height, width + board = [] + for i in range (0, height): + board.append([]) + for j in range (0, width): + board[i].append('') + board[i] = ['*' for x in board[i]] + +""" +" Prints the current game board. +""" +def printBoard(): + global board + for i in board: + for j in i: + print j, + print '' + +""" +" Places a chip in the desired column. Also makes sure +" that you can place a chip in that column, returning False +" if you cannot and True if you can. +" +" @param col, the desired column. +" @param player, the chip being placed. +" @return a bool, based on whether or not its a valid move. +""" +def placeChip(col, player): + global board, height, width + + if col > width - 1 or col < 0: + return False + + for i in range(height - 1, -1, -1): + if i > 0 and ((board[i][col] == 'o') or (board[i][col] == 'x')): + continue + elif i == 0 and (board[i][col] != '*'): + return False + else: + board[i][col] = player + break + return True + +""" +" Saves the current board, its parameters and the game +" parameters to a file using a pickling function. +" +" @param filename, the file being saved to. +""" +def saveGame(filename): + global board, width, height, winLength + + game_data = [board, width, height, winLength] + pickle.dump(game_data, open(filename, "wb")) + +""" +" Loads a previous game from a file. +" +" @param filename, the file being loaded from. +""" +def loadGame(filename): + global board, width, height, winLength + + game_data = pickle.load(open(filename, "rb" )) + board = game_data[0] + width = game_data[1] + height = game_data[2] + winLength = game_data[3] + +""" +" Checks to see if the chip passed to the function has +" enough chips in a row to warrant a win. Returns True +" if that chip's player has won, and False if that +" player has not. +" +" @param player, the chip being checked for. +" @return a bool, based on whether or not the player won. +""" +def checkWin(player): + global board, width, height + row = 0 + col = 0 + + # 1 by 1 board + if height == 1 and width == 1 and winLength == 1: + if board[0][0] == player: + return True + else: + return False + + # Horizontal check + count = 0 + for i in range(0, height): + for j in range(0, width): + if board[i][j] == player: + count = count + 1 + else: + count = 0 + if count == winLength: + return True + count = 0 + + # Vertical check + count = 0 + for i in range(0, width): + for j in range(0, height): + if board[j][i] == player: + count = count + 1 + else: + count = 0 + if count == winLength: + return True + count = 0 + + # Negative slope diagonal + count = 0 + for i in range(0, height): + for j in range(0, width): + row = i + col = j + count = 0 + while (row < height and col < width): + if board[row][col] == player: + count = count + 1 + row = row + 1 + col = col + 1 + else: + row = row + 1 + col = col + 1 + count = 0 + if count == winLength: + return True + + # Positive slope diagonal + count = 0 + for i in range(0, height): + for j in range(0, width): + row = i + col = j + count = 0 + while row >= 0 and col < width: + if board[row][col] == player: + count = count + 1 + row = row - 1 + col = col + 1 + else: + row = row - 1 + col = col + 1 + count = 0 + if count == winLength: + return True + + return False \ No newline at end of file diff --git a/Parser.py b/Parser.py new file mode 100644 index 0000000..9164990 --- /dev/null +++ b/Parser.py @@ -0,0 +1,29 @@ +import argparse + +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" +" @author Jacob McCloughan +" @version 3/30/2017 +" @see https://docs.python.org/2.7/library/argparse.html +" +" This .py file implements our command line argument +" parser using argparse. +""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" + +# Creates our parser. +parser = argparse.ArgumentParser(description="Connect Four game!") + +# Adds our arguments to the parser. +parser.add_argument('--height', default='6', action='store', type=int, + dest='height', help="Height of the game board.") +parser.add_argument('--width', default='7', action='store', type=int, + dest='width', help="Width of the game board.") +parser.add_argument('--square', default='-1', action='store', type=int, + dest='square', help='Square dimension for game board.') +parser.add_argument('--connect', default='4', action='store', type=int, + dest='connect', help="Chips in a row to win.") +parser.add_argument('--load', default=None, action='store', type=str, + dest='loadName', help="Load a previous game.") + +# Save results from the command line for further usage. +results = parser.parse_args() +