Adding user checks to Python turtle tic-tac-toe game - python

import turtle
#1)draw board
sc= turtle.Screen()
sc.setup(300,300)
import turtle
sc= turtle.Screen()
sc.setup(300,300)
turtle.speed(0)
turtle.pensize(10)
turtle.bgcolor("black")
turtle.pencolor("white")
turtle.penup()
turtle.goto(-150,50)
turtle.pendown()
turtle.forward(300)
turtle.penup()
turtle.goto(-150,-50)
turtle.pendown()
turtle.forward(300)
turtle.penup()
turtle.goto(-50,150)
turtle.setheading(-90)
turtle.pendown()
turtle.forward(300)
turtle.penup()
turtle.goto(50,150)
turtle.pendown()
turtle.forward(300)
turtle.penup()
#2) X's and O's
turtle.pencolor("yellow")
def kreuz(x,y):
turtle.penup()
turtle.goto(x+30,y-45)
turtle.setheading(-45)
turtle.pendown()
turtle.forward(50)
turtle.penup()
turtle.goto(x+60,y-40)
turtle.setheading(-130)
turtle.pendown()
turtle.forward(50)
turtle.penup()
def kreis(x,y):
turtle.penup()
turtle.goto(x+50,y-80)
turtle.setheading(0)
turtle.pendown()
turtle.circle(20)
turtle.penup()
AlleTeile=["","","","","","","","",""]
nächsterZug="X"
def zeichneTeile (AlleTeile):
x = -150
y = 150
for einTeil in AlleTeile:
if einTeil=="X":
kreuz(x,y)
elif einTeil=="O":
kreis(x,y)
else:
print("leeres feld")
x=x+100
if x > 50:
x=-150
y=y-100
zeichneTeile(AlleTeile)
def geklickt(x,y):
global nächsterZug,AlleTeile
senkrecht= (x+150) // 100
waagrecht= (-y+150)// 100
Bereich= senkrecht+waagrecht*3
Bereich=int(Bereich)
print("Du klicktest auf Bereich-Nummer", Bereich)
AlleTeile[Bereich]=nächsterZug
if nächsterZug =="X":
nächsterZug="O"
else:
nächsterZug="X"
zeichneTeile(AlleTeile)
turtle.onscreenclick(geklickt)
turtle.mainloop()
I want to create this tic-tac-toe game using turtle in Python but I am stuck. The problem is that I keep drawing noughts and crosses on the game board after all 9 fields are full with noughts and crosses. How can I code this so that after 9 turns (9 fields) it is no longer possible to keep on drawing?

Since unused squares consist of an empty string in AlleTeile, this is trivial to fix since empty strings are False in a boolean context. At the top of geklickt(), after the global statement:
if all(AlleTeile):
print("All taken!")
return
We can reuse the same trick later in that function to prevent overwritting of existing squares. After the Bereich calculation, we can do something like:
print("Du klicktest auf Bereich-Nummer", Bereich, end="")
if AlleTeile[Bereich]:
print(" -- already taken!")
return
else:
print()
Here's my complete rework with the above changes, some turtle idoms, code cleanup and English translation courtesy of Google (and common sense):
from turtle import Screen, Turtle
# X's and O's
def cross(x, y):
turtle.penup()
turtle.goto(x + 30, y - 35)
turtle.setheading(-45)
turtle.pendown()
turtle.forward(50)
turtle.penup()
turtle.goto(x + 60, y - 30)
turtle.setheading(-130)
turtle.pendown()
turtle.forward(50)
turtle.penup()
def nought(x, y):
turtle.penup()
turtle.goto(x + 50, y - 70)
turtle.setheading(0)
turtle.pendown()
turtle.circle(20)
turtle.penup()
# Playing the game
def drawSquares():
screen.tracer(False) # because this routine is a graphics bottleneck
x, y = -150, 150
for square in AllSquares:
if square == "X":
cross(x, y)
elif square == "O":
nought(x, y)
x += 100
if x > 50:
x = -150
y -= 100
screen.tracer(True)
def clicked(x, y):
global turn
if all(AllSquares):
print("All taken!")
return
vertical = (x + 150) // 100
horizontal = (150 - y) // 100
Area = int(vertical + horizontal * 3)
print("You clicked area number", Area, end="")
if AllSquares[Area]:
print(" -- already taken!")
return
else:
print()
AllSquares[Area] = turn
if turn == "X":
turn = "O"
else:
turn = "X"
drawSquares()
# Draw the board
screen = Screen()
screen.setup(330, 330)
screen.bgcolor("black")
turtle = Turtle(visible=False)
turtle.pensize(10)
turtle.color("white")
turtle.speed('fastest')
turtle.penup()
turtle.goto(-150, 50)
turtle.pendown()
turtle.forward(300)
turtle.penup()
turtle.goto(-150, -50)
turtle.pendown()
turtle.forward(300)
turtle.setheading(-90)
turtle.penup()
turtle.goto(-50, 150)
turtle.pendown()
turtle.forward(300)
turtle.penup()
turtle.goto(50, 150)
turtle.pendown()
turtle.forward(300)
turtle.penup()
# Start the game
turtle.color("yellow")
AllSquares = ["", "", "", "", "", "", "", "", ""]
turn = "X"
drawSquares()
screen.onscreenclick(clicked)
screen.mainloop()

