Simple 2 Players Tic Tac Toe Python - python

I am setting up a 2-player tic tac toe game (it's a homework). But I don't understand what mistakes I make.
def start_move(board, letter, move):
board[move] = letter
def next_player(board, player_1_letter):
#determine 2 players' letter position
if player_1_letter == "X":
player_2_letter = "O"
else:
player_2_letter = "X"
def if_board_full(board):
#if the board is full, back to "True"
for i in range(1, 10):
if free_space(board, i):
return False
return True
print("Welcome to tic tac toe !!!")
while True:
#renew the board
the_board = [" "] * 10
player_1_letter, player_2_letter = input_letter()
turn = first_turn()
print(turn + " will go first.")
gamestarts = True
while gamestarts:
if turn == "Player who choose O.":
gameboard(the_board)
move = firstplayermove(the_board)
start_move(the_board, player_1_letter, move)
if winner(the_board, player_1_letter):
gameboard(the_board)
print("Congratulationsss!!!!" + player_1_letter + " has won!")
gamestarts = False
else:
if free_space(the_board):
gameboard(the_board)
print("Tie!")
break
else:
turn = "Player who choose X"
else:
#player 2's turn
move = next_player(the_board, player_2_letter)
start_move(the_board, player_2_letter, move)
if winner(the_board, player_2_letter):
gameboard(the_board)
print("Player 2 has won!!! Congratulations!")
gamestarts = False
else:
if free_space(the_board):
gameboard(the_board)
print("Tie!!!")
break
else:
turn = "Player who choose O"
if not play_again():
break
I expect the game (code) is ok (for me)... but it keep saying.
Traceback (most recent call last): File
"C:\Users\ASUS\Desktop\Python\projectdemo.py", line 122, in
start_move(the_board, player_2_letter, move) File "C:\Users\ASUS\Desktop\Python\projectdemo.py", line 51, in start_move
board[move] = letter TypeError: list indices must be integers or slices, not NoneType

On line 50 you set move = next_player(the_board, player_2_letter). The function next_player() doesn't return any value, so move doesn't get a value.
Change next_player() to this:
def next_player(board, player_1_letter):
#determine 2 players' letter position
if player_1_letter == "X":
player_2_letter = "O"
else:
player_2_letter = "X"
return player_2_letter

You haven't defined move as anything in board[move]. It doesn't know what to do with it.

Related

List value being overwritten even though I am checking for it

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].

TicTacToe doesn't apply Win-Conditions && Wrong moves on minimax

