Python 挑战版 · Day 10

敌人与危险规则:让游戏更刺激

在限时收集宝石上加入敌人,形成“奖励 + 危险 + 时间压力”的完整规则雏形。

节奏分配(45 分钟)

01

承接 Day 9

限时规则已经有压力,但只有奖励,没有危险。

02

定义危险

让学生说出:敌人应该出现在哪里、碰到会怎样。

03

创建 enemy

把 enemy 当成第三个 turtle 角色:player、gem、enemy。

04

敌人随机出现

用 ontimer 重复调用 move_enemy,注意 game_over 时停止。

05

复用碰撞检测

宝石和敌人都用 distance,但对应不同后果。

06

整合结束原因

Game Over 可能来自时间到,也可能来自碰到敌人。

07

调参和扩展

调整敌人速度、碰撞半径,或增加第二个敌人。

教师话术

"只有奖励会让游戏变简单;危险会改变玩家的路线选择。"

"player、gem、enemy 都是 turtle。不同角色只是承担不同规则。"

"同一个 distance 判断,碰宝石是奖励,碰敌人是惩罚。"

"如果 Game Over 后敌人还在动,说明 move_enemy 没有检查 game_over。"

危险机制知识卡

enemy_interval

敌人每隔多久换位置。数字越小,敌人越频繁出现。

player.distance(enemy)

判断玩家和敌人是不是靠得太近。

show_game_over(reason)

把结束原因传进去:时间到或碰到敌人。

if game_over: return

游戏结束后,不再移动敌人,也不再继续倒计时。

关键代码

敌人核心

python
enemy = turtle.Turtle()
enemy.shape("circle")
enemy.color("black")
enemy.penup()
enemy.shapesize(1.2)
 
def move_enemy():
    if game_over:
        return
 
    enemy.goto(random.randint(-280, 280), random.randint(-180, 180))
    screen.ontimer(move_enemy, enemy_interval)

奖励和危险整合

python
def check_hit():
    global score, game_over
 
    if game_over:
        return
 
    if player.distance(gem) < 25:
        score = score + 1
        move_gem()
        show_info()
 
    if player.distance(enemy) < 30:
        game_over = True
        show_game_over("碰到敌人!")

完整版本

python
import turtle
import random
 
screen = turtle.Screen()
screen.title("第 10 课:限时收集宝石 + 敌人")
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)
 
enemy = turtle.Turtle()
enemy.shape("circle")
enemy.color("black")
enemy.penup()
enemy.shapesize(1.2)
 
score = 0
time_left = 30
game_over = False
step = 20
enemy_interval = 1200
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)
    pen.color("black")
    pen.write(f"分数: {score}  时间: {time_left}", font=("Arial", 16, "bold"))
 
def show_game_over(reason):
    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"{reason} 最终分数: {score}", align="center", font=("Arial", 18, "normal"))
 
def update_time():
    global time_left, game_over
 
    if game_over:
        return
 
    if time_left > 0:
        time_left = time_left - 1
        show_info()
        screen.ontimer(update_time, 1000)
    else:
        game_over = True
        show_game_over("时间到!")
 
def move_enemy():
    if game_over:
        return
 
    enemy.goto(random.randint(-280, 280), random.randint(-180, 180))
    screen.ontimer(move_enemy, enemy_interval)
 
def check_hit():
    global score, game_over
 
    if game_over:
        return
 
    if player.distance(gem) < 25:
        score = score + 1
        move_gem()
        show_info()
 
    if player.distance(enemy) < 30:
        game_over = True
        show_game_over("碰到敌人!")
 
def move_up():
    if not game_over and player.ycor() < top_edge:
        player.sety(player.ycor() + step)
        check_hit()
 
def move_down():
    if not game_over and player.ycor() > bottom_edge:
        player.sety(player.ycor() - step)
        check_hit()
 
def move_left():
    if not game_over and player.xcor() > left_edge:
        player.setx(player.xcor() - step)
        check_hit()
 
def move_right():
    if not game_over and player.xcor() < right_edge:
        player.setx(player.xcor() + step)
        check_hit()
 
move_gem()
move_enemy()
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()

分层挑战

基础

把敌人改成红色,调整碰撞距离。

进阶

把 enemy_interval 从 1200 改成 700,解释难度变化。

挑战

增加 enemy2,复用同一套碰撞判断。

完成标准

能解释三个角色:玩家、宝石、敌人。

能说明同一个 distance 为什么会产生不同结果。

能确认时间到和碰敌人都会结束游戏。

能通过参数调整敌人威胁感。

如果学生觉得不刺激,先调敌人出现频率和碰撞半径,不要急着加复杂追踪算法。

收尾问题

你现在可以设计奖励,也可以设计惩罚。下一课换一种游戏结构:接住从天上掉下来的东西。