i wanna draw a chessboard and here is my code(edited) - python

it has no error now but i want to draw a chess board but this thing just randomly output something else:)))))
i think there is something wrong with the fill function tho
import turtle
screen = turtle.Screen()
screen.setup(800,800)
screen.bgcolor('pink')
screen.colormode(255)
screen.title("chessboard")
turtle = turtle.Turtle()
def draw(length,angle):
for i in range (4):
turtle.forward(length)
turtle.right(angle)
length = 30
angle = 90
coor = -120
num = 64
def board(length):
draw(length,angle)
turtle.forward(length)
def limit():
for q in range (8):
board(length)
def pos(coor,length):
for w in range(8):
turtle.penup()
turtle.setpos(coor,coor+30*w)
turtle.pendown()
limit()
def fill():
for q in range (8):
for w in range(8):
if (q+w)%2==0:
turtle.fillcolor('#000000')
else:
turtle.fillcolor('#FFFFFF')
def repeat():
for h in range (8):
draw(length,angle)
turtle.forward(length)
def color():
turtle.begin_fill()
repeat()
pos(coor,length)
fill()
turtle.end_fill()
turtle.speed(0)
turtle.penup()
turtle.goto(coor, coor)
turtle.pendown()
turtle.hideturtle()
screen.update()
color()
it has no error now but i want to draw a chess board but this thing just randomly output something else:)))))
i think there is something wrong with the fill function tho

I'm just learning python as well, so I found your problem being an interesting thing to try to do myself.
Please see below a solution that works, using some ideas from your code and my own implementation too.
If anything of the above helps you fix your own code, or have any questions I might be able to answer, please let me know :)
import turtle
# draw a square at given pos
def draw_square(t, fwd, angle):
for _ in range(4):
t.forward(fwd)
t.right(angle)
def changePos(t, startPos, endPos, penUp):
if penUp:
t.pu()
t.goto(startPos, endPos)
if penUp:
t.pd()
# Let's skip the drawing all together?
turtle.tracer(0, 0)
# taking input for the side of the square
squareSize = 100
angle = 90
boardSquares = 8
startPos = -(squareSize * (boardSquares/2)), (squareSize * (boardSquares/2)) #start from top-left
print("Start position: ", startPos)
screen = turtle.Screen()
screen.setup(850, 850)
screen.bgcolor('pink')
screen.title("chessboard")
# create the white squares
squares = turtle.Turtle()
squares.hideturtle()
squares.fillcolor("white")
squares.pensize(1)
squares.pencolor("red")
changePos(squares, startPos[0], startPos[1], True)
for r in range(8):
for c in range(8):
if (r + c) % 2 == 0:
squares.fillcolor('#000000')
else:
squares.fillcolor('#FFFFFF')
changePos(squares, startPos[0] + (squareSize * c), startPos[1] - (squareSize * r), True)
squares.begin_fill()
draw_square(squares, squareSize, angle)
squares.end_fill()
# let's draw the board edge
board = turtle.Turtle()
board.hideturtle()
changePos(board, startPos[0], startPos[1], True)
board.pensize(5)
board.pencolor("brown")
draw_square(board, boardSquares * squareSize, angle)
turtle.update()
turtle.exitonclick()

Related

How to create new Python Turtle image each iteration?