Related

Creating function to check if win conditions are satisfied for turtle tictactoe game

I've created a game of Tic-Tac-Toe that can be played using the turtle module. It draws the board, then using class methods draws the circles or X's in the spot designated by a simple numbering system and coordinates.
I'm trying to finish this project up by testing for if a win condition has been satisfied by a player, and if yes, it draws a line through them and finishes the game.
Trouble is, I don't know where to start. I had the idea of adding the values of the position to a list for each player (for example, if the circle player puts a circle in position 1, a 1 gets added to the circles list) then creating if statements to check for certain conditions. However, I quickly got lost and now I'm not sure what to do. Here's what my code looks like
#Class that allows for drawing the circles and X's
class CircleOrSquare():
def __init__(self):
pass
def circle(self, x, y): #Draws from the bottom middle of the circle
import turtle
turtle.color('red')
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
turtle.circle(10)
def cross(self, x, y): #Draws from the bottom middle of the cross
import turtle
turtle.color('blue')
#position x,y at center base of cross
turtle.penup()
turtle.goto(x, y)
x = x-10 #Change x to the bottom left leg
#Draw the X
turtle.goto(x, y)
turtle.pendown()
turtle.goto(x+20, y+20)
turtle.penup()
turtle.goto(x, y+20)
turtle.pendown()
turtle.goto(x+20, y)
def main():
import turtle
canvas = turtle.Screen()
canvas.setup(200, 200)
canvas.bgcolor('light grey')
turtle.hideturtle()
#Vertical lines
turtle.penup()
turtle.goto(-25, 50)
turtle.pendown()
turtle.goto(-25, -50)
turtle.penup()
turtle.goto(25, 50)
turtle.pendown()
turtle.goto(25, -50)
turtle.penup()
#Horizontal lines
turtle.goto(-50, 20)
turtle.pendown()
turtle.goto(50, 20)
turtle.penup()
turtle.goto(-50, -20)
turtle.pendown()
turtle.goto(50, -20)
turtle.penup()
#Tic-Tac-Toe
turtle.goto(-28, 75)
turtle.write("Tic-Tac-Toe")
positions = {1: [-40, 30], 2: [0, 30], 3: [40, 30], 4: [-40, -10], 5: [0, -10],
6: [40, -10], 7: [-40, -45], 8: [0, -45], 9: [40, -45]}
screen = turtle.Screen()
for i in range(9):
move = screen.textinput("Next Move", "Starting from the top left"
", enter 1-9 for your move: ")
if i % 2 == 0:
answer = CircleOrSquare()
answer.circle(positions[int(move)][0], positions[int(move)][-1])
else:
answer = CircleOrSquare()
answer.cross(positions[int(move)][0], positions[int(move)][-1])
turtle.exitonclick()
main()

Getting "NoneType object has no attribute" error trying to use turtle module

