I have made a tic/tac/toe game but I want to create a computer player that controls "O" while the user controls "X".
For the clicked
function in my code, I am trying to return a boolean but I am not sure if I am doing it right. The function returns True
if the user's click operations were successful. If the user clicks on a position that is already outside of the board area, the move is invalid and the function should then return False
. My code:
import turtle
import time
import random
pieces = ["_", "_", "_", "_", "_", "_", "_", "_", "_"]
turn = "X"
def drawgame(brd):
# draw board
turtle.setup(600, 600)
turtle.bgcolor("silver")
turtle.color("white")
turtle.hideturtle()
turtle.speed('fastest')
turtle.width(10)
turtle.up()
# Horizontal bars
turtle.goto(-300, 100)
turtle.down()
turtle.forward(600)
turtle.up()
turtle.goto(-300, -100)
turtle.down()
turtle.forward(600)
turtle.up()
# Vertical bars
turtle.goto(-100, 300)
turtle.setheading(-90)
turtle.down()
turtle.forward(600)
turtle.up()
turtle.goto(100, 300)
turtle.down()
turtle.forward(600)
turtle.up()
turtle.color("blue")
x, y = -300, 300
for pos in pieces:
if pos == "X":
# Draw X
turtle.up()
turtle.goto(x + 20, y - 20)
turtle.setheading(-45)
turtle.down()
turtle.forward(226)
turtle.up()
turtle.goto(x + 180, y - 20)
turtle.setheading(-135)
turtle.down()
turtle.forward(226)
turtle.up()
elif pos == "O":
#Draw O
turtle.up()
turtle.goto(x + 100, y - 180)
turtle.setheading(0)
turtle.down()
turtle.circle(80)
turtle.up()
x += 200
if x > 100:
x = -300
y -= 200
def clicked(board, x, y):
#sig: list(str), int, int -> NoneType
global turn, pieces
turtle.onscreenclick(None) # disabling handler when inside handler
column = (x + 300) // 200
row = (y - 300) // -200
square = int(row * 3 + column)
print("User clicked ", x, ",", y, " at square ", square)
if pieces[square] == "_":
pieces[square] = turn
if turn == "X":
turn = "O"
else:
turn = "X"
drawgame(pieces)
else:
print("That square is already taken")
turtle.onscreenclick(clicked)
def computer_AI(board):
#sig: list(str) -> NoneType
def gameover(board):
#sig: list(str) -> bool
#checks gameover on board if there is a three in a row pattern or not
def handler(x, y):
#sig: int, int -> NoneType
if clicked(the_board, x, y):
drawgame(the_board)
if not gameover(pieces):
computer_AI(pieces)
drawgame(pieces)
gameover(pieces)
def main():
#Runs the game
turtle.tracer(0,0)
turtle.hideturtle()
turtle.onscreenclick(handler)
drawgame(pieces)
turtle.mainloop()
main()
I am trying to achieve this output:
Any help is appreciated.
For my
clicked
function in my code, I am trying to return a bool but I am not sure if I am doing it right.
The clicked()
function is an event hander, it doesn't return anything to anyone. We have to design based on that. I've reworked your code below, combining the hander()
and clicked()
functions, such that it now "plays". That is, the user goes first, and is "X", and then the computer responds as player "O":
import turtle
import random
board = ["_", "_", "_", "_", "_", "_", "_", "_", "_"]
def drawgame(board):
# draw board
turtle.setup(600, 600)
turtle.bgcolor("silver")
turtle.color("white")
turtle.hideturtle()
turtle.speed('fastest')
turtle.width(10)
turtle.up()
# Horizontal bars
turtle.goto(-300, 100)
turtle.down()
turtle.forward(600)
turtle.up()
turtle.goto(-300, -100)
turtle.down()
turtle.forward(600)
turtle.up()
# Vertical bars
turtle.setheading(-90)
turtle.goto(-100, 300)
turtle.down()
turtle.forward(600)
turtle.up()
turtle.goto(100, 300)
turtle.down()
turtle.forward(600)
turtle.up()
turtle.color("blue")
x, y = -300, 300
for pos in board:
if pos == "X":
# Draw X
turtle.up()
turtle.goto(x + 20, y - 20)
turtle.setheading(-45)
turtle.down()
turtle.forward(226)
turtle.up()
turtle.goto(x + 180, y - 20)
turtle.setheading(-135)
turtle.down()
turtle.forward(226)
turtle.up()
elif pos == "O":
# Draw O
turtle.up()
turtle.goto(x + 100, y - 180)
turtle.setheading(0)
turtle.down()
turtle.circle(80)
turtle.up()
x += 200
if x > 100:
x = -300
y -= 200
def handler(x, y):
# sig: list(str), int, int -> NoneType
turtle.onscreenclick(None) # disabling handler when inside handler
column = (x + 300) // 200
row = (y - 300) // -200
square = int(row * 3 + column)
if board[square] == "_":
board[square] = "X"
drawgame(board)
if not gameover(board):
computer_AI(board)
drawgame(board)
if not gameover(board):
turtle.onscreenclick(handler) # allow player to take a turn
else:
print("That square is already taken!")
turtle.onscreenclick(handler) # allow player to retake turn
def computer_AI(board): # sig: list(str) -> NoneType
""" stupid robot player, just picks randomly from what's available """
available = [index for index, character in enumerate(board) if character == "_"]
if available:
index = random.choice(available)
board[index] = "O"
def gameover(board):
# sig: list(str) -> bool
# checks game over on board if there is a three in a row pattern or not
pass # to be implemented!
return False
def main():
# Runs the game
turtle.hideturtle()
turtle.onscreenclick(handler)
drawgame(board)
turtle.mainloop()
main()
To do: the logic to determine if the game is over, and who won, still doesn't exist, so you need to write that. Currently it just returns False
to indicate the game isn't over. The computer_AI()
code has no smarts at all, it simply notes all the open squares and picks one at random. You need to improve on this.