human vs machine tic-tac-toe - python

in these days i have been struggling with minimax algorithm and i can say i finally understood it ( thank to another post in stackoverflow). Therefore i opened my editor and i tried to implement it into a EXTREMELY simple ( do not blame me for code please :P) tic tac toe, just to give a try out. everything is working, but the computer move function always retrieve me -1. i'm not asking you to give me code, just the "why" it does that. i have searched throught the code many times, but found nothing . The code is probably really similar to another one i found on the web. here's my code :
# COMPUTER AI
def computer_move():
best_move = minimax_recurse(game_board,active_player, 0)
print "The best move is ", best_move
make_move(game_board,best_move, active_player)
print "COMPUTER MOVE DONE"
def minimax_recurse(game_board,player,depth):
winner = is_winner(game_board)
if winner == active_player :
return 1
elif winner is not active_player :
return -1
elif len(get_move_list(game_board)) == 0 :
return 0
if player == player1 :
other_player = player2
other_player = player1
if player == active_player :
alpha = -1
alpha = 1
movelist = get_move_list(game_board)
for move in movelist :
board2 = game_board
make_move(board2,move,player)
subalpha = minimax_recurse(board2, other_player, depth + 1)
if player == active_player :
if depth == 0 and alpha <= subalpha:
best_move = move
alpha = max(alpha,subalpha)
return alpha
else :
alpha = min(alpha,subalpha)
return alpha
# BOARD FUNCTIONS
game_board = ([1,2,3],[4,5,6],[7,8,9])
def print_board(board) :
for row in board :
print row
def make_move(game_board,player_move,active_player):
x = 0
y = 0
player_move = int(player_move)
if player_move == 1 :
x = 0
y = 0
elif player_move == 2 :
x = 0
y = 1
elif player_move == 3 :
x = 0
y = 2
elif player_move == 4 :
x = 1
y = 0
elif player_move == 5 :
x = 1
y = 1
elif player_move == 6 :
x = 1
y = 2
elif player_move == 7 :
x = 2
y = 0
elif player_move == 8 :
x = 2
y = 1
elif player_move == 9 :
x = 2
y = 2
elif player_move >= 10 :
print "value is too high"
skip = False
return board
if game_board[x][y] == "O" or game_board[x][y] == "X" :
print "move not avaiable"
return game_board
game_board[x][y] = active_player
return game_board
def is_winner(board):
for i in range (0,3) :
if board[i][0] == player1 and board[i][1] == player1 and board[i][2] == player1 :
return player1
if board[i][0] == player2 and board[i][1] == player2 and board[i][2] == player2 :
return player2
# checking for obliqual, that's quite bad and slow check but it works
if board[0][0] == player1 and board[1][1] == player1 and board[2][2] == player1 :
return player1
if board[0][0] == player2 and board[1][1] == player2 and board[2][2] == player2 :
return player2
if board[2][0] == player1 and board[1][1] == player1 and board[0][2] == player1 :
return player1
if board[2][0] == player2 and board[1][1] == player2 and board[0][2] == player2 :
return player2
return None
def get_move_list (game_board) :
move = [0]
for row in game_board :
for i in row :
if isinstance(i,int) == True :
move.append(i)
move.remove(0)
return move
# Main Loop
player1 = "X"
player2 = "O"
print_board(game_board)
while True :
active_player = player1
# this is for player move
print get_move_list(game_board)
player_move = int(raw_input("Please insert your move >>> "))
make_move(game_board,player_move,active_player)
print_board(game_board)
if is_winner(game_board) == player1 :
print "Player1 is the winner"
break
if is_winner(game_board) == player2 :
print "Player2 is the winner"
break
print get_move_list(game_board)
# computer time
active_player = player2
computer_move()
print_board(game_board)
if is_winner(game_board) == player1 :
print "Player1 is the winner"
break
if is_winner(game_board) == player2 :
print "Player2 is the winner"
break

Without debugging all your code, one thing that seems wrong is your use of "best_move" variable (global uninitialized) as both a holder for a move as well as holder for -1/0/+1 result of minimax_recurse. So it's being overwritten by your minmax algorithm. You need more variables, clearer initialization of them, and consistent usage.

The root cause of the -1 always returning is that winner is not active_player returns True when winner is None. You could use a variable to keep track of the other (inactive) player, or you could use the ternary operator: elif winner is (player1 if player2 == active_player else player2)
Though that's not the only issue:
if player == active_player :
alpha = -1
alpha = 1
That will always set alpha to 1. The lines directly above that have the same problem. The variable naming issue pointed out in the other answer is also true.

Related

Get Numbers On Array Play Game with Numbers and Get Next Numbers On Array

