I recently tried creating a simple Tic Tac Toe AI with minimax (with help from YouTube), but I can't get it to work. The algorithm just spits out the first value it checks instead of going through all of them and giving the best one.
I tried copying the code from the YouTube video but it still doesn't work, can someone tell me what's wrong?
import math
import random
print()
board = {1: ' ', 2: ' ', 3: ' ',
4: ' ', 5: ' ', 6: ' ',
7: ' ', 8: ' ', 9: ' '}
computerLetter = 'X'
playerLetter = 'O'
def print_board(board=board):
for i in range(1, 8, 3):
print('|' + board[i] + '|' + board[i + 1] + '|' + board[i + 2] + '|')
if i < 7:
print('-' * 13)
print()
def space_is_free(position):
if board[position] == ' ':
return True
else:
return False
def free_spaces(board=board):
freeSpaces = 0
for key in board.keys():
if key == ' ':
freeSpaces += 1
return freeSpaces
def make_move(letter, position):
if space_is_free(position):
board[position] = ' ' + letter + ' '
print_board(board)
if check_for_win(board):
if letter == 'O':
print("You win!!")
exit()
else:
print("The computer wins. Better luck next time!")
exit()
elif check_for_tie(board):
print("It's a tie! Well played.")
exit()
else:
print("Invalid choice.")
position = int(input("Enter new position: "))
make_move(letter, position)
def check_for_win(board=board):
if board[1] == board[2] == board[3] != ' ' or board[4] == board[5] == board[6] != ' ' or board[7] == board[8] \
== board[9] != ' ' or board[1] == board[4] == board[7] != ' ' or board[2] == board[5] == board[6] != \
' ' or board[3] == board[6] == board[9] != ' ' or board[1] == board[5] == board[9] != ' ' or board[3]\
== board[5] == board[7] != ' ':
return True
else:
return False
def check_for_win_letter(letter):
if board[1] == board[2] == board[3] == ' ' + letter + ' ' or board[4] == board[5] == board[6] == ' ' + letter + ' '\
or board[7] == board[8] == board[9] == ' ' + letter + ' ' or board[1] == board[4] or board[7] == ' ' +\
letter + ' ' or board[2] == board[5] or board[6] == ' ' + letter + ' ' or board[3] == board[6] or board[9]\
== ' ' + letter + ' ' or board[1] == board[5] == board[9] == ' ' + letter + ' ' or board[3] == board[5] ==\
board[7] == ' ' + letter + ' ':
return True
else:
return False
def check_for_tie(board=board):
for key in board.keys():
if board[key] == ' ':
return False
else:
return True
def player_move(playerLetter='O'):
if free_spaces(board) >= 9:
print_board(board)
position = int(input("Enter position (1-9): "))
make_move(playerLetter, position)
def computer_move(computerLetter='X'):
if free_spaces(board) == 9:
make_move(computerLetter, 5)
else:
bestScore = -math.inf
bestPosition = 0
for key in board.keys():
if space_is_free(key):
board[key] = ' ' + computerLetter + ' '
score = minimax(board, 0, False)
board[key] = ' '
if score > bestScore:
bestScore = score
bestPosition = key
make_move(computerLetter, bestPosition)
print(f"Computer moves to {bestPosition}.")
def minimax(board, depth, isMaximising):
if check_for_win_letter('X'):
return 1 * (free_spaces(board) + 1)
elif check_for_win_letter('O'):
return -1 * (free_spaces(board) + 1)
elif check_for_tie(board):
return 0
if isMaximising:
bestScore = -math.inf
for key in board.keys():
if space_is_free(key):
board[key] = ' ' + computerLetter + ' '
score = minimax(board, depth + 1, False)
board[key] = ' '
bestScore = max(score, bestScore)
return bestScore
else:
bestScore = math.inf
for key in board.keys():
if space_is_free(key):
board[key] = ' ' + playerLetter + ' '
score = minimax(board, depth + 1, True)
board[key] = ' '
bestScore = min(score, bestScore)
return bestScore
while not check_for_win(board):
computer_move('X')
player_move('O')
# gameState = input("Would you like to play again? (y/n)")
#
# if gameState.lower() == 'y':
# main()
# elif gameState.lower() == 'n':
# exit()
# else:
# print("Invalid choice.")
I tried changing the computer and player letters, and whether the computer was maximising or minimising but it didn't work.
I think I have found what is wrong with your code, in the minmax function the first if, elif, else statement always ends with a return statement.
def minimax(board, depth, isMaximising):
if check_for_win_letter('X'):
return 1 * (free_spaces(board) + 1)
elif check_for_win_letter('O'):
return -1 * (free_spaces(board) + 1)
elif check_for_tie(board):
return 0
The else statement is the reason it is failing.
When a return statement is called, it ends the function returning the variable stated, in this case it will always be a number between -9 and 9, and does not run the next block of code, ruining the computer's process to find the best/worst place to play. the else statement means that even if the previous statements are false, it will always return zero, ending the function and halting the process of the next block of code.
I hope this helps! :)
Okay I figured out the problem, it was actually a bunch of logical errors in the functions which were checking for a winner and the winner letter, a few typos per say.
Error 1:
def check_for_win(board=board):
if board[1] == board[2] == board[3] != ' ' or board[4] == board[5] == board[6] != ' ' or board[7] == board[8] \
== board[9] != ' ' or board[1] == board[4] == board[7] != ' ' or ****board[2] == board[5] == board[6]**** != \ # board[6] should be board[8]
' ' or board[3] == board[6] == board[9] != ' ' or board[1] == board[5] == board[9] != ' ' or board[3]\
== board[5] == board[7] != ' ':
return True
Error 2:
def check_for_win_letter(letter):
if board[1] == board[2] == board[3] == ' ' + letter + ' ' or board[4] == board[5] == board[6] == ' ' + letter + ' '\
or board[7] == board[8] == board[9] == ' ' + letter + ' ' or board[1] == board[4] ****or board[7]**** == ' ' +\
letter + ' ' or board[2] == board[5] ****or board[6]**** == ' ' + letter + ' ' or board[3] == board[6] ****or board[9]****\
== ' ' + letter + ' ' or board[1] == board[5] == board[9] == ' ' + letter + ' ' or board[3] == board[5] ==\
board[7] == ' ' + letter + ' ':
return True
The statements within asterisks (*) are the errors, the or statements should be == and the board[6] should again be board[8].
I recently took it upon myself to try and code a TicTacToe board in order to test my understanding of the concepts I learned online. However, I encountered a few problems within my code and do not understand why it doesn't work as intended.
While attempting to get the code to print a winner, my code does not work as intended and does not choose a winner based on the values I have inputted. Sometimes the code runs and a winner is detected two turns after someone has already won, and sometimes it exits the code without a 5th move having even been played.
Below is the code I worked on. It includes insurance that you cannot input an X or an O in a position that has already been taken up and prints the Xs and Os where the players choose. I believe that the errors take place somewhere in the row(), column(), and diagonal() parts of the code.
player = 0
player_add = 1
winner = None
already_taken = []
turns_taken = 0
board = [
"-", "-", "-",
"-", "-", "-",
"-", "-", "-"
]
def handle_turn(turn, turn_add):
while turn % 2 == 0:
position = int(input("Choose a position from 1-9 to add an \"X\": ")) - 1
already_taken.append(position)
board[position] = "X"
turn += turn_add
display_board()
while already_taken.count(position) > 1:
print("Position already taken.")
board[position] = "O"
display_board()
already_taken.remove(position)
turn += turn_add
while turn % 2 == 1:
position = int(input("Choose a position from 1-9 to add an \"O\": ")) - 1
already_taken.append(position)
board[position] = "O"
turn += turn_add
display_board()
while already_taken.count(position) > 1:
print("Position already taken.")
board[position] = "X"
display_board()
already_taken.remove(position)
turn += turn_add
def display_board():
print(board[0] + "|" + board[1] + "|" + board[2])
print(board[3] + "|" + board[4] + "|" + board[5])
print(board[6] + "|" + board[7] + "|" + board[8])
def play_game():
display_board()
handle_turn(player, player_add)
def rows():
global running
if board[0] and board[1] and board[2] == board[0] and board[0] != "-":
running = False
return board[0]
if board[3] and board[4] and board[5] == board[3] and board[3] != "-":
running = False
return board[3]
if board[6] and board[7] and board[8] == board[6] and board[6] != "-":
running = False
return board[6]
return
def columns():
global running
if board[0] and board[3] and board[6] == board[0] and board[0] != "-":
running = False
return board[0]
if board[1] and board[4] and board[7] == board[1] and board[1] != "-":
running = False
return board[3]
if board[2] and board[5] and board[8] == board[2] and board[2] != "-":
running = False
return board[6]
return
def diagonals():
global running
if board[0] and board[4] and board[8] == board[0] and board[0] != "-":
running = False
return board[0]
if board[2] and board[4] and board[6] == board[2] and board[2] != "-":
running = False
return board[3]
return
def check_if_win():
global winner
# Rows
row_winner = rows()
# Columns
column_winner = columns()
# Diagonals
diagonal_winner = diagonals()
if row_winner:
winner = row_winner
elif column_winner:
winner = column_winner
elif diagonal_winner:
winner = diagonal_winner
else:
winner = None
def check_if_game_over():
check_if_win()
running = True
while running:
play_game()
check_if_game_over()
if winner == "X":
print("Player " + str(winner) + " has won!")
elif winner == "O":
print("Player " + str(winner) + " has won!")
elif winner is None:
print("Whoops! Looks like you both loose.")
'''
You almost got it right, but you made a typo:
if board[0] and board[3] and board[6] == board[0] and board[0] != "-":
This should be:
if board[0] == board[3] and board[6] == board[0] and board[0] != "-":
I would say, if you fix all of those. It may work - at least a little bit better.
Hope this taught you not to copy-paste code too much, as you can easily copy the same mistake over and over again.
So, what happened? Well, if you have if(board[0] and board[3]) like you did, it checks if board[0] evaluates to true and the same for board[3]. The way true and false is implemented is that false = 0, and true is just the opposite of false: true = !false. So, what you were checking for was pretty much, "is board[0] zero?" No, so that is true. So, no wonder that you were confused.
def check_over(mark):
######################################
#This checks for a win################
######################################
if board[1] == mark and board[2] == mark and board[3] == mark
or board[4] == mark and board[5] == mark and board[6] == mark
or board[7] == mark and board[8] == mark and board[9] == mark
or board[1] == mark and board[4] == mark and board[7] == mark
or board[2] == mark and board[5] == mark and board[8] == mark
or board[3] == mark and board[6] == mark and board[9] == mark
or board[1] == mark and board[5] == mark and board[9] == mark
or board[3] == mark and board[5] == mark and board[7] == mark:
print(f'{mark} won!')
This code yields the following error when I try to call it:
if board[1] == mark and board[2] == mark and board[3] == mark
^
SyntaxError: invalid syntax
This function is meant to check for a win in a tic-tac-toe game based on a python list named board.
Where is my problem?
EDIT: While trying to fix the code I got another error, still need help!
def check_over(mark):
######################################
#This checks for a win################
######################################
if board[1] == mark and board[2] == mark and board[3] == mark or board[4] == mark and board[5] == mark and board[6] == mark or board[7] == mark and board[8] == mark and board[9] == mark or board[1] == mark and board[4] == mark and board[7] == mark or board[2] == mark and board[5] == mark and board[8] == mark or board[3] == mark and board[6] == mark and board[9] == mark or board[1] == mark and board[5] == mark and board[9] == mark or board[3] == mark and board[5] == mark and board[7] == mark:
print(f'{mark} won!')
return True
elif " " not in board:
###############################
#This checks for tie###########
###############################
print('The game ended in a tie!')
return True
It gives me the following error:
def check_over(mark):
^
IndentationError: expected an indented block
Your SyntaxError is occuring because you're not using \ characters to break across multiple lines
def check_over(mark):
######################################
#This checks for a win################
######################################
if board[1] == mark and board[2] == mark and board[3] == mark \
or board[4] == mark and board[5] == mark and board[6] == mark \
or board[7] == mark and board[8] == mark and board[9] == mark \
or board[1] == mark and board[4] == mark and board[7] == mark \
or board[2] == mark and board[5] == mark and board[8] == mark \
or board[3] == mark and board[6] == mark and board[9] == mark \
or board[1] == mark and board[5] == mark and board[9] == mark \
or board[3] == mark and board[5] == mark and board[7] == mark:
print(f'{mark} won!')
You can not have have new lines in the middle of your line in python.
Try the following:
if board[1] == mark and board[2] == mark and board[3] == mark or board[4] == mark and board[5] == mark and board[6] == mark or board[7] == mark and board[8] == mark and board[9] == mark or board[1] == mark and board[4] == mark and board[7] == mark or board[2] == mark and board[5] == mark and board[8] == mark or board[3] == mark and board[6] == mark and board[9] == mark or board[1] == mark and board[5] == mark and board[9] == mark or board[3] == mark and board[5] == mark and board[7] == mark:
print(f'{mark} won!')
So, I was trying to make a basic Tic-Tac-Toe game with python, And I created one which works perfectly fine, but my code is not so good, as it has a lot of code for checking the list indexes(Winner Of The Game), which kinda bothers me. So, How I avoid using the left index for checking the winner of the game?
My Code:
board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
def show_board():# for showing the tic-tac-toe board
print(' | ' + str(board[0]) + ' | ' +
str(board[1]) + ' | ' + str(board[2]) + ' | ')
print(' | ' + str(board[3]) + ' | ' +
str(board[4]) + ' | ' + str(board[5]) + ' | ')
print(' | ' + str(board[6]) + ' | ' +
str(board[7]) + ' | ' + str(board[8]) + ' | ')
def main():
one = 1
flag = 1
show_board()
while one == 1:
if flag == 1:
x_o = 'X'
if flag == 2:
x_o = 'O'
pos = int(input('Player "' + x_o + '" Turn: '))
if x_o == 'o':
x_o = 'O'
if x_o == 'x':
x_o = 'X'
if board[pos - 1] == 'O' or board[pos - 1] == 'O':
print('That Place Is Already Filled By Player "0"')
if board[pos - 1] == 'X' or board[pos - 1] == 'X':
print('That Place Is Already Filled By Player "X"')
else:
try:
board[pos - 1] = x_o
except IndexError:
print('Type Numbers Between Only 1 And 9')
if flag == 1:
flag = 2
elif flag == 2:
flag = 1
show_board()
# Checking The Winner Of The Game
# for horizontal X
if board[0] == board[1] == board[2] == 'X':
one = 2
print('The Winner Is Player "X"!')
elif board[3] == board[4] == board[5] == 'X':
one = 2
print('The Winner Is Player "X"!')
elif board[6] == board[7] == board[8] == 'X':
one = 2
print('The Winner Is Player "X"!')
# for Daigonal X
elif board[0] == board[4] == board[8] == 'X':
one = 2
print('The Winner Is Player "X"!')
elif board[2] == board[4] == board[6] == 'X':
one = 2
print('The Winner Is Player "X"!')
# for Vertical X
elif board[1] == board[4] == board[7] == 'X':
one = 2
print('The Winner Is Player "X"!')
elif board[2] == board[5] == board[8] == 'X':
one = 2
print('The Winner Is Player "X"!')
elif board[0] == board[3] == board[6] == 'X':
one = 2
print('The Winner Is Player "X"!')
# for horizontal O
elif board[0] == board[1] == board[2] == 'O':
one = 2
print('The Winner Is Player "O"!')
elif board[3] == board[4] == board[5] == 'O':
one = 2
print('The Winner Is Player "O"!')
elif board[6] == board[7] == board[8] == 'O':
one = 2
print('The Winner Is Player "O"!')
# for Diagonal O
elif board[0] == board[4] == board[8] == 'O':
one = 2
print('The Winner Is Player "O"!')
elif board[2] == board[4] == board[6] == 'O':
one = 2
print('The Winner Is Player "O"!')
# for Vertical 0
elif board[1] == board[4] == board[7] == 'O':
one = 2
print('The Winner Is Player "O"!')
elif board[2] == board[5] == board[8] == 'O':
one = 2
print('The Winner Is Player "O"!')
elif board[0] == board[3] == board[6] == 'O':
one = 2
print('The Winner Is Player "O"!')
elif board[0] != ' ' and board[1] != ' ' and board[2] != ' ' and board[3] != ' ' and board[4] != ' ' and board[5] != ' ' and board[6] != ' ' and board[7] != ' ' and board[8] != ' ':
print('The Match Is A Tie!')
one = 2
main()
So, as you can see I'm using a lot of if statements for checking the winner of the game. How can I avoid that and do it in fewer lines.
You can replace them with some loops like:
board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
def show_board():# for showing the tic-tac-toe board
print(' | ' + str(board[0]) + ' | ' +
str(board[1]) + ' | ' + str(board[2]) + ' | ')
print(' | ' + str(board[3]) + ' | ' +
str(board[4]) + ' | ' + str(board[5]) + ' | ')
print(' | ' + str(board[6]) + ' | ' +
str(board[7]) + ' | ' + str(board[8]) + ' | ')
def main():
one = 1
flag = 1
show_board()
while one == 1:
if flag == 1:
x_o = 'X'
if flag == 2:
x_o = 'O'
pos = int(input('Player "' + x_o + '" Turn: '))
if x_o == 'o':
x_o = 'O'
if x_o == 'x':
x_o = 'X'
if board[pos - 1] == 'O' or board[pos - 1] == 'O':
print('That Place Is Already Filled By Player "0"')
if board[pos - 1] == 'X' or board[pos - 1] == 'X':
print('That Place Is Already Filled By Player "X"')
else:
try:
board[pos - 1] = x_o
except IndexError:
print('Type Numbers Between Only 1 And 9')
if flag == 1:
flag = 2
elif flag == 2:
flag = 1
show_board()
# Checking The Winner Of The Game
won = False
for turn in ('X', 'O'):
# horizontal
if not won:
for i in (0, 3, 6):
if all(board[i + k] == turn for k in range(3)):
won = True
break
# vertical
if not won:
for i in range(3):
if all(board[i + k] == turn for k in (0, 3, 6)):
won = True
break
# diagonal
if not won:
if all(board[k] == turn for k in (0, 4, 8)) or \
all(board[k] == turn for k in (2, 4, 6)):
won = True
# handle winning
if won:
one = 2
print(f'The Winner Is Player "{turn}"!')
break
# handle a tie
if not won and all(square != ' ' for square in board):
one = 2
print('The Match Is A Tie!')
main()
(You can probably also polish/simplify the rest of the code quite a bit)
EDIT
Here is some similar code simplified / polished / expanded to:
handle boards of arbitrary sizes
correctly handle non-numerical input
use more functions
get rid of redundant variables
NUM_ROWS = 3
NUM_COLS = 3
NUM_WIN = 3
BOARD_SIZE = NUM_ROWS * NUM_COLS
EMPTY = ' '
BOARD = [EMPTY] * BOARD_SIZE
TURNS = 'X', 'O'
def show_board(board):
"""Show the tic-tac-toe board."""
for i in range(0, BOARD_SIZE, NUM_COLS):
print(' | ' + ' | '.join(board[i:i + NUM_COLS]) + ' | ')
def ij(i, j):
"""Convert (row, col) to board index."""
return i + NUM_COLS * j
def check_winner(board, turn):
"""Check if there is a winner."""
# horizontal
for i in range(NUM_ROWS):
for j in range(NUM_COLS - NUM_WIN + 1):
if all(board[ij(i, j + k)] == turn for k in range(NUM_WIN)):
return True
# vertical
for i in range(NUM_ROWS - NUM_WIN + 1):
for j in range(NUM_COLS):
if all(board[ij(i + k, j)] == turn for k in range(NUM_WIN)):
return True
# diagonal
for i in range(NUM_ROWS - NUM_WIN + 1):
for j in range(NUM_COLS - NUM_WIN + 1):
K = NUM_WIN
if all(board[ij(i + k, j + k)] == turn for k in range(NUM_WIN)):
return True
if all(board[ij(i + NUM_WIN - k - 1, j + k)] == turn
for k in range(NUM_WIN)):
return True
def check_tie(board):
"""Check if tie."""
return all(square != EMPTY for square in board)
def next_turn(turn):
"""Advance to next turn."""
return TURNS[(TURNS.index(turn) + 1) % 2]
def main():
"""Tic-tac-toe game."""
turn = TURNS[0]
show_board(BOARD)
while True:
valid_input = False
while not valid_input:
try:
choice = int(input(f'Player `{turn}` turn: '))
valid_input = (1 <= choice <= BOARD_SIZE)
if not valid_input:
raise ValueError
except ValueError:
print(f'Type numbers between 1 and {BOARD_SIZE} only.')
else:
idx = choice - 1
if BOARD[idx] != EMPTY:
print(f'Position `{idx}` already taken by `{BOARD[idx]}`')
else:
BOARD[idx] = turn
show_board(BOARD)
won = check_winner(BOARD, turn)
if won:
print(f'The winner is player `{turn}`!')
break
# handle a tie
if not won and check_tie(BOARD):
print('The match is a tie!')
break
turn = next_turn(turn)
if __name__ == '__main__':
main()
Please check mnk-game's source code for a similar implementation using NumPy and classes (especially Board.py). DISCLAIMER: I am the author of the package.
EDIT 2
Note that for tic-tac-toe only, check_winner() could be shortend using an approach similar to what #rusu_ro1 proposed :
WIN_CASES = [
[0, 1, 2], [3, 4, 5], [6, 7, 8], # horizontal
[0, 3, 6], [1, 4, 7], [2, 5, 8], # vertical
[0, 4, 8], [2, 4, 6], # diagonal
]
def check_winner(board, turn, win_cases=WIN_CASES):
"""Check if there is a winner."""
for win_case in win_cases:
if all(board[i] == turn for i in win_case):
return True
import random as rnd
size = 3
## random board to test
board = [[rnd.choice(["X", "O"]) for _ in range(size)] for _ in range(size)]
print(board)
def check_winner(board):
for mark in ["X", "O"]:
## count mark in all rows
count_in_rows = [row.count(mark) for row in board]
## count mark in all columns
count_in_columns = [ [board[row_n][col_n] for row_n in range(size)].count(mark) for col_n in range(size)]
## count mark in fwd diagonal
count_in_diag = [[board[i][i] for i in range(size)].count(mark)]
## count in backward diagonal
count_in_diag.append([board[i][size-i-1] for i in range(size)].count(mark))
print((count_in_rows + count_in_columns + count_in_diag))
## if there is 3 count of mark in any rows, columns or diagonal
if 3 in (count_in_rows + count_in_columns + [count_in_diag]):
print(f"winner is {mark}")
return mark
return
check_winner(board)
you can definition o_list =['o', 'o', 'o'] and x_list = ['x', 'x', 'x']
and then just comparison them like:
#l = board
if(l[0:3] == o_list or l[3:6] == o_list or l[6:9] == o_list or l[0:9:3] == o_list or l[1:9:3] == o_list or l[8:0:-3] == o_list):
print('The Winner Is Player "O"!')
same as for x_list.
;)
o_list =['o', 'o', 'o']
x_list =['x', 'x', 'x']
board = [' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ']
def show_board():# for showing the tic-tac-toe board
print(' | ' + str(board[0]) + ' | ' +
str(board[1]) + ' | ' + str(board[2]) + ' | ')
print(' | ' + str(board[3]) + ' | ' +
str(board[4]) + ' | ' + str(board[5]) + ' | ')
print(' | ' + str(board[6]) + ' | ' +
str(board[7]) + ' | ' + str(board[8]) + ' | ')
def main():
one = 1
flag = 1
o_list =['o', 'o', 'o']
x_list =['x', 'x', 'x']
show_board()
while one == 1:
if flag == 1:
x_o = 'X'
if flag == 2:
x_o = 'O'
pos = int(input('Player "' + x_o + '" Turn: '))
if x_o == 'o':
x_o = 'O'
if x_o == 'x':
x_o = 'X'
if board[pos - 1] == 'O' or board[pos - 1] == 'O':
print('That Place Is Already Filled By Player "0"')
if board[pos - 1] == 'X' or board[pos - 1] == 'X':
print('That Place Is Already Filled By Player "X"')
else:
try:
board[pos - 1] = x_o
except IndexError:
print('Type Numbers Between Only 1 And 9')
if flag == 1:
flag = 2
elif flag == 2:
flag = 1
show_board()
# Checking The Winner Of The Game
# for horizontal X
if(board[0:3] == x_list or board[3:6] == x_list or board[6:9] == x_list or board[0:9:3] == x_list or board[1:9:3] == x_list or board[8:0:-3] == x_list):
one = 2
print('The Winner Is Player "X"!')
if(board[0:3] == o_list or board[3:6] == o_list or board[6:9] == o_list or board[0:9:3] == o_list or board[1:9:3] == o_list or board[8:0:-3] == o_list):
one = 2
print('The Winner Is Player "O"!')
elif board[0] != ' ' and board[1] != ' ' and board[2] != ' ' and board[3] != ' ' and board[4] != ' ' and board[5] != ' ' and board[6] != ' ' and board[7] != ' ' and board[8] != ' ':
print('The Match Is A Tie!')
one = 2
main()
You can use this functions(input:board and a player's letter, output: True if that player has won):
def isWinner(board, letter):
return (
(board[1] == board[2] == board[3] == letter) or
(board[4] == board[5] == board[6] == letter) or
(board[7] == board[8] == board[9] == letter) or
(board[7] == board[4] == board[1] == letter) or
(board[8] == board[5] == board[2] == letter) or
(board[9] == board[6] == board[3] == letter) or
(board[7] == board[5] == board[3] == letter) or
(board[9] == board[5] == board[1] == letter))
for checking the winner you can use:
from operator import itemgetter
from itertools import chain
winning_cases = {'diags' : [[0, 4, 8], [2, 4, 6]],
'rows': [[0, 1, 2], [3, 4, 5], [6, 7, 8]],
'cols': [[0, 3, 6], [1, 4, 7], [2, 5, 8]]}
def check_winner(board=board):
for case in chain(*winning_cases.values()):
candidates = set(itemgetter(*case)(board))
if len(candidates) == 1 and '' not in candidates: # check if a diag, row or col has only one charcter
winner, = candidates
return winner
return None
for example:
board = ['X', 'X', 'O', 'X', 'O','O', 'X', 'O', 'X']
check_winner(board)
output:
X
the method check_winner will return the winner if there is one, otherwise None
This is a Tic Tac Toe program, but it has a certain twist to it...you are able to cover up an opponent's x or o with a larger x or o. You have medium pieces and large pieces. For some reason, I can't get my board to display the current moves and it doesn't seem to recognize winning conditions. Any help would be greatly appreciated.
#Winner checker.
def player_done(playerSym, board):
return ((board[6] == playerSym and board[7] == playerSym and board[8] == playerSym) or # across the top
(board[3] == playerSym and board[4] == playerSym and board[5] == playerSym) or # across the middle
(board[0] == playerSym and board[1] == playerSym and board[2] == playerSym) or # across the bottom
(board[6] == playerSym and board[3] == playerSym and board[0] == playerSym) or # down the left side
(board[7] == playerSym and board[4] == playerSym and board[3] == playerSym) or # down the middle
(board[8] == playerSym and board[5] == playerSym and board[2] == playerSym) or # down the right side
(board[6] == playerSym and board[4] == playerSym and board[2] == playerSym) or # diagonal
(board[8] == playerSym and board[4] == playerSym and board[0] == playerSym)) # diagonal
def opponent_done(oppSym, board):
return ((board[6] == oppSym and board[7] == oppSym and board[8] == oppSym) or # across the top
(board[3] == oppSym and board[4] == oppSym and board[5] == oppSym) or # across the middle
(board[0] == oppSym and board[1] == oppSym and board[2] == oppSym) or # across the bottom
(board[6] == oppSym and board[3] == oppSym and board[0] == oppSym) or # down the left side
(board[7] == oppSym and board[4] == oppSym and board[1] == oppSym) or # down the middle
(board[8] == oppSym and board[5] == oppSym and board[2] == oppSym) or # down the right side
(board[6] == oppSym and board[4] == oppSym and board[2] == oppSym) or # diagonal
(board[8] == oppSym and board[4] == oppSym and board[0] == oppSym)) # diagonal
# Sets up the Board
def drawBoard(board):
print(' | |')
print(' ' + board[6] + ' | ' + board[7] + ' | ' + board[8])
print(' | |')
print('-----------')
print(' | |')
print(' ' + board[5] + ' | ' + board[4] + ' | ' + board[3])
print(' | |')
print('-----------')
print(' | |')
print(' ' + board[0] + ' | ' + board[1] + ' | ' + board[2])
print(' | |')
#Prints the current board
def print_board(board):
# Make a duplicate of the board list and return it the duplicate.
dupeBoard = []
for i in board:
dupeBoard.append(i)
return dupeBoard
#The Board
board = ["0", "1", "2", "3", "4", "5", "6", "7", "8"]
done = False
#The Move list for X's and O's
xmovesList = ["*","x","X"]
omovesList = [".","o","O"]
#Greeting message and choosing the initial X and O assignment.
print "Welcome to Tic-Tac-Toe-Cover-Up!"
playerSym = raw_input("Player 1, please select either X or O for your pieces: ")
print
#Player and opponent move assignment
if (playerSym == "X"):
playerSym = xmovesList
oppSym = omovesList
turn = "X"
else:
playerSym = omovesList
oppSym = xmovesList
turn = "O"
#Main game loop.
while not done:
drawBoard(board)
print turn,"'s turn"
if (turn == "X"):
player = xmovesList
opponent = omovesList
else:
player = omovesList
opponent = xmovesList
print "Select the place you want to play (0-8)"
print_board(board)
pos = input("Select: ")
if pos <=8 and pos >=0:
Y = pos/3
X = pos%3
if X != -1:
X -=1
else:
X = 2
Y -=1
if board == " ":
board = player[9]
moved = True
done = player()
elif board != " ":
if board == opponent[0]:
board = player[1]
moved = True
done = player_done()
done = opponent_done()
if board == opponent[1]:
board = player[2]
moved = True
done = player_done()
done = opponent_done()
if done == False:
if turn == "X":
turn = "O"
else:
turn = "X"
There were mltiple issues with it.
For emptiness You were comparing with " " where as you are initialing board with 1-9
Also major issue of error :
board = player[9]
This you needed
board[pos] = player[0]
Also you need to fix checking logic to :
board[6] in playerSym # and not board[6] == playerSym
This is program with some fixes.
#Winner checker.
def check_done(playerSym,board):
return ((board[6] in playerSym and board[7] in playerSym and board[8] in playerSym) or # across the top
(board[3] in playerSym and board[4] in playerSym and board[5] in playerSym) or # across the middle
(board[0] in playerSym and board[1] in playerSym and board[2] in playerSym) or # across the bottom
(board[6] in playerSym and board[3] in playerSym and board[0] in playerSym) or # down the left side
(board[7] in playerSym and board[4] in playerSym and board[3] in playerSym) or # down the middle
(board[8] in playerSym and board[5] in playerSym and board[2] in playerSym) or # down the right side
(board[6] in playerSym and board[4] in playerSym and board[2] in playerSym) or # diagonal
(board[8] in playerSym and board[4] in playerSym and board[0] in playerSym)) # diagonal
# Sets up the Board
def drawBoard(board):
print(' | |')
print(' ' + board[6] + ' | ' + board[7] + ' | ' + board[8])
print(' | |')
print('-----------')
print(' | |')
print(' ' + board[5] + ' | ' + board[4] + ' | ' + board[3])
print(' | |')
print('-----------')
print(' | |')
print(' ' + board[0] + ' | ' + board[1] + ' | ' + board[2])
print(' | |')
#Verifies if board is not full with all largest signs and no mpre moves are possible.
def movesPossible(board):
#TODO: implement this
return True
#Prints the current board
def print_board(board):
# Make a duplicate of the board list and return it the duplicate.
dupeBoard = []
for i in board:
dupeBoard.append(i)
return dupeBoard
#The Board
board = ["0", "1", "2", "3", "4", "5", "6", "7", "8"]
done = False
#The Move list for X's and O's
xmovesList = ["*","x","X"]
omovesList = [".","o","O"]
#Greeting message and choosing the initial X and O assignment.
print "Welcome to Tic-Tac-Toe-Cover-Up!"
playerSym = raw_input("Player 1, please select either X or O for your pieces: ")
print
#Player and opponent move assignment
if (playerSym == "X"):
player = xmovesList
opponent = omovesList
else:
player = omovesList
opponent = xmovesList
drawBoard(board)
#Main game loop.
while movesPossible(board):
print player[2],"'s turn"
print "Select the place you want to play (0-8)"
print_board(board)
moved = False
pos = input("Select: ")
if pos <=8 and pos >=0:
Y = pos/3
X = pos%3
if X != -1:
X -=1
else:
X = 2
Y -=1
if board[pos] == str(pos):
board[pos] = player[0]
moved = True
done = check_done(player,board)
else :
if board[pos] == opponent[0]:
board[pos] = player[1]
moved = True
done = check_done(player,board)
if board[pos] == opponent[1]:
board[pos] = player[2]
moved = True
done = check_done(player,board)
drawBoard(board)
if done:
break;
if moved :
player,opponent = opponent,player
if(done):
print player[2], "wins "
else:
print "No more moves possible. It's a draw."