Labeling a game board in python using turtle graphics - python

I'm currently making a 5x5 grid for a snakes and ladder but can't figure out how to display the numbers on the grid in this formation;
21,22,23,24,25
20,19,18,17,16
11,12,13,14,15
10, 9, 8, 7, 6
1 , 2, 3, 4, 5
The code I've wrote makes the 5x5 grid, I'm juts note sure how to add the labels of if I should take a
different approach with the code.
thanks for any help.
import turtle
t = turtle.Turtle()
speed = turtle.speed()
t.speed(10)
x=250
y=250
t.penup()
t.goto(-x,y)
t.pendown()
turtle.hideturtle()
turtle.ht()
for a in range(5):
t.penup()
t.goto(-x,-y)
t.pendown()
y=y-100
for b in range(5):
for n in range(5):
t.speed(10)
t.fd(100)
if n!=4:
t.right(90) here

Here's a solution that uses much of your existing logic, tweaking it a bit, and adds the numbers:
from turtle import Screen, Turtle
FONT_SIZE = 18
FONT = ('Arial', FONT_SIZE, 'bold')
BOXES = 5
BOX_SIZE = 100
screen = Screen()
turtle = Turtle()
turtle.hideturtle()
turtle.speed('fastest')
x = -BOX_SIZE * BOXES / 2
y = -BOX_SIZE * BOXES / 2
for i in range(BOXES):
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
for j in range(BOXES):
for _ in range(4):
turtle.forward(BOX_SIZE)
turtle.left(90)
dx, dy = turtle.position()
turtle.penup()
turtle.goto(dx + BOX_SIZE/2, dy + BOX_SIZE/2 - FONT_SIZE / 2)
turtle.write(j + BOXES * i + 1, align='center', font=FONT)
turtle.setposition(dx, dy)
turtle.pendown()
turtle.forward(BOX_SIZE)
y += BOX_SIZE
screen.exitonclick()
Centering-wise, the vertical font correction (FONT_SIZE / 2) is an approximation that works fine on my system but if you want an accurate solution for all systems, see this answer

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()

How to draw a dotted circle using python Turtle package

Something similar to the picture attached. I tried modifying the code I got online. But my code goes to infinity loop
[1]: https://i.stack.imgur.com/HfKog.png
def draw_circle(radius):
turtle.up()
turtle.goto(0, radius) # go to (0, radius)
turtle.pendown() # pen down
times_y_crossed = 0
x_sign = 1.0
while times_y_crossed <= 1:
turtle.dot(5, "Red")
turtle.forward(5) # move by 1/360
turtle.right(1.0)
turtle.penup()
turtle.forward(5) # move by 1/360
turtle.right(1.0)
x_sign_new = math.copysign(1, turtle.xcor())
if x_sign_new != x_sign:
times_y_crossed += 10
x_sign = x_sign_new
turtle.up() # pen up
return
There are some issues with your code, like it does not count with the radius and the color for the pen was not set and as I've checked it did a half circle for me.
I show you a simple working example, first a dashed version because your original code looks like you wanted a dashed circle
import turtle
import math
def draw_circle_dashed(radius):
turtle.up()
turtle.goto(0, radius) # go to (0, radius)
times_y_crossed = 0
dist=2*math.pi*radius/360
turtle.pencolor("red")
for _ in range(180):
turtle.pendown()
turtle.forward(dist) # move by 1/360
turtle.right(1.0)
turtle.penup()
turtle.forward(dist) # move by 1/360
turtle.right(1.0)
turtle.up() # pen up
return
draw_circle_dashed(200)
and a dotted variant as well because of the question title
import turtle
import math
def draw_circle_dotted(radius):
turtle.up()
turtle.goto(0, radius) # go to (0, radius)
dist=2*math.pi*radius/360
for _ in range(360):
turtle.dot(2,"red")
turtle.forward(dist) # move by 1/360
turtle.right(1.0)
turtle.up() # pen up
return
draw_circle_dotted(300)
We can use turtle's own circle() method to do this as we can arbitrarily start and stop it, leaving behind dots as we do:
from turtle import Screen, Turtle
from math import pi
DOT_DIAMETER = 5
def draw_circle(radius):
turtle.penup()
circumference = 2 * pi * radius
dot_extent = 360 * DOT_DIAMETER*2 / circumference # diameter to angle
extent = 0
while extent < 360:
turtle.dot(DOT_DIAMETER)
turtle.circle(radius, extent=dot_extent)
extent += dot_extent
screen = Screen()
turtle = Turtle()
turtle.color('red')
draw_circle(100)
turtle.hideturtle()
screen.exitonclick()
Using what we learned from that exercise, let's now fix your code. The issue I see is this:
turtle.right(1.0)
The angle to turn is dependent on the dot diameter, but we actually have to calculate it:
from turtle import Screen, Turtle
from math import pi, copysign
DOT_DIAMETER = 5
def draw_circle(radius):
turtle.penup()
turtle.sety(radius)
diameter = 2 * radius
circumference = pi * diameter
dot_extent = 360 * DOT_DIAMETER / circumference # diameter to angle
times_y_crossed = 0
x_sign = 1
while times_y_crossed < 2:
turtle.dot(DOT_DIAMETER, 'red') # draw the dot
turtle.right(dot_extent)
turtle.forward(DOT_DIAMETER)
turtle.right(dot_extent) # draw the gap
turtle.forward(DOT_DIAMETER)
x_sign_new = copysign(1, turtle.xcor())
if x_sign_new != x_sign:
times_y_crossed += 1
x_sign = x_sign_new
turtle.pendown()
screen = Screen()
turtle = Turtle()
turtle.color('red')
draw_circle(100)
turtle.hideturtle()
screen.exitonclick()
By not calculating the angle, and using a fixed angle of 1.0, you were off by a factor of two.

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()

