如何让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()
关键说明
- 线段记录:通过自定义
draw_forward函数,在绘制迷宫的同时将每条线段的起点和终点存入maze_segments列表,为碰撞检测提供数据基础。 - 碰撞检测:
is_colliding函数计算玩家位置到每条线段的最短距离,当距离小于「玩家半径+线条半宽」时判定为碰撞,避免玩家穿越线条。 - 移动逻辑优化:统一的
move_player函数先执行移动,若检测到碰撞或越界则回退到移动前的位置,确保玩家无法穿过迷宫线条。
内容的提问来源于stack exchange,提问作者Caleb Myers
相关产品推荐
相关产品推荐