I am learning Python turtle. I copied this code from internet but I am getting this error NoneType object has no attribute.
I think error is in 2nd last line in turtle.write() function.
This is code:
import turtle
import random
# sets background
bg = turtle.Screen()
bg.bgcolor("black")
# Bottom Line 1
turtle.penup()
turtle.goto(-170,-180)
turtle.color("white")
turtle.pendown()
turtle.forward(350)
# Mid Line 2
turtle.penup()
turtle.goto(-160,-150)
turtle.color("white")
turtle.pendown()
turtle.forward(300)
# First Line 3
turtle.penup()
turtle.goto(-150,-120)
turtle.color("white")
turtle.pendown()
turtle.forward(250)
# Cake
turtle.penup()
turtle.goto(-100,-100)
turtle.color("white")
turtle.begin_fill()
turtle.pendown()
turtle.forward(140)
turtle.left(90)
turtle.forward(95)
turtle.left(90)
turtle.forward(140)
turtle.left(90)
turtle.forward(95)
turtle.end_fill()
# Candles
turtle.penup()
turtle.goto(-90,0)
turtle.color("red")
turtle.left(180)
turtle.pendown()
turtle.forward(20)
turtle.penup()
turtle.goto(-60,0)
turtle.color("blue")
turtle.pendown()
turtle.forward(20)
turtle.penup()
turtle.goto(-30,0)
turtle.color("yellow")
turtle.pendown()
turtle.forward(20)
turtle.penup()
turtle.goto(0,0)
turtle.color("green")
turtle.pendown()
turtle.forward(20)
turtle.penup()
turtle.goto(30,0)
turtle.color("purple")
turtle.pendown()
turtle.forward(20)
# Decoration
colors = ["red", "orange", "yellow", "green", "blue", "purple", "black"]
turtle.penup()
turtle.goto(-40,-50)
turtle.pendown()
for each_color in colors:
angle = 360 / len(colors)
turtle.color(each_color)
turtle.circle(10)
turtle.right(angle)
turtle.forward(10)
# Happy Birthday message
turtle.penup()
turtle.goto(-150, 50)
turtle.color("pink")
turtle.pendown()
turtle.write("Happy Birthday PUNNU!", None, None, "24pt bold")
turtle.color("black")
Here is the documentation for turtle.write().
You are supplying NoneType objects incorrectly. To set the font and leave the move and align parameters as their default values, change your second to last line to turtle.write("Happy Birthday PUNNU!", font=("Arial", 24, "bold"))

Python3-Turtle: Pen color not changing

I have a function that draws a brick wall, with the option to set a certain pen color before the wall is drawn, however it seems that the brick is drawn as green no matter what I do:
def draw_brick(length, width):
t.color("green")
t.begin_fill()
for i in range(2):
t.forward(length)
t.right(90)
t.forward(width)
t.right(90)
t.end_fill()
def draw_row(row_type, bricks):
if row_type == "A":
for i in range(bricks):
draw_brick(50, 30)
t.penup()
t.forward(70)
t.pendown()
elif row_type == "B":
draw_brick(12, 30)
t.penup()
t.forward(35)
t.pendown()
for i in range(bricks - 1):
draw_brick(50, 30)
t.penup()
t.forward(70)
t.pendown()
t.penup()
t.pendown()
draw_brick(12, 30)
def draw_brick_wall(rows, brick, top_row, new_color):
t.pencolor(new_color)
if top_row == "A":
drawing_A = True
else:
drawing_A = False
for i in range(rows):
next_position = (t.xcor(), t.ycor() - 40)
if drawing_A:
draw_row("A", brick)
else:
draw_row("B", brick)
drawing_A = not (drawing_A)
move_no_trails(next_position[0], next_position[1])
# resets turtle to postion (x, y)
def move_no_trails(x, y):
t.penup()
t.goto(x, y)
t.pendown()
For some reason, though, the pen color of the turtle doesn't change. What could I do to remedy this?
Once I add a compatible draw_brick() function, your code works fine for me:
from turtle import Screen, Turtle
def draw_brick(width, height):
for _ in range(2):
turtle.forward(width)
turtle.left(90)
turtle.forward(height)
turtle.left(90)
def draw_row(row_type, bricks):
if row_type == "A":
for _ in range(bricks):
draw_brick(50, 30)
turtle.penup()
turtle.forward(70)
turtle.pendown()
elif row_type == "B":
draw_brick(12, 30)
turtle.penup()
turtle.forward(35)
turtle.pendown()
for _ in range(bricks-1):
draw_brick(50, 30)
turtle.penup()
turtle.forward(70)
turtle.pendown()
draw_brick(12, 30)
# resets turtle to postion (x, y)
def move_no_trails(x, y):
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
def draw_brick_wall(rows, brick, top_row, new_color):
turtle.pencolor(new_color)
drawing_A = top_row == "A"
for _ in range(rows):
next_x, next_y = turtle.xcor(), turtle.ycor() - 40
if drawing_A:
draw_row("A", brick)
else:
draw_row("B", brick)
drawing_A = not drawing_A
move_no_trails(next_x, next_y)
screen = Screen()
turtle = Turtle()
turtle.speed('fastest') # because I have no patience
draw_brick_wall(1, 5, "A", "red")
draw_brick_wall(1, 5, "B", "blue")
draw_brick_wall(1, 5, "A", "orange")
draw_brick_wall(1, 5, "B", "green")
screen.exitonclick()
If, however, your draw_brick() function is drawing a filled brick, then you'll need to change the call to pencolor(new_color) in draw_brick_wall() to either fillcolor(new_color) to set the fill color or color(new_color) to set both the pen and fill colors.

How do I make this a 6 sized snowflake instead of 8?

Not originally my code:
import turtle
wn = turtle.Screen()
wn.bgcolor('Black')
wn.setup( width = 250, height = 250)
turtle = turtle.Turtle()
def snowflake (size, pensize, x, y):
""" function that draws a snowflake """
turtle.speed(100)
turtle.penup()
turtle.goto(x, y)
turtle.forward(10*size)
turtle.left(45)
turtle.pendown()
turtle.color('white')
for x in range (8):
branch(size)
turtle.left(45)
def branch (size):
for z in range (3):
for z in range (3):
turtle.forward(10.0*size/3)
turtle.backward(10.0*size/3)
turtle.right(45)
turtle.left(90)
turtle.backward(10.0*size/3)
turtle.left(45)
turtle.right(90)
turtle.forward(10.0*size)
snowflake(8, 6, 0, 0)
wn.exitonclick()
If it's not originally your code, your should provide proper blame, I mean credit for it. The issue with this code is that the base angle 45 is being used to generate the 8-sided snowflake as well as the angle of the small branches. So when we go to use 60 for a 6-sided snowflake, it's hard to know which 45's (or 90's) to replace and which to keep. The author of the original code didn't help any by starting the branch logic in the snowflake() function, before calling the branch() function. So let's tease out the two different uses of 45 degrees, make the code more explicit, and switch just the sides to 60 degrees:
from turtle import Screen, Turtle
SIDES = 6
BRANCH_ANGLE = 45
def snowflake(size, x, y):
""" function that draws a snowflake """
turtle.penup()
turtle.goto(x, y)
turtle.forward(size)
turtle.left(BRANCH_ANGLE)
turtle.pendown()
for _ in range(SIDES):
branch(size)
turtle.left(BRANCH_ANGLE)
def branch(size):
for _ in range(3):
for _ in range(3):
turtle.forward(size / 3)
turtle.backward(size / 3)
turtle.right(BRANCH_ANGLE)
turtle.left(2 * BRANCH_ANGLE)
turtle.backward(size / 3)
turtle.left(BRANCH_ANGLE)
turtle.right(BRANCH_ANGLE + 360 / SIDES)
turtle.forward(size)
screen = Screen()
screen.bgcolor('black')
screen.setup(width=250, height=250)
turtle = Turtle()
turtle.color('white')
turtle.speed('fastest')
snowflake(80, 0, 0)
turtle.hideturtle()
screen.exitonclick()

Placement of turtle drawn letters in Python

I'm new to this but wanted to try Python with turtle. But I have a problem with my code when I tell the cursor to move to underneath the letter H. It just throws cursor at the start where the H is. I wanna write:
HAPPY
BDAY
in that order. Here is the code i have so far.
import turtle
frame = turtle.Screen().bgcolor("Red")
hi = turtle.Turtle()
hi.color("Black")
hi.width (3)
hi.speed (3)
# H
hi.left(90)
hi.forward(70)
hi.penup()
hi.goto(0, 35)
hi.pendown()
hi.right(90)
hi.forward(30)
hi.penup()
hi.goto(30, 70)
hi.pendown()
hi.right(90)
hi.forward(70)
# A
hi.penup()
hi.goto(40, 0)
hi.pendown()
hi.right(200)
hi.forward(75)
hi.right(140)
hi.forward(75)
hi.penup()
hi.goto(50, 35)
hi.pendown()
hi.right(-70)
hi.forward(31)
# P
hi.penup()
hi.goto(105, 70)
hi.pendown()
hi.right(90)
hi.forward(70)
hi.penup()
hi.goto(105,35)
hi.pendown()
hi.right(275)
hi.circle(18, 200)
# PP
hi.penup()
hi.goto(140, 70)
hi.pendown()
hi.right(285)
hi.forward(70)
hi.penup()
hi.goto(140,35)
hi.pendown()
hi.right(275)
hi.circle(18, 200)
# Y
hi.penup()
hi.goto(170, 70)
hi.pendown()
hi.right(255)
hi.forward(40)
hi.right(30)
hi.forward(35)
hi.penup()
hi.goto(190, 35)
hi.pendown()
hi.right(215)
hi.forward(40)
#B
hi.penup()
hi.goto(200, 70)
hi.pendown()
hi.forward(70)
turtle.mainloop()
https://imgur.com/QFx5nub the white dots are where I want the word Bday to start but the turtle is in the position where the arrow is.
You can only eyeball and guess so far. For text like this, it helps to have a fixed size box that each letter is going to fit into, and a constant location where the cursor is going to be in that box when letter drawing begins. It also helps to use relative positioning, like forward() rather than absolute positioning like goto(), when trying to debug your letters:
from turtle import Screen, Turtle
screen = Screen()
screen.bgcolor('red')
turtle = Turtle()
turtle.width(3)
# letters are in a box 30 wide by 70 tall with 10px between
# the pen starts at the lower left of each letter box
# H
turtle.left(90)
turtle.forward(70)
turtle.backward(35)
turtle.right(90)
turtle.forward(30)
turtle.left(90)
turtle.forward(35)
turtle.backward(70)
turtle.penup()
turtle.right(90)
turtle.forward(10)
turtle.pendown()
# A
turtle.left(78) # 77.9 degrees is rise 70 over run 15
turtle.forward(74)
turtle.right(156)
turtle.forward(37)
turtle.right(102)
turtle.forward(16)
turtle.backward(16)
turtle.left(102)
turtle.forward(37)
turtle.penup()
turtle.left(78)
turtle.forward(10)
turtle.pendown()
# P
turtle.left(90)
turtle.forward(70)
turtle.backward(35)
turtle.right(90)
turtle.forward(17.5)
turtle.circle(17.5, 180)
turtle.forward(17.5)
turtle.penup()
turtle.left(90)
turtle.forward(70)
turtle.left(90)
turtle.forward(40)
turtle.pendown()
# PP
turtle.left(90)
turtle.forward(70)
turtle.backward(35)
turtle.right(90)
turtle.forward(17.5)
turtle.circle(17.5, 180)
turtle.forward(17.5)
turtle.penup()
turtle.left(90)
turtle.forward(70)
turtle.left(90)
turtle.forward(40)
turtle.pendown()
# Y
turtle.penup()
turtle.forward(15)
turtle.pendown()
turtle.left(90)
turtle.forward(35)
turtle.left(23) # 90 - 67 as 66.8 degrees is rise 35 over run 15
turtle.forward(38)
turtle.backward(38)
turtle.right(46)
turtle.forward(38)
turtle.backward(38)
turtle.left(23)
turtle.backward(35)
turtle.penup()
turtle.right(90)
turtle.goto(0, -75) # 5px between lines of text
turtle.pendown()
# B
turtle.forward(17.5)
turtle.circle(17.5, 180)
turtle.forward(17.5)
turtle.right(180)
turtle.forward(17.5)
turtle.circle(17.5, 180)
turtle.forward(17.5)
turtle.left(90)
turtle.forward(70)
turtle.penup()
turtle.left(90)
turtle.forward(40)
turtle.pendown()
screen.mainloop()
Now you're in position to draw "D" in a 70x30 box with the cursor in the lower left corner pointing right.

Categories

Resources