i am trying to learn python and have been trying to programm a simple tictactoe game.
Below is the code:
import random
class TicTacToe03:
def __init__(self):
# first, the board
self.board = self.board = [" ", " ", " ", " ", " ", " ", " ", " ", " "]
# then, the symbols the players will choose
self.playerSymbol = ""
self.aiSymbol = ""
# the game is always ongoing, unless somebody won
self.gameOngoing = True
# you also need to tell the ai how different conditions are evaluated
self.scoreBoard = {
self.playerSymbol: -10, # if the player wins, it is seen as smth bad from the ai
self.aiSymbol: 10,
"tie": 0
}
# every tictactoe game starts by drawing the board
def drawBoard(self):
print("""
{} | {} | {}
-----------
{} | {} | {}
-----------
{} | {} | {}
""".format(*self.board))
# then, eveybody chooses what the like
def chooseYourPlayer(self):
self.playerSymbol = input("choose your player X/O ").upper()
if self.playerSymbol == "X":
self.aiSymbol = "O"
else:
self.aiSymbol = "X"
# everybody has to behave and leave their turn when it's over
def nextPlayer(self, player):
if player == self.playerSymbol:
return self.aiSymbol
return self.playerSymbol
# ppl also have to be able to make moves
def move(self, player, index):
self.board[index] = player
# and find what moves they CAN make, so they don't override each-other
def availableMoves(self):
availableMoves = []
for fieldIndex in range(len(self.board)):
if self.board[fieldIndex] == " ":
availableMoves.append(fieldIndex) # yes, i append indexes, not empty fields
return availableMoves
def getMoves(self, player):
playerMoves = []
for fieldIndex in range(len(self.board)):
if self.board[fieldIndex] == player:
playerMoves.append(fieldIndex)
return playerMoves
# here is the algo to check who won, based on a set of winPos is subset of playerMoves
def won(self):
winningPositions = [{0, 1, 2}, {3, 4, 5}, {6, 7, 8},
{0, 4, 8}, {2, 4, 6}, {0, 3, 6},
{1, 4, 7}, {2, 5, 8}]
for player in ("X", "O"):
playerPositions = self.getMoves(player)
for position in winningPositions:
if position.issubset(playerPositions):
print(player + "wins")
self.gameOngoing = False
return player
if self.board.count(" ") == 0: # and this dude outside of the main loop
print("Guess it's a draw")
self.gameOngoing = False
return "tie"
def minimax(self, isMaximizing, player):
if not self.gameOngoing: # base in minimax: if this is an end-state, return it's evaluation
return self.scoreBoard[self.won()]
if isMaximizing:
bestScore = float("-Infinity") # the worst eval for max
for move in self.availableMoves():
self.move(player, move)
score = self.minimax(False, self.nextPlayer(player)) # you should pick the max of what your opponent chooses
self.move(" ", move)
bestScore = max(bestScore, score)
return bestScore
else:
bestScore = float("Infinity")
for move in self.availableMoves():
self.move(player, move)
score = self.minimax(True, self.nextPlayer(player))
self.move(" ", move)
bestScore = min(bestScore, score)
return bestScore
def findOptimalMove(self, player):
goldenMiddle = 0
choices = []
for move in self.availableMoves():
self.move(player, move)
score = self.minimax(True, player)
self.move(" ", move)
if score > goldenMiddle:
choices = [move] # this is a one-element list
break
elif score == goldenMiddle:
choices.append(move)
# here is the code block that mustn't be wrongly interpreted:
# the idea is: you choose a random element, from a ONE-ELEMENT list!!!
if len(choices) > 0:
return random.choice(choices)
else:
return random.choice(self.availableMoves())
def play(self):
self.chooseYourPlayer()
while self.gameOngoing:
personMove = int(input("Choose a position (1-9) "))
self.move(self.playerSymbol, personMove - 1)
self.drawBoard()
if not self.gameOngoing:
break
print("Computer choosing move...")
aiMove = self.findOptimalMove(self.aiSymbol)
self.move(self.aiSymbol, aiMove)
self.drawBoard()
print("Thanks for playing :)")
tictactoe = TicTacToe03()
tictactoe.play()
The game "works", as of it displays the fields of the user, however it won't show whether anybody won or not.
As you can see, i tried implementing the simple minimax algorithm, but that doesn't work properly either, because the ai just chooses the next available field to go to and not the one it logically should.
As for the errors i am getting: i only got one once, after the board was full and it was the following: IndexError: Cannot choose from an empty sequence (on line 133).
I have also posted another version of this, where the "winning" issue is not present ( TicTacToe and Minimax ), but since nobody was answering that question, I thought it would be helpful asking again (sorry if i did anything wrong)
As always, I remain open to suggestions and ways to improve my code :)
In my opinion, the only issue is that you forgot to call self.won() in the play() method:
def play(self):
self.chooseYourPlayer()
while self.gameOngoing:
personMove = int(input("Choose a position (1-9) "))
self.move(self.playerSymbol, personMove - 1)
self.drawBoard()
self.won() #<--- call self.won() here
if not self.gameOngoing:
break
print("Computer choosing move...")
aiMove = self.findOptimalMove(self.aiSymbol)
self.move(self.aiSymbol, aiMove)
self.drawBoard()
print("Thanks for playing :)")
I think you tried to do something similar in minimax() method. But I didn't understand what did you mean by:
if not self.gameOngoing:
return self.scoreBoard[self.won()]

Recursive Minimax Function for Tic Tac Toe