I want to create 100 images via Python Turtle and each iteration there should be only 2 geometric shapes drawn on each image (files test0.jpg, test1.jpg etc). However, in my code each next image is drawn on the previous one, which causes collision. Can you help me please?
import turtle
import random
from PIL import Image
def generate(tur1):
a = random.randint(2, 7)
b = random.randint(2, 7)
c = random.randint(50, 100)
if a != 2:
for i in range(a):
tur1.forward(c)
tur1.left(360.0 / a)
else:
tur1.circle(c)
tur1.penup()
tur1.goto(-200, 0)
tur1.pendown()
if b != 2:
for j in range(b):
tur1.forward(c)
tur1.left(360.0 / b)
else:
tur1.circle(c)
for i in range(0, 100):
tur2 = turtle.Turtle()
tur2.color('green')
tur2.speed(1)
tur2.hideturtle()
generate(tur2)
screen = tur2.getscreen()
screen.setup(600, 600)
canvas = screen.getcanvas()
canvas.postscript(file="test"+str(i)+".eps")
img = Image.open("test"+str(i)+".eps")
img.save("test"+str(i)+".jpg")
You need to use something like turtle.clear() (+1 #JohnnyMopp) or more likely turtle.reset(), or turtle.home() in combination with turtle.clear(), since you moved the turtle. A slight rework of your code:
from turtle import Screen, Turtle
from random import randint
from PIL import Image
def generate(turtle):
a = randint(2, 7)
b = randint(50, 100)
if a == 2:
turtle.circle(b)
else:
for _ in range(a):
turtle.forward(b)
turtle.left(360 / a)
turtle.penup()
turtle.setx(-200)
turtle.pendown()
a = randint(2, 7)
if a == 2:
turtle.circle(b)
else:
for _ in range(a):
turtle.forward(b)
turtle.left(360 / a)
screen = Screen()
screen.setup(600, 600)
turtle = Turtle()
for i in range(10):
# inside loop only because reset() also resets these...
turtle.hideturtle()
turtle.color('green')
turtle.speed('fastest')
eps = "test" + str(i) + ".eps"
jpg = "test" + str(i) + ".jpg"
generate(turtle)
canvas = screen.getcanvas()
canvas.postscript(file=eps)
img = Image.open(eps)
img.save(jpg)
turtle.reset()

In the turtle module, how to find the maximum values of coordinates?

import turtle as t
from random import randint, random
def draw_star(points, size, col, x, y):
t.penup()
t.goto(x, y)
t.pendown()
angle = 180 - (180 / points)
t.color(col)
t.begin_fill()
for i in range(points):
t.forward(size)
t.right(angle)
t.end_fill()
# Main code
while True:
ranPts = randint(2, 5) * 2 + 1
ranSize = randint(10, 50)
ranCol = (random(), random(), random())
ranX = randint(-350, 300)
ranY = randint(-250, 250)
draw_star(ranPts, ranSize, ranCol, ranX, ranY)
Question:
How could I know the maximum values of coordinates of my screen? So I can have a better idea on how to set the values of ranX and ranY?
Thanks.
You could use t.setworldcoordinates(llx, lly, urx, ury)
The parameters:
llx = x of lower left corner
lly = y of lower left corner
urx= x of upper right corner
ury = y of upper right corner
You can create a function and find the values of coordinates yourself by clicking on the screen like this:
# turtle library
import turtle
#This to make turtle object
tess=turtle.Turtle()
# self defined function to print coordinate
def buttonclick(x,y):
print("You clicked at this coordinate({0},{1})".format(x,y))
#onscreen function to send coordinate
turtle.onscreenclick(buttonclick,1)
turtle.listen() # listen to incoming connections
turtle.speed(10) # set the speed
turtle.done() # hold the screen
This will print everytime you click on the screen and print the coordinates out.
The screensize() function returns the canvas width and the canvas height as a tuple.
You can use this to find the max coordinates of the canvas.
screenSize = t.screensize() #returns (width, height)
# Main code
while True:
ranPts = randint(2, 5) * 2 + 1
ranSize = randint(10, 50)
ranCol = (random(), random(), random())
ranX = randint(50-screenSize[0], screenSize[0] - 100)
ranY = randint(50-screenSize[1], screenSize[1] - 100)
draw_star(ranPts, ranSize, ranCol, ranX, ranY)
I found out this is what I need: t.window_width() and t.window_height().

Draw then erase square

I'm trying to draw a square using python graphics then erase it after 3 seconds. I have the code below:
import threading as th
import turtle
import random
thread_count = 0
def draw_square():
turtle.goto(random.randint(-200,200), random.randint(-200,200))
for i in range(4):
turtle.forward(100)
turtle.left(90)
def erase_square(x,y):
turtle.pencolor('white')
turtle.fillcolor('white')
turtle.goto(x,y)
turtle.begin_fill()
for i in range(4):
turtle.forward(target_size)
turtle.left(90)
turtle.end_fill()
def square_timer():
global thread_count
if thread_count <= 10:
print("Thread count", thread_count)
draw_square()
T = th.Timer(3, square_timer)
T.start()
The square_update() function will draw 10 squares then stop. I'm trying to make it draw one square then clear it using the erase_square() by painting white over it, then another and repeat the process and stop when it reaches 10. I can't figure how to make the erase function go to the random location of the drawn square and 'erase' it. How can I make it draw and erase the square?
The most straightforward way to clear a drawing is with the clear() method rather than trying to draw white over the image:
from turtle import Screen, Turtle
from random import randint
def draw_square():
turtle.goto(randint(-200, 200), randint(-200, 200))
turtle.pendown()
for _ in range(4):
turtle.forward(100)
turtle.left(90)
turtle.penup()
def erase_square():
turtle.clear()
screen.ontimer(square_update) # no time, ASAP
def square_update():
draw_square()
screen.ontimer(erase_square, 3000) # 3 seconds in milliseconds
screen = Screen()
turtle = Turtle()
turtle.hideturtle()
turtle.speed('fastest')
turtle.penup()
square_update()
screen.exitonclick()
You can use the undo() method as #JonathanDrukker suggests, but you have to undo each step. Even for a simple shape like a square, this takes a little thought, but with a complex shape, this is difficult. The number of operations added to the undo buffer don't always match the calls that you make to turtle. But we can get that count from turtle itself, as long as we don't do any other turtle actions between drawing and erasing:
def draw_square():
turtle.goto(randint(-200, 200), randint(-200, 200))
count = turtle.undobufferentries()
turtle.pendown()
for _ in range(4):
turtle.forward(100)
turtle.left(90)
turtle.penup()
return turtle.undobufferentries() - count
def erase_square(undo_count):
for _ in range(undo_count):
turtle.undo()
screen.ontimer(square_update)
def square_update():
undo_count = draw_square()
screen.ontimer(lambda: erase_square(undo_count), 3000)
But what I'd do is make the turtle itself the square and then just move it rather than erase and (re)draw the square:
from turtle import Screen, Turtle
from random import randint
CURSOR_SIZE = 20
def draw_square():
turtle.goto(randint(-200, 200), randint(-200, 200))
def square_update():
turtle.hideturtle()
draw_square()
turtle.showturtle()
screen.ontimer(square_update, 3000)
screen = Screen()
turtle = Turtle()
turtle.hideturtle()
turtle.shape('square')
turtle.shapesize(100 / CURSOR_SIZE)
turtle.fillcolor('white')
turtle.penup()
square_update()
screen.exitonclick()

Why isn't this code working? I am new and I really need assistance

So I am trying to make it so when the lt turtle collides with the circle turtles(the ones in the list) it draws a star. But when I run it and try it the turtle does not draw a star. Please run it and see that I am trying to make it so when my turtle collides with the circles the turtle draws a star.
import turtle
import random
screen=turtle.Screen()
screen.listen()
list=[]
lt=turtle.Turtle()
lt.penup()
lt.shape("turtle")
for i in range(10):
x=random.randint(-250,250)
y=random.randint(-250,250)
st=turtle.Turtle()
list.append(st)
for z in list:
z.speed(1000)
z.shape("circle")
z.color("white")
x=random.randint(-250,250)
y=random.randint(-250,250)
z.penup()
z.goto(x,y)
z.pendown()
def left():
lt.forward(2)
lt.left(10)
screen.onkey(left,"A")
def right():
lt.forward(2)
lt.right(10)
screen.onkey(right,"D")
r=195
g=20
b=50
screen.bgcolor(r,g,b)
def StarCheck(z):
if abs(lt.xcor()-z.xcor()) <15 and abs(lt.ycor()-z.ycor()) <15:
z.clear()
lt.color("yellow")
lt.begin_fill()
for i in range(5):
lt.forward(5)
lt.right(145)
lt.forward(10)
lt.end_fill()
while True:
r=r-0.20
screen.bgcolor(r,g,b)
lt.forward(1)
for n in list:
StarCheck(z)
I would assume you have a typo in your while loop. It should be
StarCheck(n) instead of StarCheck(z)
Below is the listing of your altered code.
import turtle
import random
screen = turtle.Screen()
screen.listen()
list = []
lt = turtle.Turtle()
lt.penup()
lt.shape("turtle")
for i in range(10):
x = random.randint(-250, 250)
y = random.randint(-250, 250)
st = turtle.Turtle()
list.append(st)
for z in list:
z.speed(1000)
z.shape("circle")
z.color("white")
x = random.randint(-250, 250)
y = random.randint(-250, 250)
z.penup()
z.goto(x, y)
z.pendown()
def left():
lt.forward(2)
lt.left(10)
screen.onkey(left, "A")
def right():
lt.forward(2)
lt.right(10)
screen.onkey(right, "D")
r = 0.9
g = 0.2
b = 0.5
screen.bgcolor('red')
def StarCheck(z):
if abs(lt.xcor() - z.xcor()) < 10 and abs(lt.ycor() - z.ycor()) < 10:
z.clear()
lt.color("yellow")
lt.begin_fill()
for i in range(5):
lt.forward(10)
lt.right(120)
lt.forward(10)
lt.right(72 - 120)
lt.end_fill()
return
while True:
r = r - 0.000002
screen.bgcolor(r, g, b)
lt.forward(1)
for n in list:
StarCheck(n)
I ran this code and a yellow star is created as the turtle goes over the white circles.
You might also want to refer colormode for setting appropriate RGB values or color. I am using python 3.7.
HTH
I made the changes that #MustafaHaider suggests and implies but I couldn't get your code to work in any real sense. There's a lot broken:
As #MustafaHaider noted, if this is standard Python turtle, you'd need to call:
colormode(255)
If you're not using standard Python turtle, eg. the Repl site, you need to mention that in your question. This makes no sense:
z.speed(1000)
The numeric arguments range from 0 to 10, though I suggest a symbolic argument like "fastest". This will eventually underflow and cause an error:
r=r-0.20
#MustafaHaider switched to a smaller increment but that's the same issue -- using a multiplicative reduction and int() wouldn't have this problem. Did you really want the user to have the CAPSLOCK pressed on some systems:
screen.onkey(left,"A")
screen.onkey(right,"D")
If not, I suggest "a" and "d" instead. There's a turtle method for this:
if abs(lt.xcor()-z.xcor()) <15 and abs(lt.ycor()-z.ycor()) <15:
it's called distance(). This doesn't do what you want:
z.clear()
as z hasn't drawn anything. You want z.hideturtle() and only call StarCheck(z) if z.isvisible(). Below is my rework of your code that addresses the above issues as well as others I haven't mentioned and general style:
from turtle import Screen, Turtle
from random import randint
def left():
player.left(10)
def right():
player.right(10)
def StarCheck(enemy):
if player.distance(enemy) < 15:
enemy.hideturtle()
player.begin_fill()
for _ in range(5): # a la #MustafaHaider
player.forward(10)
player.right(120)
player.forward(10)
player.left(48)
player.end_fill()
r, g, b = 195, 20, 50
screen = Screen()
screen.colormode(255)
screen.bgcolor(r, g, b)
player = Turtle()
player.shape('turtle')
player.color('yellow')
player.speed('fastest')
player.penup()
enemies = []
for _ in range(10):
enemy = Turtle()
enemy.hideturtle()
enemy.shape('circle')
enemy.color('white')
x = randint(-250, 250)
y = randint(-250, 250)
enemy.penup()
enemy.goto(x, y)
enemy.pendown()
enemy.showturtle()
enemies.append(enemy)
screen.onkey(left, 'a')
screen.onkey(right, 'd')
screen.listen()
while True:
r *= 0.9999
screen.bgcolor(int(r), g, b)
player.forward(1)
for enemy in enemies:
if enemy.isvisible():
StarCheck(enemy)
screen.mainloop() # never reached
This should be playable now. There's more to do, e.g. replace your while True: loop with a function and timed event if this is standard Python turtle.

Python multiple onclick events

I want to be able to have both of my turtle onclick events function, but only one of them functions. I have a function that draws a square at the location the user clicks, and I have a close button that closes the program when you click it. Only one of these functions work at a time.
import turtle
import math
turtle.penup()
def square(x, y):
turtle.up()
turtle.goto(x, y)
turtle.down()
for i in range(4):
turtle.forward(50)
turtle.left(90)
def closebutton(location1):
(x,y) = location1
turtle.up()
turtle.setposition(location1)
turtle.down()
for i in range(2):
turtle.forward(40)
turtle.left(90)
turtle.forward(25)
turtle.left(90)
turtle.up()
turtle.forward(7.5)
turtle.left(90)
turtle.forward(5)
turtle.right(90)
turtle.write("close")
def btnclick(x, y):
if x > 100 and x < 141 and y > -100 and y < -75:
quit()
turtle.onscreenclick(btnclick)
closebutton((100,-100))
turtle.onscreenclick(square)
def square(x, y):
# Check area is Close button
if x > 100 and x < 141 and y > -100 and y < -75:
quit()
turtle.up()
turtle.goto(x, y)
turtle.down()
for i in range(4):
turtle.forward(50)
turtle.left(90)
I think, at square function, we can check that is close button's area
We can solve this the way you attempted, but we have to add the screen click handlers in a specific order and take advantage of the little-used add parameter:
from turtle import Screen, Turtle, mainloop
FONT_SIZE = 20
FONT = ('Arial', FONT_SIZE, 'normal')
def draw_square(x, y):
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
for _ in range(4):
turtle.forward(50)
turtle.left(90)
def button_clicked(x, y):
if 100 < x < 100 + text_width and -FONT_SIZE/2 - 100 < y < FONT_SIZE/2 - 100:
quit()
def make_close_button(x, y):
turtle.penup()
turtle.setposition(x, y - FONT_SIZE / 2)
turtle.write("close", move=True, font=FONT)
width = turtle.xcor() - x # pixel width of text we just wrote
turtle.pendown()
for _ in range(2):
turtle.left(90)
turtle.forward(FONT_SIZE)
turtle.left(90)
turtle.forward(width)
turtle.penup()
turtle.home()
return width
turtle = Turtle()
text_width = make_close_button(100, -100)
screen = Screen()
screen.onscreenclick(button_clicked)
screen.onscreenclick(draw_square, add=True)
mainloop()
But this approach makes it hard to disable the onscreenclick() event inside the event handler code. That is, while one square is still being drawn, you can click elsewhere on the screen and start a second, interfering with the completion of the first. To solve this we might try a completely different approach with a single event handler function that we can disable and reenable as needed:
from turtle import Screen, Turtle, mainloop
FONT_SIZE = 20
FONT = ('Arial', FONT_SIZE, 'normal')
def draw_square():
for _ in range(4):
turtle.forward(50)
turtle.left(90)
def button_clicked(x, y):
screen.onscreenclick(None) # disable event handler inside event handler
if button.distance(x, y) < FONT_SIZE:
quit()
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
draw_square()
screen.onscreenclick(button_clicked)
def make_close_button(x, y):
button = Turtle(visible=False)
button.speed('fastest')
button.penup()
button.setposition(x, y - FONT_SIZE / 2)
button.write("close", move=True, font=FONT)
width = button.xcor() - x # pixel width of text we just wrote
button.pendown()
for _ in range(2):
button.left(90)
button.forward(FONT_SIZE)
button.left(90)
button.forward(width)
button.penup()
button.setposition(x + width / 2, y)
return button
button = make_close_button(100, -100)
turtle = Turtle()
screen = Screen()
screen.onscreenclick(button_clicked)
mainloop()
Here we broke up the functionality a bit to have functions with specific duties. And instead of figuring out if we clicked near the button, we left a turtle behind and just check the distance of the click from that turtle.
Both approaches have their advantages and disadvantages.

Categories