I am new to coding and has recently started learning python. My first challenge is to build a tic tac toe game. Below are my codes for the game, everything worked fine except that when I want to restart the game or end the game, the loop won't break or the game cannot start.Could anyone figure out whats wrong with my codes. thank you!
Matrix = [[' ' for i in range(3)]for j in range(3)]
for i in Matrix:
print(i) #this is the 3x3 board
def check_done(value): #this is to check if the player has won the game
for a in range(0,3):
if Matrix[0][a]==Matrix[1][a]==Matrix[2][a]==value\
or Matrix[a][0]==Matrix[a][1]==Matrix[a][2]==value:
print ('won')
return True
#when the vertical column or horizontal row is equal, the
player won the game
if Matrix[0][0]==Matrix[1][1]==Matrix[2][2]==value\
or Matrix[2][0]==Matrix[1][1]==Matrix[0][2]==value:
print('won')
return True
#when the diagonal rows are equal, the player won the game
if ' ' not in Matrix[0] and ' ' not in Matrix[1] and ' ' not in
Matrix[2]:
print('draw')
return True
#when every grid is filled in the board and no win criteria is
fulfilled, it is a draw
return False
def replay(): #this is to determine if the player wants to restart or
end the game
command =input('Enter r to restart, or e to end game: ')
while True:
if command == 'r':
player1_input()
if command == 'e':
return
break
else:
print('Invalid command.')
def player1_input(): #this is an input function to allow players to
position their next move
print('Player 1 insert your name here')
name1=input()
print('player 2 insert your name here')
name2=input()
while True:
inputValid = False
while inputValid == False:
print(name1,'please place x coordinates')
xinput=int(input())
print(name1,'please place y coordinates')
yinput=int(input())
if yinput >= 0 & yinput <= 2 & xinput >=0 & xinput <= 2:
if Matrix[yinput][xinput] == ' ':
Matrix[yinput][xinput] = 'X'
for i in Matrix:
print(i)
if check_done('X'):
print(name1,'won')
replay()
inputValid = True
inputValid = False
while inputValid == False:
print(name2,'please place x coordinates')
xinput=int(input())
print(name2,'please place y coordinates')
yinput=int(input())
if yinput >= 0 & yinput <= 2 & xinput >=0 & xinput <= 2:
if Matrix[yinput][xinput] == ' ':
Matrix[yinput][xinput] = 'O'
for i in Matrix:
print(i)
if check_done('O'):
print(name2,'won')
replay()
inputValid = True
return True
The while loop for the main gameplay is running infinite.
To solve that, you can use a continue_game flag.
A simple example:
def player1_input():
# rest of the code
continue_game = True
while continue_game:
# logic for the game
continue_game = replay()
def replay():
# Returns true or false on user input.
while True:
command = raw_input('...')
if command == 'r':
return True
elif command == 'e':
return False
else:
print ('Invalid command')
The method replay can return a boolean as approriate based on user input.
Further, note that you have to re-initialize the matrix with empty values, if the game is supposed to be restarted.
It is difficult to read the code as it is posted. But it seems to me that your while True is an infinite cycle. I dont see any break that allows you to exit the while
Related
My problem: Python tab closes on "3 1" input.
This code is heavily inspired by Hafeezul Kareem Shaik's tic-tac-toe game on geekflare.
My code:
import random
class TicTacToe:
def __init__(self):
self.board = []
def create_board(self):
for r0w in range(3):
row = []
for c0l in range(3):
row.append('-')
self.board.append(row)
def get_random_first_player(self):
return random.randint(0,1)
def fix_spot(self, row, col, player):
self.board[row][col] = player
def is_player_win(self, player):
win = None
n = len(self.board)
#checking rows
for r0w in range(n):
win = True
for c0l in range(n):
if self.board[r0w][c0l] != player:
win = False
break
if win:
return win
#checking columns
for r0w in range(n):
win = True
for c0l in range(n):
if self.board[c0l][r0w] != player:
win = False
break
if win:
return win
#checking diagonals
win = True
for i in range (n):
if self.board[i][i] != player:
win = False
break
if win:
return win
win = True
for i in range(n):
if self.board[r0w][n - 1 - r0w] != player:
win = False
break
if win:
return win
return False
for row in self.board:
for item in row:
if item == '-':
return False
return True
def is_board_filled(self):
for row in self.board:
for item in row:
if item == "-":
return False
return True
def swap_player_turn(self, player):
return 'X' if player =='O' else 'O'
def show_board(self):
for row in self.board:
for item in row:
print(item, end=" ")
print()
def start(self):
self.create_board()
player = 'X' if self.get_random_first_player() == 1 else 'O'
while True:
print(f"Player {player} turn")
self.show_board()
# user input
row, col = list(
map(int, input("Enter row and column numbers to fix spot: ").split()))
print()
#fixing spot
self.fix_spot(row - 1, col - 1, player)
#has current player won
if self.is_player_win(player):
print(f"{player} Wins!")
break
#is game a draw
if self.is_board_filled():
print("Draw!")
break
#swapping turn
player = self.swap_player_turn(player)
#final board
print()
self.show_board()
tic_tac_toe = TicTacToe()
tic_tac_toe.start()
The Tic_Tac-Toe Game worked up until I typed "3 1". I tested multiple games and it would always close after that input.
I have tried editing the scope of the following, as I believe that is what is causing it to malfunction
if win:
return win
return False
Unfortunately that has not fixed the problem. Any ideas or suggestions?
This code is so badly written that I wouldn't take it as an example for anything.
But if you really want to know why it ends on 3 1 as input, you should look here:
win = True
for i in range(n):
if self.board[r0w][n - 1 - r0w] != player:
win = False
break
if win:
return win
return False
Here r0w is not reset, it has the last value from the for loop, which is 2, and it's not changing in the loop, so there's only one check made, which is 3 1, translated to 2 0, which is the current player, so that's an instant win.
I assume this was supposed to be a loop to check the other diagonal, but it's clearly flawed.
I'm new to python and writing my first project. I'm trying to implement a check that if a space is already occupied, not to move there. I can't seem to figure out why my move_player method overwrites the index value of the board even though I am explicitly checking it (If it is O's turn and X has already been placed in the index O is trying to move to, it just overwrites it). I have tried hard coding the check for 'X' and 'O' instead of player.player as well but can't seem to figure it out. Does it have to do something with how Python works or am I implementing it wrong?
class Player:
def __init__(self, player):
self.player = player
class Board:
def __init__(self):
self.board = [[' ' for i in range(3)] for j in range(3)]
def display_board(self):
print('---------')
for row in self.board:
print('| ', end='')
for col in row:
print(f'{col} ', end='')
print('|')
print('---------')
def move_player(self, player):
try:
p1 = Player('X')
p2 = Player('O')
coordinates = [int(i) for i in input("Enter coordinates for move: ").split()]
xCoordinate = coordinates[0]
yCoordinate = coordinates[1]
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
print("That space is occupied, please choose another one.")
self.move_player(player)
else:
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
except (ValueError, IndexError):
print("Please only enter numbers between 1 and 3.")
self.move_player(player)
def has_won(self, player):
if self.check_diagonal(player):
return True
elif self.check_across(player):
return True
elif self.check_down(player):
return True
return False
if __name__ == '__main__':
board = Board()
player1 = Player('X')
player2 = Player('O')
player = player1
while True:
board.display_board()
board.move_player(player)
if board.has_won(player):
board.display_board()
print(f'{player.player} wins!!!')
break
if player == player1:
player = player2
else:
player = player1
The code is very convoluted but from what I can see:
if ((self.board[xCoordinate][yCoordinate] == p1.player) or
(self.board[xCoordinate][yCoordinate] == p2.player)):
...
self.board[xCoordinate - 1][yCoordinate - 1] = player.player
You are checking [x,y] but assigning to [x-1,y-1].
I am new to coding and has recently started learning python. My first challenge is to build a tic tac toe game. Below are my codes for the game, everything worked fine except that when there is no winner(i.e. game draw); i want to display no body has won the game. I've tried to incorporate an else in various places. but, they didn't help. Here is my code.
# a dictionary to display the grid
grid = {
'1':'1', '2':'2', '3':'3',
'4':'4', '5':'5', '6':'6',
'7':'7', '8':'8', '9':'9'
}
# a list to store the values that has already been entered
used_places = []
# players and their symbols
player_1 = 'x'
player_2 = 'o'
# to store result
result = None
def grid_display():
#this function displays the grid
print('\n\n')
print(grid['1'], '\t|\t', grid['2'], '\t|\t', grid['3'])
print(''.rjust(19,'*'))
print(grid['4'], '\t|\t', grid['5'], '\t|\t', grid['6'])
print(''.rjust(19, '*'))
print(grid['7'], '\t|\t', grid['8'], '\t|\t', grid['9'])
def win_the_game():
# this function checks for result and returns true or false
if(
(grid['1'] == grid['2'] == grid['3']) or (grid['4'] == grid['5'] == grid['6']) or
(grid['7'] == grid['8'] == grid['9']) or (grid['1'] == grid['4'] == grid['7']) or
(grid['2'] == grid['5'] == grid['8']) or (grid['3'] == grid['6'] == grid['9']) or
(grid['1'] == grid['5'] == grid['9']) or (grid['3'] == grid['5'] == grid['7'])
):
return True
else:
return False
def taking_turns(turn):
#this function asks user for input
print("its turn of ", turn)
choice = input("enter your choice")
while not (choice.isdecimal() and choice in grid and (choice not in used_places)):
# taking proper input by checkin it with already entered numbers
# and if it is a number
# and if number is in between 1 and 9
choice = input("\nenter your choice properly:")
player_move(choice, turn)
def player_move(move, assign):
# this function fills the entered numbers into used_places list
# and replaces numbers in grid with user input
used_places.append(move)
grid[move] = assign
print("player 1 : 'X'")
print("player 2 : 'O'")
for i in range(0,10): # loops 9 times to play the game
if i % 2 == 0: # giving turns. if i is even, player 1 gets turn and odd, player 2
grid_display() # displaying complete grid
turn = player_1 # to display whose turn it is; refer the function
taking_turns(turn)
if win_the_game() == True: # if the called function returns true in this 'if'
result = turn # player 1 wins
break
else:
grid_display() # same code as above
turn = player_2
taking_turns(turn)
if win_the_game() == True:
result = turn
break
print('\n\n',result, "won the game!!") # printing result
Instead of setting result = None, set result = 'Nobody'.
Looking at your logic, you only set result if somebody wins, this would leave the default of result to nobody.
-- edit --
Sorry, I kinda got carried away and re-wrote the logic of your game in proving my solution. Take it or leave it, but it works great now and maybe you can use it as an example to fix your own.
import os
# a dictionary to display the grid
grid = {
'1':'1', '2':'2', '3':'3',
'4':'4', '5':'5', '6':'6',
'7':'7', '8':'8', '9':'9'
}
# a list to store the values that are available
places = ['1','2','3','4','5','6','7','8','9']
# to store result
result = 'Nobody'
# starting player
turn = 'O'
# display a game grid
def grid_display():
os.system('cls' if os.name == 'nt' else 'clear')
#this function displays the grid
print
print(grid['1'], '|', grid['2'], '|', grid['3'])
print(''.rjust(25,'*'))
print(grid['4'], '|', grid['5'], '|', grid['6'])
print(''.rjust(25, '*'))
print(grid['7'], '|', grid['8'], '|', grid['9'])
# check to see if anyone has won or are we out of moves
def win_the_game():
# this function checks for result and returns true or false
if(
(grid['1'] == grid['2'] == grid['3']) or (grid['4'] == grid['5'] == grid['6']) or
(grid['7'] == grid['8'] == grid['9']) or (grid['1'] == grid['4'] == grid['7']) or
(grid['2'] == grid['5'] == grid['8']) or (grid['3'] == grid['6'] == grid['9']) or
(grid['1'] == grid['5'] == grid['9']) or (grid['3'] == grid['5'] == grid['7'])
):
return True
# checks if there are any moves left
elif not places:
return False
else:
return False
# input / grid update function
def taking_turns():
# this function asks user for input
# use RAW_INPUT to make it a string
print
print map(str, places)
choice = raw_input("\nEnter "+turn+"'s choice: ")
if choice in places:
# this removes the number from the available list
# and replaces numbers in grid with user input
places.remove(choice)
grid[choice] = turn
# Logic loop
while places:
grid_display() # always display the grid
if turn == "O": # giving turns.
turn = 'X'
taking_turns()
if win_the_game() == True: # if the called function returns true in this 'if'
result = turn # player 1 wins
grid_display() # Winners GRID
break
else:
turn = 'O'
taking_turns()
if win_the_game() == True:
result = turn
grid_display() # Winners GRID
break
# results
print
print(result, "won the game!!") # printing result
print
My problem is, after calling the function check_win in the gameloop,
even though the function evaluates false(I've checked so this is the
case), I assign this false value to gamePlaying inside the loop,
however the game loop gamePlaying conditional still evaluates true
and keeps going.
def check_win(): #function checks for three in a row across, down, and diagonals
for x in range (0, 3) :
y = x*3
if (board[y] == board[(y + 1)] and board[y] == board[(y + 2)]):
gamePlaying = False
else:
gamePlaying = True
if (board[x] == board[(x + 3)] and board[x] == board[(x + 6)]):
gamePlaying = False
else:
gamePlaying = True
if((board[0] == board[4] and board[0] == board[8]) or
(board[2] == board[4] and board[4] == board[6])):
gamePlaying = False
else:
gamePlaying = True
return(gamePlaying)
currentPlayer = [first_player,second_player] #creates list to iterate over turns
gamePlaying = True #bool for gameloop
while gamePlaying: #main game loop
for i in currentPlayer: #iterates over current player to switch turns
draw_board()
place_move = int(input(first_move + ' what is your move? ')) #inputs then places move for first_player
board[place_move] = first_player
gamePlaying = check_win() #should take bool output of check_win and store to cont or end gameloop
draw_board()
place_move = int(input(second_move + ' what is your move? ')) #inputs then places move for second_player
board[place_move] = second_player
gamePlaying = Check_win() #should take bool output of check_win and store to cont or end gameloop
The issue is that you are using if statements when you mean to use elif. See the docs.
However, what you probably want to do is return False at those points since that would allow the function to exit early and you would have to worry that gamePlaying gets set back to True by later if statements.
I have an excercise to do and I'm stuck. It's the board game Alak, not much known, that I have to code in python. I can link the execrcise with the rules so you can help me better. The code has the main part and the library with all the procedures and function.
from Library_alak import *
n = 0
while n < 1:
n = int(input('Saisir nombre de case strictement positif : '))
loop = True
player = 1
player2 = 2
removed = [-1]
board = newboard(n)
display(board, n)
while loop:
i = select(board, n, player, removed)
print(i)
board = put(board, player, i)
display(board, n)
capture(board, n, player, player2)
loop = True if again(board, n, player, removed) is True else False
if player == 1 and loop:
player, player2 = 2, 1
elif player == 2 and loop:
player, player2 = 1, 2
win(board, n)
print(win(board, n))
And here is the library:
def newboard(n):
board = ([0] * n)
return board
def display(board, n):
for i in range(n):
if board[i] == 1:
print('X', end=' ')
elif board[i] == 2:
print('O', end=' ')
else:
print(' . ', end=' ')
def capture(board, n, player, player2):
for place in range(n):
if place == player:
place_beginning = place
while board[place] != player:
place_end = place
if board[place + x] == player:
return board
else:
return board
def again(board, n, player, removed):
for p in board(0):
if p == 0:
if p not in removed:
return True
else:
return False
def possible(n, removed, player, i, board):
for p in range(n + 1):
if p == 1:
if board[p-1] == 0:
if p not in removed:
return True
else:
return False
def win(board, n):
piecesp1 = 0
piecesp2 = 0
for i in board(0):
if i == 1:
piecesp1 += 1
else:
piecesp2 += 1
if piecesp1 > piecesp2:
print('Victory : Player 1')
elif piecesp2 > piecesp1:
print('Victory : Player 2')
else:
return 'Equality'
def select(board, n, player, removed):
loop = True
while loop:
print('player', player)
i = int(input('Enter number of boxes : '))
loop = False if possible(n, removed, player, i, board)is True else True
return i
def put(board, player, i):
i -= 1
if board[i] == 0:
if player == 1:
board[i] = 1
return board
else:
board[i] = 2
return board
else:
put(board, player, i)
So my problems here are that I have few errors, the first one is that when I enter the number '1' when asked to enter a number of boxes ( which is the place to play on ) nothing happens. Then when entering any other number, either the error is : if board[place + x] == player:
NameError: name 'x' is not defined
or there seems to be a problem with the : if board[place + x] == player:
NameError: name 'x' is not defined
I would appreciate a lot if anyone could help me. I'm conscious that it might not be as detailed as it should be and that you maybe don't get it all but you can contact me for more.
Rules of the Alak game:
Black and white take turns placing stones on the line. Unlike Go, this placement is compulsory if a move is available; if no move is possible, the game is over.
No stone may be placed in a location occupied by another stone, or in a location where a stone of your own colour has just been removed. The latter condition keeps the game from entering a neverending loop of stone placement and capture, known in Go as ko.
If placing a stone causes one or two groups of enemy stones to no longer have any adjacent empty spaces--liberties, as in Go--then those stones are removed. As the above rule states, the opponent may not play in those locations on their following turn.
If placing a stone causes one or two groups of your own colour to no longer have any liberties, the stones are not suicided, but instead are safe and not removed from play.
You shouldn't use "player2" as a variable, there's an easier way, just use "player" which take the value 1 or 2 according to the player. You know, something like that : player = 1 if x%2==0 else 2
and x is just a increasing int from 0 until the end of the game.