How to make this wheel spin?

I have created the wheel, but when I try to make code to spin it will not work.
I have already tried to make it using a loop but that was near impossible for me. I am basically drawing the wheel over. Here is some code from the spinning wheel part:
turtle.listen()
if turtle.onkeypress("space"):
colors = ['#880000','#884400','#884400','#888800',
'#888800','#008800','#008800','#008800',
'#008800','#008800','#008888','#008888',
'#008888','#008888','#008888','#000088',
'#000088','#000088','#000088','#000088']
for color in colors:
slice_angle = 360 / len(colors)
heading, position = 90, (center[0] + radius, center[1])
turtle.color(color, color)
turtle.speed(0)
turtle.penup()
turtle.goto(position)
turtle.setheading(heading)
turtle.pendown()
turtle.begin_fill()
turtle.circle(radius, extent=slice_angle)
heading, position = turtle.heading(), turtle.position()
turtle.penup()
turtle.goto(center)
turtle.end_fill()
turtle.penup()
time.sleep(0.2)
colors = ['#884400','#884400','#888800',
'#888800','#008800','#008800','#008800',
'#008800','#008800','#008888','#008888',
'#008888','#008888','#008888','#000088',
'#000088','#000088','#000088','#000088','#880000']
for color in colors:
slice_angle = 360 / len(colors)
heading, position = 90, (center[0] + radius, center[1])
turtle.color(color, color)
turtle.speed(0)
turtle.penup()
turtle.goto(position)
turtle.setheading(heading)
turtle.pendown()
turtle.begin_fill()
turtle.circle(radius, extent=slice_angle)
heading, position = turtle.heading(), turtle.position()
turtle.penup()
turtle.goto(center)
turtle.end_fill()
turtle.penup()
time.sleep(0.2)
The code keeps on going to make the wheel 'spin'.
This is what I get:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/turtle.py", line 701, in eventfun
fun()
TypeError: 'str' object is not callable
My impression is that you're not trying to make the wheel spin but rather make it look like it's spinning by cycling its colors. Here's my example of doing such which uses tracer() and update() to turn off drawing while remaking the circle with the colors shifted. It uses a timer event to trigger redraws. Rather than your fixed list of colors, I'm going to use continuous hues, but you should be able to use any colors you wish:
from turtle import Screen, Turtle
from colorsys import hsv_to_rgb
RADIUS = 100
NUMBER_OF_WEDGES = 20
SLICE_ANGLE = 360 / NUMBER_OF_WEDGES
screen = Screen()
screen.tracer(False)
turtle = Turtle(visible=False)
turtle.penup()
center = turtle.position()
turtle.sety(turtle.ycor() - RADIUS)
hues = [color / NUMBER_OF_WEDGES for color in range(NUMBER_OF_WEDGES)] # precompute hues
index = 0
def draw_circle():
global index
for hue in range(NUMBER_OF_WEDGES):
turtle.color(hsv_to_rgb(hues[(hue + index) % NUMBER_OF_WEDGES], 1.0, 1.0))
turtle.pendown()
turtle.begin_fill()
turtle.circle(RADIUS, extent=SLICE_ANGLE)
position = turtle.position()
turtle.goto(center)
turtle.end_fill()
turtle.penup()
turtle.goto(position)
screen.update()
index = (index + 1) % NUMBER_OF_WEDGES
screen.ontimer(draw_circle, 40)
draw_circle()
screen.exitonclick()
This works, but, on my system, inexplicably slows down over time.
Let's try a different approach that doesn't redraw anything at the Python level during the cycling of colors. We're going to design a new cursor shape, "wedge" and build our circle out of turtles! All the wedges will be prepositioned and not move nor be redrawn. The timer event handler will simply ask each turtle to take on the color of its neighbor:
from turtle import Screen, Turtle
from colorsys import hsv_to_rgb
RADIUS = 100
NUMBER_OF_WEDGES = 20
SLICE_ANGLE = 360 / NUMBER_OF_WEDGES
screen = Screen()
screen.tracer(False)
# create a pie wedge-shaped cursor
turtle = Turtle(visible=False)
turtle.begin_poly()
turtle.sety(turtle.ycor() - RADIUS)
turtle.circle(RADIUS, extent=SLICE_ANGLE)
turtle.home()
turtle.end_poly()
screen.register_shape("wedge", turtle.get_poly())
# create a turtle for each wedge in the pie
turtles = []
for hue in range(NUMBER_OF_WEDGES):
turtle = Turtle("wedge")
turtle.color(hsv_to_rgb(hue / NUMBER_OF_WEDGES, 1.0, 1.0))
turtle.setheading(hue * SLICE_ANGLE)
turtles.append(turtle)
def draw_circle():
# have each turtle take on the color of its neighbor
for index, turtle in enumerate(turtles):
turtle.color(*turtles[(index + 1) % NUMBER_OF_WEDGES].color())
screen.update()
screen.ontimer(draw_circle, 40)
draw_circle()
screen.exitonclick()
Notice how much simpler our main loop, draw_circle(), is and that the spinning doesn't slow down.