I am trying to make a little game for my self.
first i have an arrays.
After this i want to play flip coin game with this data after it runs 1,2 or 3 wins.
After this code
import random
rows = [[20,30,40],[30,40,50],[50,20,30]]
#Get number to veribals
player1 = rows[0][0]
player2 = rows[0][1]
player3 = rows[0][2]
coin = [1,2]
print(player1)
print(player2)
print(player3)
game_on = False
total_game = player1 + player2 + player3
while not game_on:
flip_coin = random.choice(coin)
player1_flip = random.choice(coin)
player2_flip = random.choice(coin)
player3_flip = random.choice(coin)
print(total_game)
# Testing Code
print(f"Total Game Left {total_game}")
print(f"Computer : {flip_coin}")
print(f"Player 1 : {player1_flip} Player 2 : {player2_flip} Player 3 : {player3_flip}")
print(f"Player 1 Left Points : {player1} Player 2 Points : {player2} Player 3 Points : {player3}")
if player1_flip == flip_coin:
if player1 == 0:
pass
else:
player1 -= 1
if player2_flip == flip_coin:
if player2 == 0:
pass
else:
player2 -= 1
if player3_flip == flip_coin:
if player3 == 0:
pass
else:
player3 -= 1
total_game = player1 + player2 + player3
if total_game == 1:
game_on = True
if player1 == 1:
print("Player 1 is Won")
elif player2 == 1:
print("Player 2 is Won")
elif player3 == 1:
print("Player 3 is Won")
After this come, how can move next array [30,40,50] and [50,20,30].
After all done, i need get 1. Game Player 1 won, 2. Game player 2 won ect.
How can i do it ?
You just need to wrap most of your code in a for loop:
import random
rows = [[20,30,40],[30,40,50],[50,20,30]]
for row in rows
#Get number to veribals
player1 = row[0]
player2 = row[1]
player3 = row[2]
...
# rest of code indented here like this:
coin = [1,2]

NameError, variable not defined in Python

so the ultimate goal is to run best 2 out of 3 games of rock, paper, scissors, lizard, spock. i haven't added a loop yet or anything like that i'm trying to get the game itself running first but I'm coming across a NameError, it's saying the 'result' variable is undefined.
I've tried returning it but that doesn't appear to be working, but I also maybe don't know what I'm doing?
def number_to_name(number):
if number == 1:
return 'scissors'
elif number == 2:
return 'rock'
elif number == 3:
return 'paper'
elif number == 4:
return 'lizard'
elif number == 5:
return 'spock'
else:
print ("Error: Invalid number")
def name_to_number(name):
if name == 'scissors':
return 1
elif name == 'rock':
return 2
elif name == 'paper':
return 3
elif name == 'lizard':
return 4
elif name == 'spock':
return 5
else:
print ("Error: Invalid number")
def rpsls(name):
player_score, computer_score = (0, 0)
player_input = name_to_number(name)
computer_input = random.randint(1,5)
result = (player_input - computer_input) % 5
if result == 1 or result == 2:
print("player wins")
player_score += 1
print("Player {}, Computer {}". format(player_score, computer_score))
elif result == 3 or result == 4:
game = "computer wins"
computer_score += 1
print("Player {}, Computer {}". format(player_score, computer_score))
elif result == 0:
game = "it's a tie"
print("Player {}, Computer {}". format(player_score, computer_score))
else:
print("error")
rpsls("rock")
rpsls("spock")
rpsls("paper")
rpsls("lizard")
rpsls("scissors")
Your conditions should be inside the rpsls function.Because you result variable is local variable. You can't fetch this variable globally.
> def rpsls(name):
> player_score, computer_score = (0, 0)
> player_input = name_to_number(name)
> computer_input = random.randint(1, 5)
> result = (player_input - computer_input) % 5
>
>
> if result == 1 or result == 2:
> print("player wins")
> player_score += 1
> print("Player {}, Computer {}".format(player_score, computer_score))
>
> elif result == 3 or result == 4:
> game = "computer wins"
> computer_score += 1
> print("Player {}, Computer {}".format(player_score, computer_score))
>
> elif result == 0:
> game = "it's a tie"
> print("Player {}, Computer {}".format(player_score, computer_score))
>
> else:
> print("error")
Your variable result is inside the function rpsls. So the scope of result lies to the function only.
A easy solution would be assign a 0 value to result before the function 'rpsls'
This way your updating a globally defined variable inside the function.
result = 0
def rpsls(name):
#Your code
The best way would be to write a class, have a class level variable result, and put all this code into the class.
First of all, since result is only defined in the function, it is only accessable inside that specific function, unless you choose to use the global method, which I wouldn't recommend.
Second, since you called result before you called the function that actually defines result, even if you use global, it will still not be defined for that specific line.