I have recently being try to make a tic tac toe game using the mini max algorithm. I first created a board, then two player. Afterwards, I changed one of the players into the algorithm. I tried using something similar to this javascript implementation. I am not getting an syntax error, just the algorithm is not working.
For example, take the following game sequence.
The algorithm starts the game and places an "X" at the top right of the board or in index[0].
I, the player place "O" in the top right of the board or in index[2].
The algorithm places an "X" at the top center of the board or in index [1].
I, the player place "O" in the middle center of the board or in index[4].
The algorithm places an "X" at the middle left of the board or in index [3].
The error is that rather than stopping the win, the algorithm is playing the next free position.
In the min-max algorithm, this is a minimizing agent (seeks the least score) and the maximizing agent (the higher score) (in this case the AI). Below is the code, can you help me find the issue? Or how should I go along? Because I have been trying for the last two days. Hopefully the explanation above made sense.
board = ["."] * 9
winning_comb = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[3,4,6],[0,4,8]]
game = True
def new_board():
print (board[0] + "|" + board[1] + "|" + board[2])
print (board[3] + "|" + board[4] + "|" + board[5])
print (board[6] + "|" + board[7] + "|" + board[8])
new_board()
def winning(comb):
global game
for l in range(len(winning_comb)):
a = winning_comb[l][0]
f = winning_comb[l][1]
v = winning_comb[l][2]
if comb[a] == comb[f] == comb[v] == "O" or "x" == comb[a] == comb[f] == comb[v]:
game = False
if comb[a] == "x":
return 1
else:
return -1
break
else:
game = True
def minmax(board,depth, ismax):
if winning(board) != None:
h = winning(board)
return h
else:
if ismax == True:
bestscore = float('-inf')
for k in range(len(board)):
if board[k] == ".":
board[k] = "x"
score = minmax(board,depth+1,False)
board[k] = '.'
bestscore = max(bestscore, score)
return bestscore
else:
bestscore = float('inf')
for k in range(len(board)):
if board[k] == ".":
board[k] = "O"
score = minmax(board,depth+1,True)
board[k] = '.'
bestscore = min(bestscore,score)
return bestscore
def player1() :
bestscore = float('-inf')
bestmove = 0
for k in range(len(board)):
if board[k] == ".":
board[k] = "x"
score = minmax(board, 0, False)
board[k] = "."
if score > bestscore:
bestscore = score
bestmove = k
board[bestmove] = "x"
new_board()
def player2():
number = int(input("Please enter your poistion?") )
board[number - 1 ] = "O"
new_board()
winning(board)
while game==True:
player1()
player2()
[3,4,6] shouldn't be a winning combination. It should be [2,4,6]
Some issues:
[3,4,6] should be [2,4,6]
Indentation of return bestscore is wrong in the second instance: currently it interrupts the loop.
If you backtrack after game = False is executed, that assignment should be undone. For that reason it is probably easier to not use that variable at all, and just call the function winning when needed. The main loop could then be:
while winning(board) is None:
player1()
if winning(board) is not None: # need to exit
break
player2()
bestscore will be (-)infinity when there is no more free cell in the grid, and the game really is a draw. In that case bestscore should be 0, so this draw is considered better than a loss, and worse than a win. So make sure winning does not return None in that case, but 0:
if not "." in comb:
return 0
Not an error, but it is a bit odd that some functions take the board as argument, and others not. Make this consistent, and always pass the board as argument (player1(board), player2(board) and winning(board)).
With these changes, the AI will play the best play, although the calculation for the first move takes quite some time. You could improve by applying alpha-beta pruning.

How to find tie game python

Hi i was making this tic tac toe game and i watched some tutorials for it, but there wasn't any game that could end with tie game i tried to make one but the game freezes when tie game appears don't worry about my Finnish variables and comments
import random
board = [0,1,2,
3,4,5,
6,7,8]
def show():
print board[0], '|',board[1],'|',board[2]
print '----------'
print board[3], '|',board[4],'|',board[5]
print '----------'
print board[6], '|',board[7],'|',board[8]
def checkLine(char, spot1, spot2, spot3):
if (board[spot1] == char) and (board[spot2] == char) and (board [spot3] == char) :
return True
else:
return False
def checkAll(char):
ret = False
if checkLine(char, 0, 1, 2):
ret = True
if checkLine(char, 0,3, 6):
ret = True
if checkLine(char, 1, 4, 7):
ret = True
if checkLine(char, 2, 5, 8):
ret = True
if checkLine(char, 6, 7, 8):
ret = True
if checkLine(char, 3, 4, 5):
ret = True
if checkLine(char, 2, 4, 6):
ret = True
if checkLine(char, 0, 4, 8):
ret = True
return ret
moves = range(9)
numindex = 1
ratkennut = False
while moves:
show()
input = raw_input("Put x: ")
try:
val = int(input)
input = int(input)
except ValueError:
print("Input number!")
input = raw_input("Put x: ")
input = int(input)
if input in moves:
moves.remove(input)
if board [input] != 'x' and board[input] != 'o':
board[input] = 'x'
if checkAll('x') == True:
print "~~ X Won ~~"
ratkennut = True
break;
while moves:
random.seed() #Gives opponents move
opponent = random.choice(moves)
moves.remove(opponent)
if board[opponent] != 'o' and board[opponent] != 'x':
board[opponent] = 'o'
if checkAll('o') == True:
print "~~ O Won ~~"
ratkennut = True
break;
else:
print 'This spot is taken'
else:
print "Tie!"
Question: What's wrong with this code when the game ends with tie game it freezes and i need to ctrl + c how to make it find the tie game and print "tie game"
I edited it and now it works really great!
Your randint move choice in a while loop for the opponent could run indefinitely, especially as the number of valid moves remaining gets smaller. Instead, make a list of valid moves and list.remove() each move from it:
moves = range(9)
This simplifies the user's move:
if input in moves:
moves.remove(input)
The opponent's move:
opponent = random.choice(moves)
moves.remove(opponent)
And determining the end of the game:
while moves:
...
else:
print "It's a tie."
You could count your moves there are only 9 moves in a tic tac toe game.
You want something like:
if not checkAll('o') and not checkAll('x') and moves == 9:
print "Tie Game"
break

