You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Python Turtle无法穿越迷宫预设线条实现防作弊?

迷宫游戏:实现Turtle与内部线条的碰撞阻挡

我需要创建一个迷宫游戏,玩家操控Turtle沿唯一路径到达终点,且不能穿越迷宫线条防止作弊。此前尝试设置阻挡线条,虽能起到一定作用,但无法实现类似外围边界的效果——碰到内部线条后不会穿过,同时仍可继续移动完成迷宫,仅针对已绘制的预设线条生效。现有代码如下:

import turtle

# Set up the screen
screen = turtle.Screen()
x_min, y_min = -250, -250
x_max, y_max = 250, 250
screen.setup(600, 600)
screen.bgcolor("white")
screen.title("Labyrinth Game")
screen.bgcolor("darkgoldenrod")
# Draw the maze
pen = turtle.Turtle()
pen.hideturtle()
pen.speed(0)
pen.pensize(5)
pen.color("black")
pen.penup()
pen.goto(-250, 250)
pen.pendown()
pen.forward(500)
pen.right(90)
pen.forward(500)
pen.penup()
pen.right(90)
pen.forward(50)
pen.pendown()
pen.forward(450)
pen.right(90)
pen.forward(500)
pen.right(90)
pen.forward(200)
pen.right(90)
pen.forward(300)
pen.right(90)
pen.forward(50)
pen.penup()
pen.forward(50)
pen.pendown()
pen.forward(100)
pen.penup()
pen.backward(200)
pen.pendown()
pen.left(180)
pen.forward(50)
pen.penup()
pen.forward(50)
pen.pendown()
pen.forward(50)
pen.right(90)
pen.forward(200)
pen.backward(200)
pen.right(180)
pen.forward(200)
pen.backward(50)
pen.left(45)
pen.forward(100)
pen.backward(100)
pen.right(45)
pen.backward(100)
pen.right(135)
pen.forward(100)
pen.penup()
pen.left(45)
pen.forward(78)
pen.right(90)
pen.backward(20)
pen.right(45)
pen.pendown()
pen.forward(100)
pen.penup()
pen.goto(-50,60)
pen.pendown()
pen.left(90)
pen.forward(100)
pen.backward(100)
pen.right(45)
pen.forward(112)
pen.left(45)
pen.forward(140)
pen.right(45)
pen.penup()
pen.forward(99)
pen.pendown()
pen.right(90)
pen.forward(50)
pen.right(45)
pen.forward(140)
pen.right(45)
pen.penup()
pen.forward(100)
pen.pendown()
pen.left(135)
pen.forward(150)
pen.left(90)
pen.forward(75)
pen.left(45)
pen.penup()
pen.forward(403)
pen.pendown()
pen.left(90)
pen.forward(200)
pen.left(45)
pen.forward(100)
pen.left(45)
pen.penup()
pen.forward(75)
pen.pendown()
pen.right(135)
pen.forward(150)
pen.left(45)
pen.penup()
pen.forward(80)
pen.pendown()
pen.left(135)
pen.forward(100)


# Create the player
player = turtle.Turtle()
player.shape("circle")
player.color("grey")
player.penup()
player.speed(0)
player.goto(230,-250) 


# Set up the keyboard controls
def in_bounds(t):
  x, y = player.position()
  return x_min < x < x_max and y_min < y < y_max

def go_up():
  player.setheading(90)
  player.forward(10)
  if not in_bounds(player):
    player.backward(10)

def go_down():
  player.setheading(270)
  player.forward(10)
  if not in_bounds(player):
    player.backward(10)

def go_left():
  player.setheading(180)
  player.forward(10)
  if not in_bounds(player):
    player.backward(10)

def go_right():
  player.setheading(0)
  player.forward(10)
  if not in_bounds(player):
    player.backward(10)

screen.listen()
screen.onkeypress(go_up, "Up")
screen.onkeypress(go_down, "Down")
screen.onkeypress(go_left, "Left")
screen.onkeypress(go_right, "Right")

turtle.done()

解决方案

要实现内部线条的碰撞阻挡,核心是记录所有迷宫线段并检测玩家与线段的距离。以下是修改后的完整代码:

import turtle

# 设置屏幕
screen = turtle.Screen()
x_min, y_min = -250, -250
x_max, y_max = 250, 250
screen.setup(600, 600)
screen.bgcolor("darkgoldenrod")
screen.title("Labyrinth Game")

# 存储迷宫所有线段,每个元素为((起点x,起点y), (终点x,终点y))
maze_segments = []

# 创建画笔
pen = turtle.Turtle()
pen.hideturtle()
pen.speed(0)
pen.pensize(5)
pen.color("black")
pen.penup()
pen.goto(-250, 250)
pen.pendown()

# 自定义前进绘制函数,同时记录线段
def draw_forward(distance):
    start_pos = pen.position()
    pen.forward(distance)
    end_pos = pen.position()
    maze_segments.append((start_pos, end_pos))

# 重新绘制迷宫,用自定义函数记录每条线段
draw_forward(500)
pen.right(90)
draw_forward(500)
pen.penup()
pen.right(90)
pen.forward(50)
pen.pendown()
draw_forward(450)
pen.right(90)
draw_forward(500)
pen.right(90)
draw_forward(200)
pen.right(90)
draw_forward(300)
pen.right(90)
draw_forward(50)
pen.penup()
pen.forward(50)
pen.pendown()
draw_forward(100)
pen.penup()
pen.backward(200)
pen.pendown()
pen.left(180)
draw_forward(50)
pen.penup()
pen.forward(50)
pen.pendown()
draw_forward(50)
pen.right(90)
draw_forward(200)
pen.backward(200)
pen.right(180)
draw_forward(200)
pen.backward(50)
pen.left(45)
draw_forward(100)
pen.backward(100)
pen.right(45)
pen.backward(100)
pen.right(135)
draw_forward(100)
pen.penup()
pen.left(45)
pen.forward(78)
pen.right(90)
pen.backward(20)
pen.right(45)
pen.pendown()
draw_forward(100)
pen.penup()
pen.goto(-50,60)
pen.pendown()
pen.left(90)
draw_forward(100)
pen.backward(100)
pen.right(45)
draw_forward(112)
pen.left(45)
draw_forward(140)
pen.right(45)
pen.penup()
pen.forward(99)
pen.pendown()
pen.right(90)
draw_forward(50)
pen.right(45)
draw_forward(140)
pen.right(45)
pen.penup()
pen.forward(100)
pen.pendown()
pen.left(135)
draw_forward(150)
pen.left(90)
draw_forward(75)
pen.left(45)
pen.penup()
pen.forward(403)
pen.pendown()
pen.left(90)
draw_forward(200)
pen.left(45)
draw_forward(100)
pen.left(45)
pen.penup()
pen.forward(75)
pen.pendown()
pen.right(135)
draw_forward(150)
pen.left(45)
pen.penup()
pen.forward(80)
pen.pendown()
pen.left(135)
draw_forward(100)

# 创建玩家
player = turtle.Turtle()
player.shape("circle")
player.color("grey")
player.penup()
player.speed(0)
player.goto(230,-250)

# 碰撞检测:判断玩家位置是否与迷宫线条碰撞
def is_colliding(x, y):
    player_radius = 10  # 圆形玩家的半径
    line_half_width = pen.pensize() / 2  # 线条宽度的一半
    collision_threshold = player_radius + line_half_width

    for (start, end) in maze_segments:
        x1, y1 = start
        x2, y2 = end

        # 计算点到线段的最短距离
        dx = x2 - x1
        dy = y2 - y1
        if dx == 0 and dy == 0:
            # 线段为单点,直接计算欧氏距离
            distance = ((x - x1)**2 + (y - y1)**2)**0.5
        else:
            # 投影点在线段内则取投影距离,否则取端点距离
            t = ((x - x1)*dx + (y - y1)*dy) / (dx**2 + dy**2)
            t = max(0, min(1, t))
            closest_x = x1 + t * dx
            closest_y = y1 + t * dy
            distance = ((x - closest_x)**2 + (y - closest_y)**2)**0.5

        if distance < collision_threshold:
            return True
    return False

# 边界检测
def in_bounds(t):
    x, y = t.position()
    return x_min < x < x_max and y_min < y < y_max

# 统一移动逻辑
def move_player(direction):
    player.setheading(direction)
    prev_x, prev_y = player.position()
    player.forward(10)
    new_x, new_y = player.position()
    # 检测边界和碰撞,不符合则回退
    if not in_bounds(player) or is_colliding(new_x, new_y):
        player.goto(prev_x, prev_y)

# 方向控制函数
def go_up():
    move_player(90)

def go_down():
    move_player(270)

def go_left():
    move_player(180)

def go_right():
    move_player(0)

# 绑定键盘事件
screen.listen()
screen.onkeypress(go_up, "Up")
screen.onkeypress(go_down, "Down")
screen.onkeypress(go_left, "Left")
screen.onkeypress(go_right, "Right")

turtle.done()

关键说明

  1. 线段记录:通过自定义draw_forward函数,在绘制迷宫的同时将每条线段的起点和终点存入maze_segments列表,为碰撞检测提供数据基础。
  2. 碰撞检测:is_colliding函数计算玩家位置到每条线段的最短距离,当距离小于「玩家半径+线条半宽」时判定为碰撞,避免玩家穿越线条。
  3. 移动逻辑优化:统一的move_player函数先执行移动,若检测到碰撞或越界则回退到移动前的位置,确保玩家无法穿过迷宫线条。

内容的提问来源于stack exchange,提问作者Caleb Myers

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 10:52:03