how can i fix the undefined error in python?

Hy , i am stuck at the last part were i have to write the place marker(place_marker(the_Board, player2_marker, position)) , it doesn't recognize the marker , it said it is a undefined variable , any ideas ?
Here is my script : (it isn't finished yet because of that problem )
def display_board(board):
print('\n'*3)
print(board[7]+'|'+board[8]+'|'+board[9])
print(board[4]+'|'+board[5]+'|'+board[6])
print(board[1]+'|'+board[2]+'|'+board[3])
#test_board = ['#','X','O','X','O','X','O','X','O','X'] #test
#display_board(test_board) #test
def player_input():
print('\n'*3)
Player1_name=input('What is your name player1 ? : ')
Player2_name=input('What is your name player2 ? : ')
marker = ''
while marker != 'X' and marker != '0' :
Player1=marker = input('{}, please chose X or 0 : '.format(Player1_name))
if Player1 == 'X':
Player2 = '0'
else:
Player2= 'X'
return ('OK, {} is : {}\nAnd {} is : {} ' .format(Player1_name,Player1,Player2_name,Player2))
#print(player_input()) #test
def place_marker(board, marker, position):
board[position] = marker
#print(place_marker(test_board,'2',8))
#print(display_board(test_board))
def win_check(board, mark):
return ((board[7] == mark and board[8] == mark and board[9] == mark) or (board[4] == mark and board[5] == mark and board[6] == mark) or (board[1] == mark and board[2] == mark and board[3] == mark) or (board[7] == mark and board[4] == mark and board[1] == mark) or (board[8] == mark and board[5] == mark and board[2] == mark) or (board[9] == mark and board[6] == mark and board[3] == mark) or (board[7] == mark and board[5] == mark and board[3] == mark) or (board[9] == mark and board[5] == mark and board[1] == mark))
#print(win_check(test_board,'X')) #test
import random
def choose_first():
flip = random.randint(0,1)
if flip == 0 :
return 'Player1'
else:
return 'Player2'
def space_check(board, position):
return board[position] == ''
def full_board_check(board):
for i in range(1, 10) :
if space_check(board, i):
return False
return True
def player_choice(board):
print('\n'*3)
position = 0
while position not in [1,2,3,4,5,6,7,8,9] or not space_check(board,position):
position = int(input('Please chose a position from 1 to 9 : '))
return position
def replay():
choise = input('Do you wnat to play again, yes or no ? : ')
return choise == 'yes'
print('Welcome to Tic Tac Toe!')
while True:
the_board=[' '] *10
player_input()
turn=choose_first()
print(turn+'will go first')
play_game=input('Ready to play ? y or n ? : ')
if play_game == 'y' :
game_on = True
else:
game_on = False
while game_on :
if turn == 'Player1' :
display_board(the_board)
position=player_choice(the_board)
place_marker(the_Board, player2_marker, position) ### HERE
if win_check (the_board ,Player1) :
display_board(the_board)
print('{} has Won !!')
game_on = False
if not replay() :
break
here is the console after i run the code , it don't recognize the number i thick because the final script isn't done ,
Welcome to Tic Tac Toe!
What is your name player1 ? : SALLY
What is your name player2 ? : Sammy
Player1will go first
Ready to play ? y or n ? : y
| |
| |
| |
Please chose a position from 1 to 9 : 1
Please chose a position from 1 to 9 : 2
Please chose a position from 1 to 9 : 3
it is still asking me for a number
i have tried to change some parameters of the place_marker code but it didn't work
def place_marker(board, marker, position):
board[position] = marker
place_marker(the_Board, player2_marker, position)
Your problem is exactly where you mark it:
place_marker(the_Board, player2_marker, position)
This is the first reference to player2_marker. You need to initialise it somewhere before you reference it! I assume this is as simple as setting it to 'O' or 'X' in your case.
Hi thanks for your answer , i realize that , i compared my script with the course solution script and i saw that i made a modify at player input , that was just returning that formatted sentence, so i change my code with that one which return 'x' , '0' or '0', 'x' , that is assigned to the player 1,player 2 = player_input() , i meat player 1 = x and player 2 = o or reverse , so that variable i can introduce in the place_marker function as X (assigned to player 1) or O (assigned to player 2 ) , also little mistakes , and it finally works now !!

Why is the check "x not in y" not working?

I have written up a Tic Tac Toe game however there seems to be an error.
None of the players have won, nor there still exists "-" in board, the game just ends to a draw after some playing.
(Please see in def check(): last elif statement.)
Could you please help me what is wrong with the code?
(Sorry I am a beginner and please excuse the lack of my code)
Here is my code below:
import sys
board = [["-","-","-"],["-","-","-"],["-","-","-"]]
def print_board():
for x in board:
print(" ".join(x))
P1X = input("Hi Player 1. What is your name? ")
P2O = input("Hi Player 2. What is your name? ")
def play_again():
answer = input("It is a draw!. Do you want to play again? Y/N ").upper()
if answer == "Y":
play_game()
else:
sys.exit()
def check():
if board[0][0] == board[0][1] == board[0][2]:
check_win(0, 0)
elif board[0][0] == board[1][0] == board[2][0]:
check_win(0, 0)
elif board[0][0] == board[1][1] == board[2][2]:
check_win(0, 0)
elif board[0][1] == board[1][1] == board[2][1]:
check_win(1, 1)
elif board[0][2] == board[1][2] == board[2][2]:
check_win(2, 2)
elif board[1][0] == board[1][1] == board[1][2]:
check_win(1, 1)
elif board[2][0] == board[2][1] == board[2][2]:
check_win(2, 2)
elif board[0][2] == board[1][1] == board[2][0]:
check_win(1, 1)
elif "-" not in board:
print("It is a draw!")
play_again()
else:
pass
def check_win(row,col):
if board[row][col] == 'X':
print_board()
print("{0} has won the game. Game Over!".format(P1X))
play_again()
elif board[row][col] == "O":
print_board()
print("{0} has won the game. Game Over!".format(P2O))
play_again()
else:
pass
count = 0
def place(row, col):
if count == 0:
board[row][col] = "X"
else:
board[row][col] = "O"
def play_game():
global count
print("Please start the game {0}".format(P1X))
while count != 892:
row_input = int(input("Please select the row ")) -1
col_input = int(input("Please select the column ")) -1
place(row_input, col_input)
check()
print_board()
if count == 0:
count = 1
print("It is now {0}'s turn".format(P2O))
else:
count = 0
print("It is now {0}'s turn".format(P1X))
play_game()
Your program doesn't define check_win, so I am not sure how it works at all. Your problem, however, is that you use a list of rows as your board representation, presumably starting with each board element as '-' to indicate unplayed spaces.
Depending on the rest of your code you might find it easier to use a dictionary as the board representation, with two-element tuples as subscripts.
As the code is now that last test would need to be modified to test that no row contains a '-', which you could do with the test:
if not any('-' in row for row in board):
At present you are comparing lists with strings. That's never going to give you equality.

Where exactly does a python function's return value go?

My Rock Paper Scissors code doesn't work and I'm assuming it's because I'm using the return value incorrectly. What should I do?
EDIT, so I've stored the return like this
def results (x, y):
if (x == "R" or x == "rock" or x == "r" or x == "Rock" or x == "ROCK") and (y == "S" or y == "s" or y == "Scissors" or y == "SCISSORS" or y == "scissors"):
winner = 1
return winner
But how do I get "winner" to print outside of the function?
OLD
player1 = input ("Player 1: Please enter either Rock, Paper or Scissors:")
player2 = input ("Player 2: Please enter either Rock, Paper or Scissors:")
def results (x, y):
if (x == "R" or x == "rock" or x == "r" or x == "Rock" or x == "ROCK") and (y == "S" or y == "s" or y == "Scissors" or y == "SCISSORS" or y == "scissors"):
return 1
else:
if (x == "rock" or x == "r" or x =="R" or x == "Rock" or x == "ROCK") and (y == "P" or y == "p" or y == "paper" or y == "Paper" or y == "PAPER"):
return 2
else:
if (x == "rock" or x =="R" or x == "r" or x == "Rock" or x == "ROCK") and (y == "rock" or y =="R" or y == "r" or y =="Rock" or y == "ROCK"):
return 0
else:
print ("Sorry, I didn't understand your input")
results (player1, player2)
if results == 1:
print ("Player 1 wins!")
else:
if results == 2:
print("Player 2 wins!")
else:
if results == 0:
print("It was a tie!")
The return value isn't automatically stored anywhere. You need to store it manually:
result = results(player1, player2)
if result == 1:
...
If you look up at the top of your code, you'll see you already did the right thing with the input function:
player1 = input ("Player 1: Please enter either Rock, Paper or Scissors:")
Functions you define yourself should be handled the same way.
In response to the edit: Creating a local variable inside results won't help. The code that calls the function needs to store the return value. (People have designed languages that work the way you're trying to get it to work. The result is a huge headache with unrelated parts of the program stomping over each other's data.)

Categories