Python 挑战版 · Day 9
倒计时与 Game Over:给游戏加压力
从“收集宝石”升级成“限时收集宝石”:学生不仅写倒计时,还要理解状态开关如何控制规则。
节奏分配(45 分钟)
01
复习并制造问题
收集宝石能一直玩,所以缺少压力。引出限时挑战。
02
演示倒计时版本
先看 Time 30、29、28,到 0 后 Game Over。
03
加入状态变量
time_left 负责时间,game_over 负责游戏是否结束。
04
刷新信息栏
show_info 同时显示 score 和 time_left。
05
ontimer 自动调用
让 update_time 每隔 1000 毫秒再次执行。
06
结束规则
time_left 到 0 时切换 game_over,并禁止移动和得分。
07
分层改造
调整秒数、最后 5 秒变红、显示最终分数。
教师话术
"限时不是装饰,它改变了玩家的行为:玩家会更快、更紧张。"
"ontimer(update_time, 1000) 的意思是:1000 毫秒后调用 update_time。"
"game_over 是状态变量。移动函数先检查状态,再决定能不能动。"
"如果结束后还能得分,说明有一条路径没有检查 game_over。"
计时器知识卡
time_left还剩多少秒,是会被 update_time 改变的变量。
screen.ontimer(fn, 1000)1000 毫秒后调用 fn 一次。想持续倒计时,就在函数里再次安排下一次。
game_over游戏结束开关,用来统一控制移动和得分。
not game_over只有游戏没有结束时,才允许移动、收集和加分。
关键代码
计时器核心
time_left = 30
game_over = False
def update_time():
global time_left, game_over
if time_left > 0:
time_left = time_left - 1
show_info()
screen.ontimer(update_time, 1000)
else:
game_over = True
show_game_over()移动前检查 game_over
def move_up():
if not game_over and player.ycor() < top_edge:
player.sety(player.ycor() + step)
collect_gem()完整版本
import turtle
import random
screen = turtle.Screen()
screen.title("第 9 课:限时收集宝石")
screen.setup(700, 500)
screen.bgcolor("lightcyan")
player = turtle.Turtle()
player.shape("turtle")
player.color("green")
player.penup()
player.goto(0, 0)
gem = turtle.Turtle()
gem.shape("circle")
gem.color("gold")
gem.penup()
gem.shapesize(0.8)
score = 0
time_left = 30
game_over = False
step = 20
left_edge = -320
right_edge = 320
top_edge = 220
bottom_edge = -220
pen = turtle.Turtle()
pen.hideturtle()
pen.penup()
def move_gem():
gem.goto(random.randint(-280, 280), random.randint(-180, 180))
def show_info():
pen.clear()
pen.goto(-310, 210)
if time_left <= 5:
pen.color("red")
else:
pen.color("black")
pen.write(f"分数: {score} 时间: {time_left}", font=("Arial", 16, "bold"))
def show_game_over():
pen.clear()
pen.goto(0, 20)
pen.color("red")
pen.write("Game Over", align="center", font=("Arial", 36, "bold"))
pen.goto(0, -30)
pen.color("black")
pen.write(f"最终分数: {score}", align="center", font=("Arial", 18, "normal"))
def update_time():
global time_left, game_over
if time_left > 0:
time_left = time_left - 1
show_info()
screen.ontimer(update_time, 1000)
else:
game_over = True
show_game_over()
def collect_gem():
global score
if not game_over and player.distance(gem) < 25:
score = score + 1
move_gem()
show_info()
def move_up():
if not game_over and player.ycor() < top_edge:
player.sety(player.ycor() + step)
collect_gem()
def move_down():
if not game_over and player.ycor() > bottom_edge:
player.sety(player.ycor() - step)
collect_gem()
def move_left():
if not game_over and player.xcor() > left_edge:
player.setx(player.xcor() - step)
collect_gem()
def move_right():
if not game_over and player.xcor() < right_edge:
player.setx(player.xcor() + step)
collect_gem()
move_gem()
show_info()
update_time()
screen.listen()
screen.onkey(move_up, "Up")
screen.onkey(move_down, "Down")
screen.onkey(move_left, "Left")
screen.onkey(move_right, "Right")
turtle.done()分层挑战
基础
把倒计时改成 20 秒或 10 秒,并解释难度变化。
进阶
最后 5 秒把时间文字变红。
挑战
显示最终分数,或让每收集 3 个宝石加 3 秒。
完成标准
能解释 ontimer 的两个参数分别是什么。
能说明 time_left 和 game_over 各自负责什么。
能确认时间到 0 后不能移动、不能继续得分。
能做一个限时规则改造,并解释它如何改变游戏体验。
排查 bug 时按路径查:移动函数、收集函数、计时函数都需要尊重 game_over。
收尾问题
如果只有奖励没有危险,好玩吗?下一步可以加入敌人:碰到敌人就提前 Game Over。
模块目录
Python 启蒙