Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import numpy as np
- import random
- class Game:
- mat = None
- rows = 6
- cols = 7
- turn = 0
- wins = 4
- game = Game()
- def pop_check(game):
- pop_list = [] #tempory list for holding pop possibilities
- pop_col = [] #temp list for holding columns of each possibility
- pop_row = [] #need to know row list for diagonals
- critcol=0 #nothin if no pop possibilities
- #HORIZONTAL
- for r in range(0,game.rows,1): #iterating through all rows
- for c in range(0,game.cols-game.wins+1,1): #iterating all the columns for each row
- while c < game.cols-1 and game.mat[r][c] != 0:
- while len(pop_list) < game.wins:
- critrow = r
- pop_col.append (c)
- pop_list.append (game.mat [r][c])
- c+=1 #now poplist has the correct number of pieces
- if 0 in pop_list:
- continue
- if pop_list.count(game.turn)==1: #theres a potential for a pop for current turn.
- critcol = pop_col [pop_list.index(game.turn)] #this is the number of the column that'll be needed
- if game.mat [critrow+1][critcol] == game.turn and game.mat [0][critcol] == game.turn:#check above piece and bottom pieces for match
- return (critcol,1)#return to pop
- elif pop_list.count(game.turn%2+1)==1: # potential for pop for other player
- critcol = pop_col [pop_list.index(game.turn%2+1)]
- if game.mat [critrow+1][critcol] and game.mat [0][critcol] == game.turn%2+1:#check above piece and bottom pieces for match
- for sidecol in pop_col: #pick the col list again
- if sidecol != critcol: #take each value thats NOT critcol
- if game.mat [critrow+1][sidecol] and game.mat [0][sidecol] == game.turn: #check for popping possibility
- return (sidecol,2) #pop it
- else:
- continue
- else:
- pop_list = []
- pop_col = []
- continue
- #DIAGONAL 1
- for r in range(0,game.rows-game.wins+1,1): #iterating through rows where starting of sequence is possible
- for c in range(0,game.cols-game.wins+1,1): #iterating through columns where starting of sequence is possible
- while r < game.rows-1 and c < game.cols-1 and game.mat[r][c] != 0:
- while len(pop_list) < game.wins:
- pop_row.append (r)
- pop_col.append (c)
- pop_list.append (game.mat [r][c])
- c+1
- r+1
- if 0 in pop_list:
- continue
- if pop_list.count(game.turn)==1: #theres a potential for a pop for current turn.
- critcol = pop_col [pop_list.index(game.turn)]
- critrow = pop_row [pop_list.index(game.turn)]
- if game.mat [critrow+1][critcol] == game.turn and game.mat [0][critcol] == game.turn:#check above piece and bottom pieces for match
- return (critcol,1)#return to pop
- elif pop_list.count(game.turn%2+1)==1: # potential for pop for other player
- critcol = pop_col [pop_list.index(game.turn%2+1)]
- critrow = pop_row [pop_list.index(game.turn%2+1)]
- if game.mat [critrow+1][critcol] and game.mat [0][critcol] == game.turn%2+1:
- for sidecol in pop_col:
- siderow = pop_row[pop_col.index(sidecol)]
- if sidecol != critcol:
- if game.mat [critrow+1][sidecol] and game.mat [0][sidecol] == game.turn: #check for blocking possibility
- return (sidecol,2) #pop it
- else:
- continue
- else:
- pop_list = []
- pop_col = []
- continue
- #DIAGONAL 2
- for r in range(0,game.rows-game.wins+1,1): #iterating through rows where starting of sequence is possible
- for c in range(0,game.cols-game.wins+1,1): #iterating through columns where starting of sequence is possible
- while r < game.rows-1 and c < game.cols-1 and game.mat[r][c] != 0:
- while len(pop_list) < game.wins:
- pop_row.append (r)
- pop_col.append (c)
- pop_list.append (game.mat [r][c])
- c-1
- r+1
- if 0 in pop_list:
- continue
- if pop_list.count(game.turn)==1: #theres a potential for a pop for current turn.
- critcol = pop_col [pop_list.index(game.turn)]
- critrow = pop_row [pop_list.index(game.turn)]
- if game.mat [critrow+1][critcol] == game.turn and game.mat [0][critcol] == game.turn:#check above piece and bottom pieces for match
- return (critcol,1)#return to pop
- elif pop_list.count(game.turn%2+1)==1: # potential for pop for other player
- critcol = pop_col[pop_list.index(game.turn%2+1)]
- critrow = pop_row[pop_list.index(game.turn%2+1)]
- if game.mat [critrow+1][critcol] and game.mat [0][critcol] == game.turn%2+1:
- for sidecol in pop_col:
- siderow = pop_row[pop_col.index(sidecol)]
- if sidecol != critcol:
- if game.mat [critrow+1][sidecol] and game.mat [0][sidecol] == game.turn: #check for blocking possibility
- return (sidecol,2) #pop it
- else:
- continue
- else:
- pop_list = []
- pop_col = []
- continue
- def computer_check(game):
- temp_board = game.mat.copy()
- for i in range(game.cols):
- for j in range(2):
- if j == 0:
- pop_option = False
- else:
- pop_option = True
- move_validity = check_move(game,i,pop_option)
- if move_validity == True:
- apply_move(game,i,pop_option)
- possible_win = check_victory(game)
- game.mat = temp_board
- if possible_win == 1 and game.turn == 2:
- apply_move(game,i,pop_option)
- return i,pop_option
- elif possible_win == 2 and game.turn == 1:
- apply_move(game,i,pop_option)
- return i,pop_option
- else:
- continue
- def human_move(game):
- while True:
- while True:
- try:
- if game.turn == 1: #deciding whose turn it is
- player_move = input("Player 1 please pick a column: ")
- elif game.turn == 2:
- player_move = input("Player 2 please pick a column: ")
- int(player_move)
- if not 0 <= int(player_move) <= game.cols-1: #selected column must be within range
- print("Please pick a valid column!")
- continue #ask the question again for invalid input
- else:
- player_move = int(player_move)
- break #escapes the loop for valid input
- except ValueError:
- print("Please pick a valid column!")
- continue
- while True:
- pop_option = (input("Enter 1 if you'd like to pop; enter 2 otherwise: "))
- if pop_option == "1":
- pop_option = True #player wants to pop
- break
- elif pop_option == "2":
- pop_option = False #player does not want to pop
- break
- else:
- print("Please pick either 1 or 2!")
- move_validity = check_move(game,player_move,pop_option)
- if not move_validity:
- print("Move not valid. Please try again")
- continue #if move is invalid, ask for a new column input
- else:
- apply_move(game,player_move,pop_option) #if move is valid, apply it
- break
- def display_board(game):
- print(np.flip(game.mat,0))
- def check_victory(game):
- #input the if game = game.mat
- winlist = [] #list of win conditions to be used to determine winner and outcome
- tick = 0 #counter for consecutive disks in a row
- #horizontal check
- for r in range(0,game.rows,1): #iterating through all rows
- for c in range(0,game.cols-game.wins+1,1): #iterating all the columns for each row
- while c < game.cols-1 and game.mat[r][c] != 0:
- #checking all spaces that aren't empty until c+1 becomes invalid
- if game.mat[r][c] == game.mat[r][c+1]:
- tick += 1 #counter goes up if consecutive disks are equal
- if tick == game.wins-1:
- #when the counter hits game.wins-1, a win condition has been reached
- #said win condition is appended to the list
- winlist.append(game.mat[r][c])
- break
- c += 1 #c increases to continue checking consecutive disks
- continue
- else:
- tick = 0 #counter resets when consecutive disks aren't the same
- break
- #vertical check
- for c in range(0,game.cols,1): #iterating through all columns
- for r in range(0,game.rows-game.wins+1,1): #iterating through all rows for each column
- while r < game.rows-1 and game.mat[r][c] != 0:
- #checking all spaces that aren't empty until r+1 becomes invalid
- if game.mat[r][c] == game.mat[r+1][c]:
- tick += 1 #counter goes up if consecutive disks are equal
- if tick == game.wins-1:
- #when counter hits game.wins-1, a win condition has been reached
- #said win condition is appended to list
- winlist.append(game.mat[r][c])
- break
- r += 1 #r increases to continue checking consecutive disks
- continue
- else:
- tick = 0 #counter resets when consecutive disks aren't the same
- break
- #diagonal check 1
- for r in range(0,game.rows-game.wins+1,1): #iterating through rows where starting of sequence is possible
- for c in range(0,game.cols-game.wins+1,1): #iterating through columns where starting of sequence is possible
- while r < game.rows-1 and c < game.cols-1 and game.mat[r][c] != 0:
- #checking non-zero spaces until r+1 or c+1 becomes invalid
- if game.mat[r][c] == game.mat[r+1][c+1]:
- tick +=1 #counter goes up with consecutive disks being equal
- if tick == game.wins-1:
- winlist.append(game.mat[r][c])
- break
- r += 1 #both r and c increase to continue checking consecutive disks
- c += 1
- continue
- else:
- tick = 0
- break
- #diagonal check 2
- for r in range(game.wins-1,game.rows,1): #iterating through rows where start of sequence is possiblke
- for c in range(0,game.cols-game.wins+1,1): #iterating through columns where start of sequence is possible
- while r > 0 and c < game.cols-1 and game.mat[r][c] != 0:
- #checking non-zero spaces until r-1 or c+1 becomes invalid
- if game.mat[r][c] ==game.mat[r-1][c+1]:
- tick +=1 #counter goes up with consecutive disks being equal
- if tick == game.wins-1:
- winlist.append(game.mat[r][c])
- break
- r -= 1 #r decreases and c increases to continue checking consecutive disks in that direction
- c += 1
- continue
- else:
- tick = 0
- break
- #processing winning instances
- if len(winlist) == 0: #no winning instances
- if np.count_nonzero(game.mat) == game.mat.size: #entire board is filled
- win = 3 #it's a draw
- else:
- win = 0 #if board isn't filled, next turn commences
- elif len(winlist) >= 2: #if a single turn causes more than 1 win condition to be reached
- #if player 1 dropped the last disks, we check for 1s within the win conditions
- #if it exists, we know player 1 has a game.wins in a row and so they win
- #if it doesn't exist, we know player 1 gave the win to player 2
- if game.turn == 1:
- if 2 in winlist: #turn was changed in apply_move
- win = 2
- else:
- win = 1
- #vice versa for player 2
- else:
- if 1 in winlist:
- win = 1
- else:
- win = 2
- else:
- win = int(winlist[0]) #only 1 win condition, so we look at their values
- return (win)
- def apply_move(game,col,pop):
- if pop == False: #
- for i in range(0,game.rows,1):
- if game.mat[i][col] == 0: #check for the first space from the bottom in that column that's empty
- game.mat[i][col] = game.turn #replace empty space with player's chip
- break
- else:
- for i in range(1,game.rows,1):
- game.mat[i-1][col] = game.mat[i][col] #replace every value in that column with the one above
- game.mat[game.rows-1][col] = 0 #set top row of the column as 0
- if game.turn == 1: #change of turn
- game.turn = 2
- elif game.turn == 2:
- game.turn = 1
- return game
- def check_move(game,col,pop):
- if pop == False: #no popping, so the disk is dropped from the top
- if game.mat[game.rows-1][col] != 0: #checking top most space of the column; if it's not empty, the column is full
- move_validity = False #column is full so move is invalid
- else:
- move_validity = True #column isn't full so move is valid
- if pop == True: #popping so disk is removed from the bottom
- if game.mat[0][col] != game.turn: #checking bottom most space of column to see if it's the current player's
- move_validity = False #bottom disk isn't the player's so move is invalid
- else:
- move_validity = True #bottom disk belongs to the player so move is valid
- return move_validity
- def computer_move(game,level):
- if level == 1:
- while True:
- player_move = random.randint(0,game.cols-1)
- pop_option = random.randint(1,2)
- if pop_option == 1:
- pop_option = True
- else:
- pop_option = False
- move_validity = check_move(game,player_move,pop_option)
- if not move_validity:
- continue
- else:
- apply_move(game,player_move,pop_option)
- break
- return player_move,pop_option
- if level == 2:
- output = computer_check(game)
- return output
- def menu():
- print("Connect 4\n\nby Koh Si Yan, Gerald Ong, and Chen Zhixing")
- while True:
- new_game = (input("1. Start new game\n2. Quit\n\n"))
- if new_game == "2":
- print("Thank you for playing. Goodbye")
- return
- if new_game != "2" and new_game != "1":
- print("Please select 1 or 2!")
- continue
- else:
- break
- while True:
- try:
- game.rows = input("How many rows in the game? ") #user input for no. of rows
- int(game.rows)
- if int(game.rows) < 2: #min no. of rows is 2
- print("Please enter a valid number (2 or more)")
- else:
- game.rows = int(game.rows)
- break
- except ValueError: #if input isn't an integer, ask for a new input
- print("Please pick a valid number!")
- while True:
- try:
- game.cols = input("How many columns in the game? ") #user input for no. of columns
- int(game.cols)
- if int(game.cols) < 2: #min no. of columns is 2
- print("Please enter a valid number (2 or more)")
- else:
- game.cols = int(game.cols)
- break
- except ValueError: #if input isn't an integer, ask for a new input
- print("Please pick a valid number!")
- while True:
- try:
- game.wins = input("How many disks in a row to win? ") #user input for no. of disks to win
- int(game.wins)
- if int(game.wins) > int(game.rows) or int(game.wins) > int(game.cols) or int(game.wins) < 2:
- #no. of disks in a row to win has to be within the range of columns and rows
- print("Pick a positive number > 1 and <= number of columns and rows")
- else:
- game.wins = int(game.wins)
- break
- except ValueError:
- print("Please pick a valid number!")
- game.mat = np.zeros((game.rows,game.cols)) #initialising the game board
- game.turn = 1 #set initial turn to be 1
- while True:
- opponent = input("Pick your opponent\n1. Computer(1P)\n2. Human(2P)\n")
- #choosing a human or compuoter opponent
- if opponent == "1":
- while True:
- turn_order = input("Who should go first?\n1. Player\n2. Computer\n3. Random\n")
- #choosing turn order for computer opponent
- if turn_order == "3":
- turn_order = str(random.randint(1,2))
- #for random turn order, random integer that leads to either human or computer starting first is generated
- if turn_order == "1":
- print("Human is Player 1 and goes first")
- break
- elif turn_order == "2":
- print("Computer is Player 1 and goes first")
- break
- else:
- print("Please pick 1, 2, or 3!")
- continue
- while True:
- try:
- computer_level = input("What level should the computer be? 1 or 2: ")
- #comptuer difficulty
- int(computer_level)
- if int(computer_level) != 1 and int(computer_level) != 2:
- print("Invalid input; please try again!")
- else:
- computer_level = int(computer_level)
- break
- #limit integer values depending on levels
- except ValueError:
- print("Invalid input; please try again")
- if turn_order == "1":
- #human player goes first
- display_board(game)
- while True:
- human_move(game)
- check_victory(game)
- display_board(game)
- if check_victory(game) != 0:
- break
- else:
- print("\nComputer makes its move!")
- computer_move(game,computer_level)
- check_victory(game)
- display_board(game)
- if check_victory(game) != 0:
- break
- else:
- continue
- if turn_order == "2":
- #computer goes first so order is reversed
- while True:
- computer_move(game,computer_level)
- check_victory(game)
- display_board(game)
- if check_victory(game) != 0:
- break
- else:
- game.turn
- human_move(game)
- check_victory(game)
- display_board(game)
- if check_victory(game) != 0:
- break
- else:
- print("\nComputer makes its move!")
- continue
- break
- break
- elif opponent == "2":
- #2 human player game
- display_board(game)
- while True:
- human_move(game)
- check_victory(game)
- display_board(game)
- if check_victory(game) == 0:
- continue
- else:
- break
- break
- else:
- print("Please pick 1 or 2!")
- continue
- if check_victory(game) == 1 or check_victory(game) == 2: #condition for someone winning
- print("Player",check_victory(game),"wins!")
- if check_victory(game) == 3: #condition for draw
- print("All slots filled. It's a draw!")
- while True:
- play_again = input("Would you like to play again?\n1. Yes please!\n2. No, I'd like to quit\n")
- if play_again == "1":
- menu()
- if play_again != "1" and play_again != "2":
- print("Not an option! Please try again!")
- continue
- if play_again == "2":
- print("Okay; goodbye!")
- return
- menu()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement