I'm trying to draw grass and I'm struggling to make my drawing start from the bottom left then go all the way to the bottom right. I know there is something wrong with my code but can't figure it out.
The code I have starts from the middle and that's not what I want.
import turtle
import random
window = turtle.Screen()
bob = turtle.Turtle()
window.bgcolor("white")
window.title("TURTLE")
bob.pencolor("green")
window.colormode(255)
position = 0
height = 0
height11 = 0
height12 = 0
height13 = 0
height14 = 0
def draw_grass(bob):
green = random.randint (100, 200)
length = random.randint(10,20)
bob.fillcolor(0,green,0)
bob.begin_fill()
bob.setheading(90)
for i in range (2):
bob.forward(length)
bob.right(90)
bob.forward(3)
bob.right(90)
bob.end_fill()
bob.penup()
bob.pendown()
return length
for i in range (10):
height = draw_grass(bob)
position = position + 3
bob.goto(position, 0)
if height == 11 :
height11 = height11 + 1
elif height == 12:
height12 = height12 + 1
elif height == 13:
height13 = height13 + 1
You need to understand that the origin (0, 0) is in the center of the window and you have to work with positive and negative numbers. The screen methods window_width() and window_height() are useful for figuring out the size of a window that you didn't configure yourself. Here's a rework of your code that incorporates these ideas:
from turtle import Screen, Turtle
from random import randint
def draw_grass(turtle):
green = randint(100, 200)
length = randint(10, 20)
turtle.fillcolor(0, green, 0)
turtle.begin_fill()
for _ in range(2):
turtle.forward(3)
turtle.left(90)
turtle.forward(length)
turtle.left(90)
turtle.end_fill()
turtle.penup()
turtle.pendown()
return length
screen = Screen()
screen.bgcolor('white')
screen.title("TURTLE")
screen.colormode(255)
turtle = Turtle()
turtle.pencolor('green')
turtle.speed('fastest') # because I have no patience
turtle.penup()
turtle.setposition(6 - screen.window_width()//2, 12 - screen.window_height()//2)
turtle.pendown()
height11 = 0
height12 = 0
height13 = 0
height14 = 0
while turtle.xcor() < screen.window_width()//2 - 6:
height = draw_grass(turtle)
if height == 11:
height11 += 1
elif height == 12:
height12 += 1
elif height == 13:
height13 += 1
elif height == 14:
height14 += 1
turtle.forward(3)
screen.exitonclick()
Related
I made a simple text-based tic-tac-toe game and now I am trying to step it up creating a GUI using the Turtle module. The problem is that when I run my program, the Turtle window draws the board correctly, but then freezes and stops responding. I tried searching this problem everywhere and some people said that it could have to do with the line screen.mainloop(), but I can't figure out what is wrong.
Here is my code:
import warnings
import numpy as np
from turtle import Turtle, Screen
warnings.simplefilter(action='ignore', category=FutureWarning)
def create_board():
# turtle.hideturtle()
turtle.speed(0)
turtle.pensize(5)
turtle.left(90)
turtle.penup()
turtle.setpos(-150, -450)
turtle.pendown()
turtle.forward(900)
turtle.penup()
turtle.setpos(150, -450)
turtle.pendown()
turtle.forward(900)
turtle.right(90)
turtle.penup()
turtle.setpos(-450, -150)
turtle.pendown()
turtle.forward(900)
turtle.penup()
turtle.setpos(-450, 150)
turtle.pendown()
turtle.forward(900)
def enter_data(matrix, user, number):
if user == 1:
matrix = np.where(matrix == number, 'X', matrix)
if is_winner(matrix):
user = 1
else:
user = 2
elif user == 2:
matrix = np.where(matrix == number, 'O', matrix)
if is_winner(matrix):
user = 2
else:
user = 1
return matrix, user
def show_board(matrix):
print('-----|-----|-----')
for i in range(3):
print(f' {matrix[i][0]} | {matrix[i][1]} | {matrix[i][2]} ')
print('-----|-----|-----')
return
def is_winner(matrix):
for i in range(3):
if matrix[0][i] == matrix[1][i] == matrix[2][i]:
return True
elif matrix[:, 0][i] == matrix[:, 1][i] == matrix[:, 2][i]:
return True
if matrix[0][0] == matrix[1][1] == matrix[2][2]:
return True
elif matrix[0][2] == matrix[1][1] == matrix[2][0]:
return True
else:
return False
def draw_circle(x, y):
turtle.penup()
turtle.goto(x, y + 60)
turtle.pendown()
turtle.circle(-60)
def draw_cross(x, y):
turtle.penup()
turtle.goto(x - 60, y - 60)
turtle.pendown()
turtle.goto(x + 60, y + 60)
turtle.penup()
turtle.goto(x - 60, y + 60)
turtle.pendown()
turtle.goto(x + 60, y - 60)
screen = Screen()
screen.setup(width=0.65, height=0.95, starty=0)
turtle = Turtle()
create_board()
array = np.array(np.mat('1 2 3; 4 5 6; 7 8 9'), dtype=object)
count = 0
player = 1
show_board(array)
while count < 9 and is_winner(array) is not True:
choice = int(input(f'\nPlayer {player}, enter the number you want:\n'))
if choice not in range(1, 10) or choice not in array:
print('\nThat is invalid. Try again.\n')
show_board(array)
else:
count += 1
array, player = enter_data(array, player, choice)
screen.update()
show_board(array)
if count == 9:
print("\nThat's a draw.")
else:
print(f'\nPlayer {player} won! Congratulations!!')
print('Game Over!')
screen.mainloop()
Any help would be very much appreciated.
I was watching a video by Aperture on youtube: https://youtu.be/1w40fxsyraE?t=325
At the provided timestamp (5:25), he begins talking about a way to create a fractal. I tried to replicate this in a python program, but I am getting a different output. I have no idea why I am getting this output, but the math seems right, so I don't know what to change. Can anyone explain why my output looks different than the one in the video?
import turtle as t
drawer = t.Turtle()
drawer.speed(1000)
# drawer.hideturtle()
drawer.penup()
#make dot A
dotAx = 125
dotAy = 150
drawer.goto(dotAx, dotAy)
drawer.dot(10, "red")
#
#make dot B
dotBx = 185
dotBy = 0
drawer.goto(dotBx, dotBy)
drawer.dot(10, "red")
#
#make dot C
dotCx = 0
dotCy = 0
drawer.goto(dotCx, dotCy)
drawer.dot(10, "red")
#
#make middle dot
dotPx = 100
dotPy = 75
drawer.goto(dotPx, dotPy)
drawer.dot(5,"yellow")
#
#draw dots v
x = 0
drawer.pendown()
while True:
if x == 0:
dotPx = (dotPx + dotAx)/2
dotPy = (dotPy + dotAy)/2
drawer.goto(dotPx, dotPy)
drawer.dot(5,"black")
print("A", dotPx, dotPy)
x+=1
if x == 1:
dotPx = (dotPx + dotBx)/2
dotPy = (dotPy + dotBy)/2
drawer.goto(dotPx, dotPy)
drawer.dot(5, "black")
print("B", dotPx, dotPy)
x+=1
if x == 2:
dotPx = (dotPx + dotCx)/2
dotPy = (dotPy + dotCy)/2
drawer.goto(dotPx, dotPy)
drawer.dot(5, "black")
print("C", dotPx, dotPy)
x = 0
I watched the video and played with your code and can't see the inconsistency. But looking further afield, I found that by changing your x (corner selection) from being cyclic, to instead being random, it works fine:
from turtle import Turtle
from random import randint
turtle = Turtle()
turtle.speed('fastest')
turtle.hideturtle()
turtle.penup()
# make dot A
dotAx, dotAy = 0, 0
turtle.goto(dotAx, dotAy)
turtle.dot(10, 'red')
# make dot B
dotBx, dotBy = 150, 260
turtle.goto(dotBx, dotBy)
turtle.dot(10, 'red')
# make dot C
dotCx, dotCy = 300, 0
turtle.goto(dotCx, dotCy)
turtle.dot(10, 'red')
# make random dot inside triangle
dotPx, dotPy = 100, 75
turtle.goto(dotPx, dotPy)
turtle.dot(5, 'green')
# draw dots
while True:
x = randint(0, 2) # pick a random corner
if x == 0:
dotPx = (dotAx + dotPx)/2
dotPy = (dotAy + dotPy)/2
turtle.goto(dotPx, dotPy)
turtle.dot(5)
elif x == 1:
dotPx = (dotBx + dotPx)/2
dotPy = (dotBy + dotPy)/2
turtle.goto(dotPx, dotPy)
turtle.dot(5)
elif x == 2:
dotPx = (dotCx + dotPx)/2
dotPy = (dotCy + dotPy)/2
turtle.goto(dotPx, dotPy)
turtle.dot(5)
Perhaps this will narrow your search as to why your orignal approach, as suggested by the video, failed. If I were writing this from scratch, and attempting to get finer detail (and speed), I might take greater advantage of turtle and Python by doing:
from turtle import Screen, Turtle, Vec2D
from random import choice
VERTICES = [Vec2D(0, 0), Vec2D(150, 260), Vec2D(300, 0)]
point = Vec2D(100, 75) # random point inside triangle
def doit():
global point
point = (choice(VERTICES) + point) * 0.5
turtle.goto(point)
turtle.dot(2)
screen.update()
screen.ontimer(doit)
screen = Screen()
screen.tracer(False)
turtle = Turtle()
turtle.hideturtle()
turtle.penup()
for vertex in VERTICES:
turtle.goto(vertex)
turtle.dot(5, 'red')
turtle.goto(point)
turtle.dot(5, 'green')
doit()
screen.mainloop()
I am trying to create a game where a turtle is confined in a box. A ball bounces around the box, and if it collides with the turtle, or if the turtle touches the perimeter of the box, the game is over. A red dot spawns in a random location in the box, and when the turtle runs over that dot, the dot is supposed to disappear and respawn somewhere else. However, this only works sometimes. Sometimes the dot will randomly disappear and spawn somewhere else even though the turtle isn't even close to it. How can I fix this?
from turtle import Screen, Turtle, mainloop
wn = Screen()
wn.bgcolor("light blue")
#CONTROLLABLE TURTLE
t = Turtle()
t.color('black')
t.pensize(10)
t.shape("turtle")
t.speed("fastest")
t.penup()
t.goto(-130,-200)
t.pendown()
global hit
global score
hit = False
score = 0
#MAKE SQUARE
for i in range(4):
t.forward(400)
t.left(90)
t.penup()
t.goto(50,0)
speed = 2
t.color("black")
#BALL
ball1 = turtle.Turtle()
ball1.color("blue")
ball1.speed(0)
ball1.penup()
ball1.shape("circle")
A = random.randint(30,60)
B = random.randint(120,150)
C = random.randint(210,240)
D = random.randint(300,330)
Directions = [A, B, C, D]
direct = random.choice(Directions)
def tDirection(direct):
ball1.right(direct)
tDirection(direct)
angle = 90
#DOT TURTLE
dot = turtle.Turtle()
dot.color("black")
dot.speed(0)
dot.hideturtle()
def createDot():
dotx = random.randint(-10,230)
doty = random.randint(-160,200)
dot.penup()
dot.goto(dotx,doty)
dot.pendown()
dot.pensize(3)
dot.fillcolor("Red")
dot.begin_fill()
dot.circle(7)
dot.end_fill()
createDot()
#make score function
while True:
if hit == False:
#moving ball
ty = ball1.ycor()
tx = ball1.xcor()
if ty < -183:
angleCurr = ball1.heading()
if(270>angleCurr>180):
ball1.right(angle)
else:
ball1.left(angle)
ball1.forward(2)
elif ty > 185:
angleCurr = ball1.heading()
if(0<angleCurr<90):
ball1.right(angle)
else:
ball1.left(angle)
ball1.forward(2)
elif tx < -115:
angleCurr = ball1.heading()
if(180<angleCurr<270):
ball1.left(angle)
else:
ball1.right(angle)
ball1.forward(2)
elif tx > 251:
angleCurr = ball1.heading()
if(0<angleCurr<90):
ball1.left(angle)
else:
ball1.right(angle)
ball1.forward(9)
wn.onkey(lambda: t.setheading(180), 'Left')
wn.onkey(lambda: t.setheading(0), 'Right')
wn.onkey(lambda: t.setheading(90), 'Up')
wn.onkey(lambda: t.setheading(270), 'Down')
w = turtle.Turtle()
w.hideturtle()
w.penup()
w.speed("fastest")
def end():
w.goto(-95,-20)
w.pendown()
w.write("GAME OVER", font=("Arial", 40, "normal"))
t.hideturtle()
ball1.hideturtle()
dot.hideturtle()
dot.clear()
speed = 2
def turtleMove():
t.forward(speed)
wn.ontimer(turtleMove, 10)
dodx = dot.xcor()
dody = dot.ycor()
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() == dody) < 5:
hit = True
dot.clear()
elif abs(t.xcor() - tx) < 5 and abs(t.ycor() - ty) < 5:
end()
if t.xcor() > 253 or t.xcor() < -115 or t.ycor() > 185 or t.ycor() < -183:
end()
turtleMove()
wn.mainloop()
wn.listen()
if hit == True:
createDot()
score+=1
print(score)
hit = False
I think it might just be a typo:
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() == dody) < 5:
Your collision detection is doing a comparison with the y coordinates instead of subtracting like you did with the x coordinates.
So this should fix it:
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() - dody) < 5:
I would avoid code like this:
dodx = dot.xcor()
dody = dot.ycor()
if abs(t.xcor() - dodx) < 5 and abs(t.ycor() == dody) < 5:
hit = True
dot.clear()
elif abs(t.xcor() - tx) < 5 and abs(t.ycor() - ty) < 5:
end()
And instead use turtle's distance() method:
if t.distance(dot) < 5:
hit = True
dot.clear()
elif t.distance(ball1) < 5:
end()
However, this only works sometimes. Sometimes the dot will randomly
disappear and spawn somewhere else even though the turtle isn't even
close to it.
Are you pretending that this code runs? It doesn't even start up due to two different import issues. Fixing those, the turtle controls don't work at all. And the ball doesn't bounce around the box!
This appears to be a random collection of bits of code borrowed from other programs patched together with wishful thinking. It simply doesn't work.
Below I've taken apart your code and put it back together again such that it basically runs. The blue ball does bounce around the box; you can move the turtle with the arrow keys; the red dot does disappear and reappear elsewhere when the turtle touches it:
from turtle import Screen, Turtle
from random import randint, choice
CURSOR_SIZE = 20
def tDirection(direct):
ball.right(direct)
def turtleMove():
turtle.forward(speed)
screen.ontimer(turtleMove, 10)
def createDot():
x, y = randint(CURSOR_SIZE - 200, 200 - CURSOR_SIZE), randint(CURSOR_SIZE - 200, 200 - CURSOR_SIZE)
dot.goto(x, y)
def end():
marker.write("GAME OVER", align='center', font=("Arial", 40, "normal"))
turtle.hideturtle()
ball.hideturtle()
dot.hideturtle()
screen = Screen()
screen.bgcolor("light blue")
score = 0
speed = 2
# CONTROLLABLE TURTLE
turtle = Turtle("turtle")
turtle.color('black')
turtle.pensize(10)
turtle.speed("fastest")
turtle.penup()
turtle.goto(-200, -200)
turtle.pendown()
# MAKE SQUARE
for i in range(4):
turtle.forward(400)
turtle.left(90)
turtle.penup()
turtle.goto(50, 0)
# BALL
ball = Turtle("circle")
ball.color("blue")
ball.speed('fastest')
ball.penup()
A = randint(30, 60)
B = randint(120, 150)
C = randint(210, 240)
D = randint(300, 330)
directions = [A, B, C, D]
direct = choice(directions)
tDirection(direct)
angle = 90
# DOT TURTLE
dot = Turtle('circle')
dot.color("red")
dot.speed('fastest')
dot.pensize(3)
dot.penup()
createDot()
marker = Turtle(visible=False)
marker.penup()
marker.sety(-20)
screen.onkey(lambda: turtle.setheading(0), 'Right')
screen.onkey(lambda: turtle.setheading(90), 'Up')
screen.onkey(lambda: turtle.setheading(180), 'Left')
screen.onkey(lambda: turtle.setheading(270), 'Down')
screen.listen()
turtleMove()
while True:
# moving ball
tx, ty = ball.position()
if ty < CURSOR_SIZE - 200:
angleCurr = ball.heading()
if 270 > angleCurr > 180:
ball.right(angle)
else:
ball.left(angle)
ball.forward(2)
elif ty > 200 - CURSOR_SIZE:
angleCurr = ball.heading()
if 0 < angleCurr < 90:
ball.right(angle)
else:
ball.left(angle)
ball.forward(2)
elif tx < CURSOR_SIZE - 200:
angleCurr = ball.heading()
if 180 < angleCurr < 270:
ball.left(angle)
else:
ball.right(angle)
ball.forward(2)
elif tx > 200 - CURSOR_SIZE:
angleCurr = ball.heading()
if 0 < angleCurr < 90:
ball.left(angle)
else:
ball.right(angle)
ball.forward(2)
ball.forward(9)
if turtle.distance(dot) < CURSOR_SIZE/2:
score += 1
dot.hideturtle()
createDot()
dot.showturtle()
elif turtle.distance(ball) < CURSOR_SIZE/2:
end()
if not CURSOR_SIZE - 200 < turtle.xcor() < 200 - CURSOR_SIZE or not CURSOR_SIZE - 200 < turtle.ycor() < 200 - CURSOR_SIZE:
end()
screen.mainloop()
When asking for help on SO, please be honest about the state of your code.
The above code isn't complete, there is still work to do. E.g. the while True: loop should be converted to a function and ontimer() event; the score needs to be displayed; the game should be made restartable.
So, I have asked a similar question before, but I was still unable to solve my problem. I need to make a checkerboard with 6 game pieces evenly on each side. This code was helpful, but it randomly distributes the game pieces, I've played around with it in multiple lines and attempted to understand but it's not clicking for me. How can I get six pieces to be on top half and six to be on lower half with space in the middle? Like a regular checkerboard set up?
from turtle import Turtle, Screen
from random import randrange
CURSOR_SIZE = 20
SQUARE_SIZE = 40
SQUARES_PER_SIDE = 8
def drawRect(color):
turtle.color(color)
turtle.pendown()
turtle.begin_fill()
for iterations in range(4):
turtle.forward(SQUARE_SIZE)
turtle.left(90)
turtle.end_fill()
turtle.penup()
def pushTurtleForward():
turtle.forward(SQUARE_SIZE)
def drawHorizontal(inverted=False):
if inverted:
for horizontal in range(SQUARES_PER_SIDE):
if horizontal > 0:
if horizontal % 2 == 1:
pushTurtleForward()
drawRect("white")
else:
pushTurtleForward()
drawRect("black")
else:
drawRect("black")
else:
for horizontal in range(SQUARES_PER_SIDE):
if horizontal > 0:
if horizontal % 2 == 1:
pushTurtleForward()
drawRect("black")
else:
pushTurtleForward()
drawRect("white")
else:
drawRect("white")
screen = Screen()
screen.bgcolor("Grey")
turtle = Turtle(visible=False)
turtle.speed('fastest')
for drawVertical in range(SQUARES_PER_SIDE):
turtle.setposition(0, SQUARE_SIZE * drawVertical)
if drawVertical % 2 == 0:
drawHorizontal(inverted=True)
else:
drawHorizontal()
# Checker graphics demonstration. Distribute 12 red checkers around
# black squares on board without any two landing on the same spot.
red_checkers = []
for _ in range(12):
checker = Turtle('circle')
checker.color('black', 'red')
checker.shapesize(SQUARE_SIZE / CURSOR_SIZE)
checker.penup()
red_checkers.append(checker)
position = checker.position() # a position guaranteed to fail
while any(map(lambda checker, p=position: checker.distance(p) <
SQUARE_SIZE/2, red_checkers)):
x, y = 0, 1 # a parity guaranteed to fail
while x % 2 != y % 2:
x, y = (SQUARES_PER_SIDE),(SQUARES_PER_SIDE)
position = (x * SQUARE_SIZE + SQUARE_SIZE/2, y * SQUARE_SIZE +
SQUARE_SIZE/2)
checker.goto(position)
screen.mainloop()
I think this is what you want. Replace the for _ in range(12): loop with this:
# Returns the drawing co-ords of checker space
def get_square_coords(row, col):
return (col * SQUARE_SIZE + SQUARE_SIZE/2, row * SQUARE_SIZE + SQUARE_SIZE/2)
# Creates 2 rows of checkers
def create_checkers(row, color):
checkers = []
col = 0
for y in range(row, row+2):
for x in range(col, SQUARES_PER_SIDE, 2):
checker = Turtle('circle')
checker.color('black', color)
checker.shapesize(SQUARE_SIZE / CURSOR_SIZE)
checker.penup()
position = get_square_coords(y, x)
checker.goto(position)
checkers.append(checker)
col += 1
return checkers
red_checkers = create_checkers(0, 'red')
green_checkers = create_checkers(6, 'green')
It creates this:
I am trying to setup a program in which the user decides how many turtles to generate and then they have a race after. My current solution is to just get an int input from the user and execute the code below (the code keeps repeating with larger numbers). I have tried putting in a loop but I am running into troubles since they all need to preform random movements in the end. Any help?
if turtNum >= 1:
turt1 = Turtle()
turt1.color(turtColour[0])
turt1.shape('turtle')
turt1.penup()
turt1.goto(0, -10)
turt1.pendown()
if turtNum >= 2:
turt2Name = input('Enter a name for the second turtle: ')
turt2 = Turtle()
turt2.color(turtColour[1])
turt2.shape('turtle')
turt2.penup()
turt2.goto(0, -25)
turt2.pendown()
This is the code I tried but got this error "list indices must be integers or slices, not str"
turtName = []
maxLengthList = turtNum
while len(turtName) < maxLengthList:
name = input('Enter the names for the turtles: ')
turtName.append(name)
for i in turtName:
turtName[i] = Turtle()
turtName[i].color(turtColour[0])
turtName[i].shape('turtle')
turtName[i].penup()
turtName[i].goto(0, -10)
turtName[i].pendown()
You can't dangle the concept of turtle racing without expecting us to get excited about seeing it happen. Below is a rough implementation that addresses the issues you had about entering the number of turtles, entering individual turtle information, storing it all and random motion:
from turtle import Turtle, Screen
from itertools import cycle
from random import randrange
MAX_TURTLES = 20
LANE_WIDTH = 25
FONT_SIZE = 18
FONT = ("Arial", FONT_SIZE, "normal")
COLORS = cycle(['red', 'green', 'blue', 'cyan', 'black', 'yellow'])
FINISH_LINE = 350
START_LINE = -200
NAME_LINE = START_LINE - 150
DELAY = 100 # milliseconds
MAX_STEP = 10
turtles = dict()
def race():
for name, turtle in turtles.items(): # should shuffle turtles
turtle.forward(randrange(MAX_STEP + 1))
if turtle.xcor() > FINISH_LINE:
return # the race is over
screen.ontimer(race, DELAY)
magic_marker = Turtle(visible=False)
magic_marker.penup()
turtNum = 0
while not 1 <= turtNum <= MAX_TURTLES:
turtNum = int(input('Enter the number of turtles: '))
for i in range(turtNum):
name = input('Enter a name for the turtle #{}: '.format(i + 1))
turtle = Turtle(shape="turtle")
turtle.color(next(COLORS))
y_offset = LANE_WIDTH * i - LANE_WIDTH * turtNum // 2
magic_marker.color(turtle.pencolor())
magic_marker.goto(NAME_LINE, y_offset - FONT_SIZE / 2)
magic_marker.write(name, font=FONT)
turtle.penup()
turtle.goto(START_LINE, y_offset)
turtle.pendown()
turtles[name] = turtle
magic_marker.color('red')
magic_marker.goto(FINISH_LINE, -FINISH_LINE)
magic_marker.pendown()
magic_marker.goto(FINISH_LINE, FINISH_LINE)
magic_marker.penup()
screen = Screen()
screen.ontimer(race, DELAY)
screen.exitonclick()