编写打地鼠游戏时当前地鼠不响应按键
我正在做一个打地鼠游戏的作业。程序运行得很好,可以随机生成一个地鼠在方块之间跳来跳去。地鼠应该用数字键盘来打,比如左上角是7,依此类推。
不过,每次游戏的时候,它都告诉我我打不中。经过实验,我发现如果我预测地鼠会去哪里,我就能打到它,这说明它在下一轮才进行比较。那我该怎么做呢?
import turtle
import random
import time
t = turtle.Turtle()
t.hideturtle()
mole_x, mole_y = 0, 0
# Set up screen
wn = turtle.Screen()
wn.title("Whack-A-Mole")
wn.bgcolor("green")
wn.setup(width=600, height=600)
wn.tracer(0)
# Draws a square with top-left position (x,y) and side length size
def drawsq(x, y, size):
t.penup()
t.goto(x, y)
t.pendown()
for i in range(4):
t.forward(size)
t.right(90)
t.penup()
# Draw a circle at center (x,y) with radius r
def drawcr(x, y, r):
t.penup()
t.goto(x, y - r)
t.pendown()
t.circle(r)
def molecoords():
coords = [-150, 0, 150]
x = random.choice(coords)
y = random.choice(coords)
return x, y
#Draws the mole
def draw_mole(x, y):
drawcr(x, y, 50) # Body
drawcr(x - 40, y - 40, 7) # Left foot
drawcr(x + 40, y - 40, 7) # Right foot
drawcr(x - 55, y + 15, 7) # Left hand
drawcr(x + 55, y + 15, 7) # Right hand
t.penup() # Head
t.goto(x - 45, y + 20)
t.setheading(-50)
t.pendown()
t.circle(60, 100)
t.setheading(0)
drawcr(x - 10, y + 35, 2) # Left eye
drawcr(x + 10, y + 35, 2) # Right eye
drawgrid(x - 7, y + 20, 2, 1, 7) # Teeth
t.goto(x, y + 22) # Nose
t.fillcolor("black") # Set the fill color
t.begin_fill() # Begin filling
t.pendown()
t.left(60)
t.forward(5)
t.left(120)
t.forward(5)
t.left(120)
t.forward(5)
t.end_fill()
t.setheading(0)
# Draw a grid with x rows and y columns with squares of side length size starting at (tlx,tly)
def drawgrid(tlx, tly, x, y, size):
for i in range(x):
for j in range(y):
drawsq(tlx + (i * size), tly - j * size, size)
def check_hit(key):
target_positions = {
'1': (-150, -150),
'2': (0, -150),
'3': (150, -150),
'4': (-150, 0),
'5': (0, 0),
'6': (150, 0),
'7': (-150, 150),
'8': (0, 150),
'9': (150, 150)
}
target_x, target_y = target_positions.get(key)
if (mole_x, mole_y) == (target_x, target_y):
print("Hit!")
else:
print("Miss!")
def on_key_press(key):
check_hit(key)
def game_loop():
global mole_x, mole_y
start = time.time()
duration = 30
while time.time() - start < duration:
t.clear()
drawgrid(-225, 225, 3, 3, 150)
mole_x, mole_y = molecoords()
draw_mole(mole_x, mole_y)
wn.update()
time.sleep(2)
# Bind key press events
wn.listen()
wn.onkeypress(lambda: on_key_press('1'), '1')
wn.onkeypress(lambda: on_key_press('2'), '2')
wn.onkeypress(lambda: on_key_press('3'), '3')
wn.onkeypress(lambda: on_key_press('4'), '4')
wn.onkeypress(lambda: on_key_press('5'), '5')
wn.onkeypress(lambda: on_key_press('6'), '6')
wn.onkeypress(lambda: on_key_press('7'), '7')
wn.onkeypress(lambda: on_key_press('8'), '8')
wn.onkeypress(lambda: on_key_press('9'), '9')
game_loop()
def gameover():
t.penup()
wn.clear()
wn.bgcolor("black")
t.goto(0, 100)
t.pencolor("White")
t.write("Time's Up!", align="center", font=("Arial", 80, "bold"))
gameover()
turtle.done()
它能正确读取输入,但没有在正确的时间应用这些输入。
1 个回答
1
这里有很多内容(我一般建议把你的问题代码简化一下,以便更好地找到问题),但根本问题在于在海龟程序中使用了 while
和 sleep
。通常来说,这两者都不太适合。实现循环和事件的常用工具是 Screen().ontimer()
。
这里有一个部分重写的代码,清理了一些内容(使用了基本的文档字符串,去掉了一些重复的部分),并稍微重新组织了一下代码,以适应 ontimer
的设计。还有很多可以改进的地方,留给你自己去练习。
import random
from turtle import Screen, Turtle
def draw_square(x, y, size):
"""Draws a square with top-left position (x,y) and side length size"""
t.penup()
t.goto(x, y)
t.pendown()
for i in range(4):
t.forward(size)
t.right(90)
t.penup()
def draw_circle(x, y, r):
"""Draw a circle at center (x,y) with radius r"""
t.penup()
t.goto(x, y - r)
t.pendown()
t.circle(r)
def new_mole_position():
"""Chooses random mole coordinates"""
coords = [-150, 0, 150]
x = random.choice(coords)
y = random.choice(coords)
return x, y
def draw_mole(x, y):
"""Draws the mole at (x, y)"""
draw_circle(x, y, 50) # Body
draw_circle(x - 40, y - 40, 7) # Left foot
draw_circle(x + 40, y - 40, 7) # Right foot
draw_circle(x - 55, y + 15, 7) # Left hand
draw_circle(x + 55, y + 15, 7) # Right hand
t.penup() # Head
t.goto(x - 45, y + 20)
t.setheading(-50)
t.pendown()
t.circle(60, 100)
t.setheading(0)
draw_circle(x - 10, y + 35, 2) # Left eye
draw_circle(x + 10, y + 35, 2) # Right eye
draw_grid(x - 7, y + 20, 2, 1, 7) # Teeth
t.goto(x, y + 22) # Nose
t.fillcolor("black") # Set the fill color
t.begin_fill() # Begin filling
t.pendown()
t.left(60)
t.forward(5)
t.left(120)
t.forward(5)
t.left(120)
t.forward(5)
t.end_fill()
t.setheading(0)
def draw_grid(tlx, tly, x, y, size):
"""
Draws a grid with x rows and y columns with
squares of side length size starting at (tlx,tly)
"""
for i in range(x):
for j in range(y):
draw_square(tlx + (i * size), tly - j * size, size)
def check_hit(key):
"""Determines whether a key corresponds to the mole"s location"""
target_positions = {
"1": (-150, -150),
"2": (0, -150),
"3": (150, -150),
"4": (-150, 0),
"5": (0, 0),
"6": (150, 0),
"7": (-150, 150),
"8": (0, 150),
"9": (150, 150)
}
target_x, target_y = target_positions.get(key)
if (mole_x, mole_y) == (target_x, target_y):
print("Hit!")
else:
print("Miss!")
def move_mole():
"""
Moves the mole and triggers the next mole move
if the timer hasn"t expired
"""
global mole_x, mole_y
if game_over:
return
mole_x, mole_y = new_mole_position()
t.clear()
draw_grid(-225, 225, 3, 3, 150)
draw_mole(mole_x, mole_y)
wn.update()
wn.ontimer(move_mole, 2000)
def end_game():
"""Ends the game"""
global game_over
game_over = True
t.penup()
wn.clear()
wn.bgcolor("black")
t.goto(0, 100)
t.pencolor("White")
t.write("Time's Up!", align="center", font=("Arial", 20, "bold"))
def bind_key(k):
"""Bind key k to check hit on the corresponding square"""
wn.onkeypress(lambda: check_hit(k), k)
t = Turtle()
t.hideturtle()
mole_x, mole_y = 0, 0
# Set up screen
wn = Screen()
wn.tracer(0)
wn.title("Whack-A-Mole")
wn.bgcolor("green")
wn.setup(width=600, height=600)
# Bind key press events
wn.listen()
for i in range(1, 10):
bind_key(str(i))
duration = 30
game_over = False
wn.ontimer(end_game, duration * 1000)
move_mole()
wn.exitonclick()