编写打地鼠游戏时当前地鼠不响应按键

3 投票
1 回答
58 浏览
提问于 2025-04-14 17:33

我正在做一个打地鼠游戏的作业。程序运行得很好,可以随机生成一个地鼠在方块之间跳来跳去。地鼠应该用数字键盘来打,比如左上角是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

这里有很多内容(我一般建议把你的问题代码简化一下,以便更好地找到问题),但根本问题在于在海龟程序中使用了 whilesleep。通常来说,这两者都不太适合。实现循环和事件的常用工具是 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()

撰写回答