So basically I am trying to build a Tic-Tac-Toe game with both single and multiplayer difficulty levels but I am stuck on what code should I write for player vs computer and I am stuck in a forever loop in the def play_game() function. I can't keep the previous stats of the game as well. I really need help with this.
# --------- Global Variables -----------
# Will hold our game board data
board = ["-", "-", "-",
"-", "-", "-",
"-", "-", "-"]
# Lets us know if the game is over yet
game_still_going = True
# Tells us who the winner is
winner = None
# Tells us who the current player is (X goes first)
current_player = "X"
# ------------- Functions ---------------
# Play a game of tic tac toe
def play_game():
# Show the initial game board
display_board()
game_on = True
while True:
print("1.Single Player")
print("2.Multiplayer")
print("3.Game Stats")
print("4.Quit")
input_1 = int(input("Please Select An Option"))
if input_1 == "3" :
print('reading database...')
read_log()
elif input_1 == "4" :
exit()
elif input_1 == "2" :
Player_1 = input("Enter First Player Name:")
Player_2 = input("Enter Second Player Name:")
display_board()
while game_on:
position = input("Choose a position from 1-9: ")
check_for_winner()
display_board()
# Loop until the game stops (winner or tie)
while game_still_going:
# Handle a turn
handle_turn(current_player)
# Check if the game is over
check_if_game_over()
# Flip to the other player
flip_player()
# Since the game is over, print the winner or tie
if winner == "X" or winner == "O":
print(winner + " won.")
elif winner == None:
print("Tie.")
# Display the game board to the screen
def display_board():
print("\n")
print(board[0] + " | " + board[1] + " | " + board[2] + " 1 | 2 | 3")
print(board[3] + " | " + board[4] + " | " + board[5] + " 4 | 5 | 6")
print(board[6] + " | " + board[7] + " | " + board[8] + " 7 | 8 | 9")
print("\n")
# Handle a turn for an arbitrary player
def handle_turn(player):
# Get position from player
print(player + "'s turn.")
position = input("Choose a position from 1-9: ")
# Whatever the user inputs, make sure it is a valid input, and the spot is open
valid = False
while not valid:
# Make sure the input is valid
while position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
position = input("Choose a position from 1-9: ")
# Get correct index in our board list
position = int(position) - 1
# Then also make sure the spot is available on the board
if board[position] == "-":
valid = True
else:
print("You can't go there. Go again.")
# Put the game piece on the board
board[position] = player
# Show the game board
display_board()
# Check if the game is over
def check_if_game_over():
check_for_winner()
check_for_tie()
# Check to see if somebody has won
def check_for_winner():
# Set global variables
global winner
# Check if there was a winner anywhere
row_winner = check_rows()
column_winner = check_columns()
diagonal_winner = check_diagonals()
# Get the winner
if row_winner:
winner = row_winner
elif column_winner:
winner = column_winner
elif diagonal_winner:
winner = diagonal_winner
else:
winner = None
# Check the rows for a win
def check_rows():
# Set global variables
global game_still_going
# Check if any of the rows have all the same value (and is not empty)
row_1 = board[0] == board[1] == board[2] != "-"
row_2 = board[3] == board[4] == board[5] != "-"
row_3 = board[6] == board[7] == board[8] != "-"
# If any row does have a match, flag that there is a win
if row_1 or row_2 or row_3:
game_still_going = False
# Return the winner
if row_1:
return board[0]
elif row_2:
return board[3]
elif row_3:
return board[6]
# Or return None if there was no winner
else:
return None
# Check the columns for a win
def check_columns():
# Set global variables
global game_still_going
# Check if any of the columns have all the same value (and is not empty)
column_1 = board[0] == board[3] == board[6] != "-"
column_2 = board[1] == board[4] == board[7] != "-"
column_3 = board[2] == board[5] == board[8] != "-"
# If any row does have a match, flag that there is a win
if column_1 or column_2 or column_3:
game_still_going = False
# Return the winner
if column_1:
return board[0]
elif column_2:
return board[1]
elif column_3:
return board[2]
# Or return None if there was no winner
else:
return None
# Check the diagonals for a win
def check_diagonals():
# Set global variables
global game_still_going
# Check if any of the columns have all the same value (and is not empty)
diagonal_1 = board[0] == board[4] == board[8] != "-"
diagonal_2 = board[2] == board[4] == board[6] != "-"
# If any row does have a match, flag that there is a win
if diagonal_1 or diagonal_2:
game_still_going = False
# Return the winner
if diagonal_1:
return board[0]
elif diagonal_2:
return board[2]
# Or return None if there was no winner
else:
return None
# Check if there is a tie
def check_for_tie():
# Set global variables
global game_still_going
# If board is full
if "-" not in board:
game_still_going = False
return True
# Else there is no tie
else:
return False
# Flip the current player from X to O, or O to X
def flip_player():
# Global variables we need
global current_player
# If the current player was X, make it O
if current_player == "X":
current_player = "O"
# Or if the current player was O, make it X
elif current_player == "O":
current_player = "X"
def read_log():
log = open('log.txt', 'r')
log.seek(0)
print('\n\n')
print(log.read(),'\n\n')
# ------------ Start Execution -------------
# Play a game of tic tac toe
play_game()
If I understood correctly You can do it like this:
Define functions:
handle_player_move()
handle_computer_move()
as names suggests when you call the function either human player or computer will make a move (make sure that it's certain or add some Errorcodes/Exceptions when player do something unexpected and you want to end program)
Define function:
game_is_over() # returns True if it's the end of game False other wise
Then Your game is just:
Human vs Human:
whos_move = 0 # number of player ( 0 or 1 )
while not game_is_over():
if whos_move == 0:
handle_player_move(player1)
if whos_move == 1:
handle_player_move(player2)
whos_move = (whos_move + 1) % 2
Quite similarly Human vs Bot:
whos_move = 0 # number of player ( 0 or 1 )
while not game_is_over():
if whos_move == 0:
handle_player_move(player1)
if whos_move == 1:
handle_computer_move(player2)
whos_move = (whos_move + 1) % 2
Instead of this you can also check for end of game with your function, and do:
whos_move = 0 # number of player ( 0 or 1 )
while game_still_going:
if whos_move == 0:
handle_player_move(player1)
if whos_move == 1:
handle_computer_move(player2)
whos_move = (whos_move + 1) % 2
check_if_game_over()
if statement: # your ending statement here
game_is_still_going = False
Your method with flip_player() is also good I just put if statements to both so that they are familiar in truth if you would are able to distinguish in handle_turn() between bot and human player you can do it for both cases ;)
As implementing computer moves can be hard here are some tips:
Easiest way you can just randomly choose number between 1 and 9 check if it's unoccupied if it's free computer makes move there if it is not you pick again. Maybe it sounds like being potentially endless loop but statisticly computer shouldn't have any problems with making a move.
You can also create list of free squares and then randomly choose an index (probably better way)
You can also try to add some logic f.e. if there are two in a row block third square.
too choose random integer from given interval you can use:
import random
random.randint(1,9) # choose integer x such that: 1 <= x <= 9
Of course you can and even maybe should use your own function names (name them as you wish!)
Hope that helps, good luck!
Related
I am working on one of my first codes (Tic Tac Toe), and I cannot figure out why I'm getting a name error.
First I have a list (board).
Then I have a function (possible_victory_for() ) that I define. It is supposed to to something with a list (temp_board) that will be defined later, within the next function.
The next function (computer_move() ) says temp_board = board and then calls the possible_victory_for().
In my understanding, seeing as "board" seems to work fine, the temp_board = board should be enough of a definition for temp_board. But Python disagrees.
I tried to recreate the error on a simple example, like this:
board = [1, 2, 3]
temp_board = board
if temp_board[0] == 1:
print("it works")
But this works fine and doesn't produce the error. So maybe it's something related to communication between functions (or simply a typo somewhere)?
As I fail to shorten the code and get the same error, I am attaching everything I made for now. Sorry for a long post.
(if you decide to run the code, go for Medium difficulty, that's where the error happens).
# I need these functions to make everything work
# clear_output was imported by Google Colab, not sure if it's standard
# all mentions of clear_output can be deleted if needed, the code will work
# but it will show every turn made by computer/human, not just the current board
from IPython.core.display import clear_output
from random import randrange
# Sets the board at the beginning
board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# Just displays the current board
def display_board():
print(
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[0]," | ",board[1]," | ",board[2]," |",
"\n| | | |",
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[3]," | ",board[4]," | ",board[5]," |",
"\n| | | |",
"\n+-------+-------+-------+",
"\n| | | |",
"\n| ",board[6]," | ",board[7]," | ",board[8]," |",
"\n| | | |",
"\n+-------+-------+-------+"
)
# Asks player to define who plays first (human or computer). Impacts the order of turns.
def who_plays_first():
global first_player
while True:
first_player = int(input("Choose who plays first: 1 for human, 2 for computer"))
if first_player == 1 or first_player == 2:
break
print("invalid input, read the instruction")
if first_player == 1:
first_player = "human"
else:
first_player = "computer"
return(first_player)
# Asks player to set difficulty. Impacts how computer decides on its move.
def choose_difficulty():
global difficulty
while True:
difficulty = int(input("Choose difficulty: 1 = easy, 2 = medium, 3 = hard"))
if difficulty == 1 or difficulty == 2 or difficulty == 3:
break
print("invalid input, read the instruction")
if difficulty == 1:
difficulty = "easy"
elif difficulty == 2:
difficulty = "medium"
else:
difficulty = "hard"
return(difficulty)
# Makes a list of free fields. Used in other functions.
def make_list_of_free_fields():
list_of_free_fields = []
for field in range(1,10):
if field in board:
list_of_free_fields.append(field)
return(list_of_free_fields)
# Checks whether the player (defined by the sign) won.
def victory_for(sign):
if (board[0] == sign and board[1] == sign and board[2] == sign or
board[3] == sign and board[4] == sign and board[5] == sign or
board[6] == sign and board[7] == sign and board[8] == sign or
board[0] == sign and board[3] == sign and board[6] == sign or
board[1] == sign and board[4] == sign and board[7] == sign or
board[2] == sign and board[5] == sign and board[8] == sign or
board[0] == sign and board[4] == sign and board[8] == sign or
board[2] == sign and board[4] == sign and board[6] == sign):
return True
else:
return False
# Same as victory_for, but only used to help computer make its move on medium/hard.
def possible_victory_for(sign):
if (temp_board[0] == sign and temp_board[1] == sign and temp_board[2] == sign or
temp_board[3] == sign and temp_board[4] == sign and temp_board[5] == sign or
temp_board[6] == sign and temp_board[7] == sign and temp_board[8] == sign or
temp_board[0] == sign and temp_board[3] == sign and temp_board[6] == sign or
temp_board[1] == sign and temp_board[4] == sign and temp_board[7] == sign or
temp_board[2] == sign and temp_board[5] == sign and temp_board[8] == sign or
temp_board[0] == sign and temp_board[4] == sign and temp_board[8] == sign or
temp_board[2] == sign and temp_board[4] == sign and temp_board[6] == sign):
return True
else:
return False
# Asks the human player to make their move.
def human_move():
while True:
human_input = int(input("Choose a field"))
if human_input in make_list_of_free_fields():
break
print("You must choose one of the free fields on the board by typing 1-9")
board[human_input-1] = "O"
# This is how the computer makes its move.
# Depends on the difficulty.
# Easy is completely random.
# Medium checks whether:
# a) there's a (list of) move(s) that could guarantee computer's victory
# b) there's a (list of) move(s) that could guarantee human's victory
# - then play a random move out of that list (computer victory has priority)
# Hard is yet to be defined.
def computer_move():
if difficulty == "easy":
while True:
computer_input = randrange(10)
if computer_input in make_list_of_free_fields():
break
board[computer_input-1] = "X"
# elif difficulty == "medium":
else:
brings_computer_victory = []
brings_human_victory = []
for field in make_list_of_free_fields():
temp_board = board
temp_move = field
temp_board[temp_move-1] = "X"
if possible_victory_for("X") == True:
brings_computer_victory.append(temp_move)
if brings_computer_victory != []:
computer_input = randrange(1, len(brings_computer_victory) + 1)
board[computer_input-1] = "X"
for field in make_list_of_free_fields():
temp_board = board
temp_move = field
temp_board[temp_move-1] = "O"
if possible_victory_for("O") == True:
brings_human_victory.append(temp_move)
if brings_human_victory != []:
computer_input = randrange(1, len(brings_human_victory) + 1)
board[computer_input-1] = "X"
# This is the final piece of code that connects all the functions.
who_plays_first()
choose_difficulty()
clear_output()
if first_player == "human":
display_board()
while True:
human_move()
clear_output()
display_board()
if victory_for("O") == True:
print("You won!")
break
if len(make_list_of_free_fields()) == 0:
print("it's a tie")
break
computer_move()
clear_output()
display_board()
if victory_for("X") == True:
print("You lost!")
break
else:
while True:
computer_move()
clear_output()
display_board()
if victory_for("X") == True:
print("You lost!")
break
if len(make_list_of_free_fields()) == 0:
print("it's a tie")
break
human_move()
clear_output()
display_board()
if victory_for("O") == True:
print("You won!")
break
Here's the error traceback:
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-11-322daee905b6> in <module>
28
29 while True:
---> 30 computer_move()
31 clear_output()
32 display_board()
1 frames
<ipython-input-10-6530342ed281> in computer_move()
24 temp_move = field
25 temp_board[temp_move-1] = "X"
---> 26 if possible_victory_for("X") == True:
27 brings_computer_victory.append(temp_move)
28 if brings_computer_victory != []:
<ipython-input-8-bd71fed33fb4> in possible_victory_for(sign)
1 # Same as victory_for, but only used to help computer make its move on medium/hard.
2 def possible_victory_for(sign):
----> 3 if (temp_board[0] == sign and temp_board[1] == sign and temp_board[2] == sign or
4 temp_board[3] == sign and temp_board[4] == sign and temp_board[5] == sign or
5 temp_board[6] == sign and temp_board[7] == sign and temp_board[8] == sign or
NameError: name 'temp_board' is not defined
temp_board is local to computer_move, but you're treating it as if it were a global. You should make it a parameter to possible_victory_for:
def possible_victory_for(sign, temp_board):
# if (temp_board[0] ...
and then pass it from computer_move as an argument:
if possible_victory_for("X", temp_board) == True:
In general I'd recommend passing variables to your functions as arguments rather than relying on pulling them implicitly from an outer scope; it makes the dependencies between different parts of your code more obvious (in this case possible_victory_for depends on not only sign but the current values of temp_board), which makes it easier to change and extend.
for a school assignment I need to make tic tac toe, I've got pretty much everything ready, except for 1 issue, I don't know how to make the game know when it's a draw and then quit
in the function check_tie()
you can still see I have some attempts left over.
The spots in the tic tac toe board have to be numbers from 1-9 so I can't replace them with empty spaces. Meaning I can't do a check to see if there are no empty spots left
thanks in advance
Here's the full code
print ("*** Welcome to Tic Tac Teen ***")
gameboard = ['1', '2', '3', '4', '5', '6', '7', '8', '9']
game_running = True
winner = None
player = 'X'
marker = ['X', 'O']
player_list = []
name1 = input("Fill in the name of player 1: ")
player_list.append(name1)
name2 = input("Fill in the name of player 2: ")
player_list.append(name2)
print("These are the players:", player_list)
print("These are their markers:", marker)
# Function to print gameboard
def print_gameboard(gameboard):
print(" -----------")
print(" | " + gameboard[0] + " | " + gameboard[1] + " | " + gameboard[2] + " | ")
print(" -----------")
print(" | " + gameboard[3] + " | " + gameboard[4] + " | " + gameboard[5] + " | ")
print(" -----------")
print(" | " + gameboard[6] + " | " + gameboard[7] + " | " + gameboard[8] + " | ")
print(" -----------")
print()
#Checks if the game is over by checking for a win or tie:
def check_if_game_over():
check_win()
check_tie()
def check_win():
global winner
winner_row = check_row()
winner_column = check_column()
winner_diagonal = check_diagonal()
#Gets the winer
if winner_row:
winner = winner_row
elif winner_column:
winner = winner_column
elif winner_diagonal:
winner = winner_diagonal
else: winner = None # / Tie?
#checks rows for a win, by comparing if the elements in the row are the same
def check_row():
global game_running
row1 = gameboard[0] == gameboard[1] == gameboard[2]
row2 = gameboard[3] == gameboard[4] == gameboard[5]
row3 = gameboard[6] == gameboard[7] == gameboard[8]
if row1 or row2 or row3:
game_running = False
if row1:
return gameboard[0]
elif row2:
return gameboard[3]
elif row3:
return gameboard[6]
def check_column():
global game_running
column1 = gameboard[0] == gameboard[3] == gameboard[6]
column2 = gameboard[1] == gameboard[4] == gameboard[7]
column3 = gameboard[2] == gameboard[5] == gameboard[8]
if column1 or column2 or column3:
game_running = False
if column1:
return gameboard[0]
elif column2:
return gameboard[1]
elif column3:
return gameboard[2]
def check_diagonal():
global game_running
diag1 = gameboard[0] == gameboard[4] == gameboard[8]
diag2 = gameboard[2] == gameboard[4] == gameboard[6]
if diag1 or diag2:
game_running = False
if diag1:
return gameboard[0]
elif diag2:
return gameboard[2]
def check_tie():
return
global game_running
if not position.isdigit():
game_running = False
# global game_running
# if moves == 9:
# game_running = False
def switch_player():
global player
#Switches player depending on who's turn it is.
if player =="X":
player = "O"
elif player == "O":
player = "X"
#function that runs the whole game
def play_game():
while game_running:
print("This is the current gameboard:")
moves = 0
print_gameboard(gameboard)
player_turn(player)
check_if_game_over()
switch_player()
if winner == "X":
print(player_list[0] + " won!")
elif winner == "O":
print(player_list[1] + " won!" )
elif winner == None:
print("It's a tie!")
def player_turn(player):
position = input("Choose a spot from 1-9: ")
while position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
position = input("That's not a number between 1-9, try again: ")
position = int(position) - 1
# if gameboard[position] = taken (how do you do this?, )
#print(Position is already taken, please pick another spot)
gameboard[position] = player
print_gameboard(gameboard)
play_game()
Well the only way it can be a draw is when there is no winner after 9 moves right? After 9 moves just check if there is a winner; if there still isnt then it is a draw.
So in play_game() i would loop for 9 times, in each loop I would show the board like you did, make the move, check for winner, if winner then return, if not keep looping. If I happen to exit out of the loop then that means I've used up all of my moves and that there is no winner so it must be a tie.
Edit: Thats just how I would approach the problem. Your method works just as well. There is no right or wrong answer
Your code works okay as is, just replace the check_tie() function with this
def check_tie():
global game_running
game_running = any(tile.isdigit() for tile in gameboard)
You had the right idea, just didn't loop through the tiles.
For clarity, any() is a function that returns True if one of the evaluated values is True. Otherwise returns False. isdigit() is a method belonging to string which checks if all the characters included are digits or not.
--------- Global Variables -----------
# Will hold our game board data
board = ["-", "-", "-",
"-", "-", "-",
"-", "-", "-"]
# Lets us know if the game is over yet
game_still_going = True
# Tells us who the winner is
winner = None
# Tells us who the current player is (X goes first)
current_player = "X"
# ------------- Functions ---------------
# Play a game of tic tac toe
def play_game():
# Show the initial game board
display_board()
# Loop until the game stops (winner or tie)
while game_still_going:
# Handle a turn
handle_turn(current_player)
# Check if the game is over
check_if_game_over()
# Flip to the other player
flip_player()
# Since the game is over, print the winner or tie
if winner == "X" or winner == "O":
print(winner + " won.")
elif winner == None:
print("Tie.")
# Display the game board to the screen
def display_board():
print("\n")
print(board[0] + " | " + board[1] + " | " + board[2] + " 1 | 2 | 3")
print(board[3] + " | " + board[4] + " | " + board[5] + " 4 | 5 | 6")
print(board[6] + " | " + board[7] + " | " + board[8] + " 7 | 8 | 9")
print("\n")
# Handle a turn for an arbitrary player
def handle_turn(player):
# Get position from player
print(player + "'s turn.")
position = input("Choose a position from 1-9: ")
# Whatever the user inputs, make sure it is a valid input, and the spot is open
valid = False
while not valid:
# Make sure the input is valid
while position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"]:
position = input("Choose a position from 1-9: ")
# Get correct index in our board list
position = int(position) - 1
# Then also make sure the spot is available on the board
if board[position] == "-":
valid = True
else:
print("You can't go there. Go again.")
# Put the game piece on the board
board[position] = player
# Show the game board
display_board()
# Check if the game is over
def check_if_game_over():
check_for_winner()
check_for_tie()
# Check to see if somebody has won
def check_for_winner():
# Set global variables
global winner
# Check if there was a winner anywhere
row_winner = check_rows()
column_winner = check_columns()
diagonal_winner = check_diagonals()
# Get the winner
if row_winner:
winner = row_winner
elif column_winner:
winner = column_winner
elif diagonal_winner:
winner = diagonal_winner
else:
winner = None
# Check the rows for a win
def check_rows():
# Set global variables
global game_still_going
# Check if any of the rows have all the same value (and is not empty)
row_1 = board[0] == board[1] == board[2] != "-"
row_2 = board[3] == board[4] == board[5] != "-"
row_3 = board[6] == board[7] == board[8] != "-"
# If any row does have a match, flag that there is a win
if row_1 or row_2 or row_3:
game_still_going = False
# Return the winner
if row_1:
return board[0]
elif row_2:
return board[3]
elif row_3:
return board[6]
# Or return None if there was no winner
else:
return None
# Check the columns for a win
def check_columns():
# Set global variables
global game_still_going
# Check if any of the columns have all the same value (and is not empty)
column_1 = board[0] == board[3] == board[6] != "-"
column_2 = board[1] == board[4] == board[7] != "-"
column_3 = board[2] == board[5] == board[8] != "-"
# If any row does have a match, flag that there is a win
if column_1 or column_2 or column_3:
game_still_going = False
# Return the winner
if column_1:
return board[0]
elif column_2:
return board[1]
elif column_3:
return board[2]
# Or return None if there was no winner
else:
return None
# Check the diagonals for a win
def check_diagonals():
# Set global variables
global game_still_going
# Check if any of the columns have all the same value (and is not empty)
diagonal_1 = board[0] == board[4] == board[8] != "-"
diagonal_2 = board[2] == board[4] == board[6] != "-"
# If any row does have a match, flag that there is a win
if diagonal_1 or diagonal_2:
game_still_going = False
# Return the winner
if diagonal_1:
return board[0]
elif diagonal_2:
return board[2]
# Or return None if there was no winner
else:
return None
# Check if there is a tie
def check_for_tie():
# Set global variables
global game_still_going
# If board is full
if "-" not in board:
game_still_going = False
return True
# Else there is no tie
else:
return False
# Flip the current player from X to O, or O to X
def flip_player():
# Global variables we need
global current_player
# If the current player was X, make it O
if current_player == "X":
current_player = "O"
# Or if the current player was O, make it X
elif current_player == "O":
current_player = "X"
# ------------ Start Execution -------------
# Play a game of tic tac toe
play_game()
So I am trying to write a unit test for this code, so for example I am trying to check the def check_columns() function.
So far I came up with:
import unittest
import Tic_tac_toe
class TestGame(unittest.TestCase):
def test_check_for_column(self):
columns_1 = None
self.assertEqual(Tic_tac_toe.check_columns(), columns_1)
This checks out because initially, there is no input so I get None but I am trying to input "x" in the column and see if it returns the winner. How would I do that?
I am currently learning python and trying to build a tic tac toe game. I wrote a program to prevent the user repeating the same input but when I repeat the same number two times, the program starts looping continuously without stopping. Could someone give me advice on how to rectify this issue? see below the code:
from tabulate import tabulate
# define the board
board = ["_", "_", "_",
"_", "_", "_",
"_", "_", "_"]
# Current player
current_player = "X"
winner = None
game_still_on = True
def play_game():
while game_still_on:
position()
board_display()
handle_player()
winner_check()
winner_check2()
def handle_player():
global current_player
if current_player == "X":
current_player = "O"
elif current_player == "O":
current_player = "X"
def board_display():
board_row1 = [board[0], board[1], board[2]]
board_row2 = [board[3], board[4], board[5]]
board_row3 = [board[6], board[7], board[8]]
com_board = [board_row1,
board_row2,
board_row3]
print(tabulate(com_board, tablefmt="grid"))
# position input
def position():
global board
print(current_player+"'s turn")
positions = input("enter 1-9")
valid = False
while not valid:
while int(positions) >= 10 or 0 >= int(positions):
positions = input("Choose a position from 1 -9")
positions = int(positions)
if board[positions-1] == "_":
valid = True
else:
print("Choose another")
board[positions - 1] = current_player
def winner_check():
if board[0] == board[1] == board[2] != "_":
return board[0]
elif board[3] == board[4] == board[5] != "_":
return board[3]
elif board[6] == board[7] == board[8] != "_":
return board[6]
elif board[0] == board[3] == board[6] != "_":
return board[0]
elif board[1] == board[4] == board[7] != "_":
return board[1]
elif board[2] == board[5] == board[8] != "_":
return board[2]
elif board[0] == board[4] == board[8] != "_":
return board[0]
elif board[2] == board[4] == board[6] != "_":
return board[1]
else:
return None
def winner_check2():
row_winner = winner_check()
if row_winner:
global game_still_on
global winner
winner = row_winner
print((winner+ " won"))
game_still_on = False
play_game()
Let's look at this function:
# position input
def position():
global board
print(current_player+"'s turn")
positions = input("enter 1-9")
valid = False
while not valid:
while int(positions) >= 10 or 0 >= int(positions):
positions = input("Choose a position from 1 -9")
positions = int(positions)
if board[positions-1] == "_":
valid = True
else:
print("Choose another")
board[positions - 1] = current_player
This has nested validation loops. The inner one checks the range of the input integer (if it is an integer -- otherwise it throws an exception) and requests input until it's in range. That's fine.
Then in the outer validation loop, it checks if the requested space is unoccupied. If so, fine. If not, it prompts the user to choose another. But the input call is before the outer loop, so it just tries again to validate the same input that already failed.
Try moving the input into the outer loop:
# position input
def position():
global board
print(current_player+"'s turn")
valid = False
while not valid:
positions = input("enter 1-9")
while int(positions) >= 10 or 0 >= int(positions):
positions = input("Choose a position from 1 -9")
positions = int(positions)
if board[positions-1] == "_":
valid = True
else:
print("Choose another")
board[positions - 1] = current_player
I'd probably also change the inner loop to be just an if with a continue and make the handling of non-integer input more robust.
I am attempting to prompt the user the option to save the game, after the first move, during gameplay?
After the game is completed I want to prompt the user to reset the game(Y or N) then call the play game function(with a loop)?
However, I am unsure how to organize the code to accomplish these tasks. I am a beginner to python.
def play_game():
game = True
while game == True:
game_choice = menu()
if game_choice == 1:
choice_one()
elif game_choice ==2:
player1VSai()
elif game_choice ==3:
save_and_exit()
elif game_choice==4:
load_game()
#After the game is completed I want to reset the game and call the play game function(with a loop).
# reset_game()
# play_game()
def choice_one():
# Display initial board
display_board()
while game_still_playing:
# handle a single turn of a arbitrary player
handle_turn(current_player)
# check if win or tie
check_if_game_over()
# flip to other player
alternate_player()
# The game has ended
if winner == 'X' or winner == 'O':
print(winner + " won.")
elif winner == None:
print("Tie.")
# handle a single turn of a random player
def handle_turn(player):
print(player + "'s turn.")
position = input("Choose a position from 1 to 9: ")
# I can index into position with int instead of string
valid = False
while not valid:
while position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"] or position ==0:
position = input("Choose a position from 1-9: ")
if position == 0:
save_and_exit()
pass
# convert from string to int
position = int(position) - 1
if board[position] == '':
valid = True
else:
print("Space filled. Go again.")
# Board at position equals X
board[position] = player
display_board()
print("Press 0 to save & exit game.")
#then if? or loop? prompt user to save game?
For saving code, your Game has things that you should save:
The state of the board, variable player
Whose turn it is, variable
board
This means you would have to write a function that takes these 2 variables as input argument and writes the content to a file.
#Remy this is what I have for the save function,
which I believe works properly as I've saved the data I need.
def save_and_exit():
global current_player
#save and end loop
turn=current_player
option = menu()
file=open("HW3game.txt", "w")
for x in board:
file.write(x)
file.write(turn)
file.write(str(option))
file.close()
print("You have saved the game and exited")
return
import random
# functions
# board
# display board
# ask if you want to be x or O
# menu
# play game
# take input & alternate turns
# check win
# check rows
# check columns
# check diagonals
# check tie
# is board full
# ---- Global Variables -----
# Game Board
board = [''] * 9
# If game is still going
game_still_playing = True
# Who won? Or Tie?
winner = None
# Prompt user to choose X's or O's
letter = input("Choose a letter X or O: ").upper()
current_player = letter
# Input validation
while current_player not in ('x', 'o', 'X', 'O'):
letter = input("Try again. Choose a letter X or O:").upper()
current_player = letter
if letter.upper() not in ('X', 'O'):
print("Not an appropriate choice.")
else:
break
print("Player 1 will be ", current_player + "'s.\n")
def display_board():
print(board[6], "\t|", board[7] + " | " + board[8])
print("--------------")
print(board[3], "\t|", board[4] + " | " + board[5])
print("--------------")
print(board[0], "\t|", board[1] + " | " + board[2])
# ("1) Player 1 vs Player 2\n2) Player 1 vs AI\n3) Load Game\n0) Save & Exit")
# play tic tac toe
def play_game():
begin = "Y"
while begin == "Y":
game_choice = menu()
if game_choice == 1:
choice_one()
elif game_choice ==2:
player1VSai()
elif game_choice ==3:
save_and_exit()
elif game_choice==4:
load_game()
def choice_one():
# Display initial board
display_board()
while game_still_playing:
# handle a single turn of a arbitrary player
handle_turn(current_player)
# check if win or tie
check_if_game_over()
# flip to other player
alternate_player()
# The game has ended
if winner == 'X' or winner == 'O':
print(winner + " won.")
clear_board = reset_game()
play_game()
elif winner == None:
print("Tie.")
reset_game()
play_game()
# handle a single turn of a random player
def handle_turn(player):
print(player + "'s turn.")
position = input("Choose a position from 1 to 9: ")
# I can index into position with int instead of string
valid = False
while not valid:
while position not in ["1", "2", "3", "4", "5", "6", "7", "8", "9"] or position ==0:
position = input("Choose a position from 1-9: ")
if position == 0:
save_and_exit()
pass
# convert from string to int
position = int(position) - 1
if board[position] == '':
valid = True
else:
print("Space filled. Go again.")
# Board at position equals X
board[position] = player
display_board()
print("Press 0 to save & exit game.")
#then if? or loop? prompt user to save game?
def check_if_game_over():
# 3 in a row
check_for_winner()
# full board
check_if_tie()
def check_for_winner():
# Set up global variables
global winner
# check rows
row_winner = check_rows()
# check columns
column_winner = check_columns()
# check diagonals
diagonal_winner = check_diagonals()
if row_winner:
winner = row_winner
print("There was a ROW win!")
elif column_winner:
winner = column_winner
print("There was a COLUMN win!")
elif diagonal_winner:
winner = diagonal_winner
print("There was a DIAGONAL win!")
else:
winner = None
def check_rows():
# Set up global variables
global game_still_playing
# check rows for all the same values & is not an empty ''
row_1 = board[6] == board[7] == board[8] != ''
row_2 = board[3] == board[4] == board[5] != ''
row_3 = board[0] == board[1] == board[2] != ''
# if any row does have a match, flag that there is a win
if row_1 or row_2 or row_3:
game_still_playing = False
# Return the winner (X or O)
if row_1:
return board[6]
elif row_2:
return board[3]
elif row_3:
return board[0]
# return X or O if winner
# then flag game still playing to false to end loop
def check_columns():
# Set up global variables
global game_still_playing
# check columns for all the same values & is not an empty ''
column_1 = board[6] == board[3] == board[0] != ''
column_2 = board[7] == board[4] == board[1] != ''
column_3 = board[8] == board[5] == board[2] != ''
# if any column does have a match, flag that there is a win
if column_1 or column_2 or column_3:
game_still_playing = False
# Return the winner (X or O)
if column_1:
return board[6]
elif column_2:
return board[7]
elif column_3:
return board[8]
# return X or O if winner
# then flag game still playing to false to end loop
def check_diagonals():
# Set up global variables
global game_still_playing
# check columns for all the same values & is not an empty ''
diagonal_1 = board[0] == board[4] == board[8] != ''
diagonal_2 = board[6] == board[4] == board[2] != ''
# if any row does have a match, flag that there is a win
if diagonal_1 or diagonal_2:
game_still_playing = False
# Return the winner (X or O)
if diagonal_1:
return board[0]
elif diagonal_2:
return board[6]
# return X or O if winner
# then flag game still playing to false to end loop
def check_if_tie():
# declare global variable
global game_still_playing
# check if board full
if '' not in board:
game_still_playing = False
return
def alternate_player():
global current_player
# if current player is == to X then change it to O
if current_player == "X":
current_player = 'O'
# if current player is == to O then change it to X
elif current_player == "O":
current_player = 'X'
def player1VSai():
#random number
return
def save_and_exit():
global current_player
#save and end loop
turn=current_player
option = menu()
file=open("HW3game.txt", "w")
for x in board:
file.write(x)
file.write(turn)
file.write(str(option))
file.close()
print("You have saved the game and exited")
return
def menu():
print("Welcome to Tic Tac Toe")
print("1) Player 1 vs Player 2\n2) Player 1 vs AI\n3) Save & Exit\n4) Load Game")
game_choice = int(input("Choose an option, 0-4: "))
#
return game_choice
def load_game():
#setup global
global current_player
file = open("HW3game.txt", "r")
for i in range(0,8):
board[i]=file.read(1)
current_player=file.read(1)
#current choice of game.
game_choice=int(file.read(1))
file.close()
print("You have called the load function.")
return
def reset_game():
global board
#erase contents in current board
#replay game
clear_board = board.clear()
return clear_board
play_game()