Drawing concentric squares

When going through the book "How to think like...", I got stuck with exercise 4.9.2.
The question is: "Write a program to draw this. Assume the innermost square is 20 units per side, and each successive square is 20 units bigger, per side, than the one inside it"
The following code represents how far I got till now:
import turtle
wn = turtle.Screen()
wn.bgcolor("lightgreen")
tess = turtle.Turtle()
def draw_square(t,size):
for i in range(4):
tess.forward(size)
tess.left(90)
size = 20
for j in range(3):
tess.pensize(3)
draw_square(tess,size)
size = size + 20
tess.penup()
tess.goto(-20, -20)
tess.pendown()
wn.mainloop()
Can someone be so kind and show me the right direction please?
Thanks!
Swen
The problem is here:
tess.goto(-20, -20)
You have two issues. First, if each square is 20 units bigger and you offset each square by (-20, -20) all squares would share one corner. Instead you want to offset the corner of the square by (-10, -10) so that the inner square is offset by 10 units on all sides.
The second issue is that .goto(x, y) sets an absolute position, not an offset. To move to an offset you need to calculate a new absolute position based on the offset:
tess.goto(tess.xcor()-10, tess.ycor()-10)
Or
tess.goto(tess.pos() + (-10, -10))
Sometimes when you're stuck, a good approach with turtle graphics is to think outside the square. If we consider the desired result as badly drawn concentric circles then the problem reduces to:
from turtle import Turtle, Screen
HYPOTENUSE = (2 ** 0.5) / 2
screen = Screen()
screen.bgcolor("lightgreen")
tess = Turtle()
tess.pencolor("red")
tess.setheading(45)
tess.width(3)
for radius in range(20, 20 * 5 + 1, 20):
tess.penup()
tess.goto(radius/2, -radius/2)
tess.pendown()
tess.circle(radius * HYPOTENUSE, steps=4)
screen.exitonclick()
OUTPUT
import turtle
def drawSquare (t, size):
for i in range (4):
t.forward(size)
t.left(90)
def main():
wn = turtle.Screen()
wn.bgcolor('black')
pat = turtle.Turtle()
pat.pensize(2)
pat.speed(10)
pat.color('blue')
space = -10
for i in range(20, 105, 20):
drawSquare(pat,i)
pat.up()
pat.goto(space, space)
pat.down()
space = space - 10
wn.exitonclick()
main()
import turtle
def draw_sqr(name,size):
for i in range(4):
name.forward(size)
name.left(90)
name.penup()
name.backward(10)
name.right(90)
name.forward(10)
name.left(90)
name.pendown()
window = turtle.Screen()
window.bgcolor('lightgreen')
window.title("conc_sqr")
x = turtle.Turtle()
x.color('hotpink')
x.pensize(3)
for i in range(5):
draw_sqr(x,20 + 20*i)
window.mainloop()
def draw_rectangle(animal, width, height):
for _ in range(2):
animal.forward(width)
animal.left(90)
animal.forward(height)
animal.left(90)
def draw_square(animal, size):
draw_rectangle(animal, size, size)
def make_window(back_color,title):
window = turtle.Screen()
window.bgcolor(back_color)
window.title(title)
return window
def make_turtle(color, size):
animal = turtle.Turtle()
animal.color(color)
animal.pensize(size)
return animal
import turtle
window = make_window("lightgreen","Squares")
tess = make_turtle("hotpink",3)
size_sqr=20
adjustment = 10
for _ in range(5):
draw_square(tess,size_sqr)
size_sqr += 20
tess.penup()
tess.backward(20/2)
tess.right(90)
tess.forward(20/2)
tess.left(90)
tess.pendown()
import turtle
def drawsquare(t,sz): #(turtle, size)
for i in range(4):
t.fd(sz)
t.right(90)
def main():
wn = turtle.Screen()
your_turtle = turtle.Turtle()
your_turtle.pensize(3)
wn.bgcolor("light green")
your_turtle.pencolor("hot pink")
for i in range(1,6):
drawsquare(your_turtle,20*i)
your_turtle.up()
your_turtle.left(135)
your_turtle.fd(14.142) #the distance between each square
your_turtle.right(135)
your_turtle.down()
main()
wn.exitonclick()

Categories

Resources