地鼠会从洞里随机冒头,你要在它缩回去之前点中它。练到三个核心概念:定时器驱动的事件、随机刷新位置、得分与倒计时。
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 惩罚;③难度随分数提升;④音效;⑤最高分存档。