地鼠会从洞里随机冒头,你要在它缩回去之前点中它。练到三个核心概念:定时器驱动的事件、随机刷新位置、得分与倒计时。

1. 地鼠的"冒头"与"缩回"

地鼠用一个时间戳管理:到时间了冒头,再过一个时间窗口缩回去。用 pygame.time.get_ticks() 记录毫秒时间:

import random, pygame

HOLES = 9            # 3x3 个洞
up_until = [0] * HOLES          # 每个洞的"缩回时间"
next_up = 0                     # 下一次冒头时间

def update(now):
    global next_up
    if now >= next_up:                       # 到点冒头
        i = random.randrange(HOLES)
        up_until[i] = now + random.randint(800, 1400)
        next_up = now + random.randint(400, 900)
    for i in range(HOLES):                   # 到点缩回
        if now >= up_until[i]:
            up_until[i] = 0

2. 点击判定与得分

鼠标点击时,判断点中的洞里有没有地鼠(该洞未到缩回时间)。打中 +1 并立即缩回,防止连点刷分:

def on_click(pos, now):
    global score
    i = hole_at(pos)          # 像素坐标 -> 洞编号
    if i is None or now >= up_until[i] or up_until[i] == 0:
        return
    score += 1
    up_until[i] = 0           # 打中就缩回

3. 倒计时与结束

开局 30 秒倒计时,时间到显示成绩。倒计时同样用 get_ticks() 算,不用单独线程:

START = 30000          # 30 秒(毫秒)
start_time = pygame.time.get_ticks()
game_over = False

while not game_over:
    now = pygame.time.get_ticks()
    if now - start_time >= START:
        game_over = True
        print('时间到!得分:', score)
        break

4. 完整代码

import random, pygame

W, H = 480, 520
pygame.init()
screen = pygame.display.set_mode((W, H))
clock = pygame.time.Clock()
font = pygame.font.SysFont('simhei', 30)

HOLES = 9
CELL = 120
OX, OY = 60, 60           # 第一行洞的左上角
up_until = [0] * HOLES
next_up = 0
score = 0
START = 30000
start_time = pygame.time.get_ticks()
game_over = False

def hole_rect(i):
    r, c = divmod(i, 3)
    return (OX + c * CELL, OY + r * CELL, CELL - 10, CELL - 10)

def hole_at(pos):
    mx, my = pos
    for i in range(HOLES):
        x, y, w, h = hole_rect(i)
        if x <= mx <= x + w and y <= my <= y + h:
            return i
    return None

def update(now):
    global next_up
    if now >= next_up:
        i = random.randrange(HOLES)
        up_until[i] = now + random.randint(800, 1400)
        next_up = now + random.randint(400, 900)
    for i in range(HOLES):
        if now >= up_until[i]:
            up_until[i] = 0

def draw(now):
    screen.fill((60, 120, 60))
    for i in range(HOLES):
        x, y, w, h = hole_rect(i)
        pygame.draw.ellipse(screen, (90, 70, 40), (x, y + h // 2, w, h // 2))
        if up_until[i] > now:
            pygame.draw.circle(screen, (160, 110, 70), (x + w // 2, y + h // 2 - 10), 26)
            pygame.draw.circle(screen, (20, 20, 20), (x + w // 2 - 10, y + h // 2 - 14), 4)
            pygame.draw.circle(screen, (20, 20, 20), (x + w // 2 + 10, y + h // 2 - 14), 4)
    left = max(0, (START - (now - start_time)) // 1000)
    screen.blit(font.render('时间: %ds  得分: %d' % (left, score), True, (255, 255, 255)), (20, 470))
    pygame.display.flip()

while not game_over:
    now = pygame.time.get_ticks()
    if now - start_time >= START:
        game_over = True
        break
    for e in pygame.event.get():
        if e.type == pygame.QUIT:
            pygame.quit(); raise SystemExit
        if e.type == pygame.MOUSEBUTTONDOWN and e.button == 1:
            i = hole_at(e.pos)
            if i is not None and up_until[i] > now:
                score += 1
                up_until[i] = 0
    update(now)
    draw(now)
    clock.tick(30)
print('时间到!得分:', score)

5. 运行与常见问题

保存为 whack.py,python3 whack.py 运行。常见问题:①地鼠不冒头——检查 next_up 是否在每次循环里被更新;②打中没加分——确认点击坐标换算到洞编号正确,且该洞真的"有地鼠";③节奏太慢——把冒头间隔调短。

💡 改进方向:①地鼠出现动画(上下浮动);②连击奖励与 MISS 惩罚;③难度随分数提升;④音效;⑤最高分存档。