IndexErrors in Tic-Tac-Toe program I'm having issues with

I've pasted the code here:
X = "X"
O = "O"
board = []
EMPTY = ""
def instructions_prompt ():
print "\t\t\tNoughts and Crosses"
print \
"""Foolish human. Now that you've entered this Python program,
there is no exit. None! (At any point in the game if you feel
like you are intimidated by my presence, hit 0 to exit)
This challenge of wits will be one of many failures in your life.
The instructions are as follows:
1. Select a number from the following key:
0 | 1 | 2
---------
3 | 4 | 5
---------
6 | 7 | 8
to place X or O which is predetermined by whether or not you start
the game.
2. Try to save face while failing. And don't talk about Fight Club."""
def start_prompt ():
choice = raw_input ("Would you like to go first (Y/N)?")
lower = choice.lower()
if lower == "y":
human = X
computer = O
print "You're",human
print "I am",computer
elif lower == "n":
computer = X
human = O
print "You're",human
print "I'm in",computer
return human, computer
def display_board (board):
print "",board[0],"|",board[1],"|",board[2],""
print "---------"
print "",board[3],"|",board[4],"|",board[5],""
print "---------"
print "",board[6],"|",board[7],"|",board[8],""
def turn_switcher (turn):
if turn == X:
return O
else:
return X
def fresh_board ():
for i in range (9):
board.append (EMPTY)
return board
def request_move ():
try:
square = int(raw_input("Where'd you like your square to be?"))
if square>8 or square<0:
print "This program can't proceed as that number is not on the board."
else:
return square
except:
print "That's not a number on the board. This program can't proceed."
def legal_moves (board):
legal_moves = []
for i in range (9):
if board [i] == EMPTY:
legal_moves.append(i)
return legal_moves
def winner (board):
if board[0] == board [1] == board [2] != EMPTY:
winner = board [0]
return winner
elif board [0] == board [3] == board [6] != EMPTY:
winner = board [0]
return winner
elif board [0] == board [4] == board [8] != EMPTY:
winner = board [0]
return winner
elif board [1] == board [4] == board [7] != EMPTY:
winner = board [1]
return winner
elif board [2] == board [5] == board [8] != EMPTY:
winner = board [2]
return winner
elif board [2] == board [4] == board [6] != EMPTY:
winner = board [2]
return winner
elif board [6] == board [7] == board [8] != EMPTY:
winner = board [8]
return winner
elif EMPTY not in board:
return None
def human_move (board, square):
legal = legal_moves(board)
if square not in legal:
print "This is not a legal move"
sys.exit()
else:
return square
def computer_move (computer, board, human):
best = (4,0,8,2,6,1,3,5,7)
board = board [:]
legal = legal_moves(board)
for i in legal:
board[i] = computer
if winner(board) == computer:
return i
board = EMPTY
#Stopping human from winning
for i in legal_moves(board):
board [i] = human
if winner(board) == human:
return i
for i in best:
if i in legal_moves(board):
return i
def main ():
instructions_prompt ()
human, computer = start_prompt ()
turn = X
board = fresh_board()
request_move ()
display_board (board)
while not winner(board):
if turn == human:
square = request_move()
move = human_move (board, square)
board[move] = human
else:
move = computer_move(computer, board, human)
board[move] = computer
display_board(board)
turn = turn_switcher(turn)
main ()
raw_input ("Enter a key to end.")
TRACKBACK:
Traceback (most recent call last):
File "C:\Users\COMPAQ\Desktop\NoughtsCrosses.py", line 152, in <module>
main ()
File "C:\Users\COMPAQ\Desktop\NoughtsCrosses.py", line 147, in main
move = computer_move(computer, board, human)
File "C:\Users\COMPAQ\Desktop\NoughtsCrosses.py", line 118, in computer_move
board[i] = computer
TypeError: 'str' object does not support item assignment
You have your arguments mixed up for the function computer_move. On line 113, the arguments are in the order computer, board, human. However, on line 147, where computer_move is called, the order is board, computer, human.
Python gave you the confusing index error because Python strings are really just lists of characters. E.g.
>>> "foo"[2] == "o"
True
Update: You're getting this new error because of the last line of computer_move. It should be board[i] = EMPTY rather than board = EMPTY.

Categories

Resources