【问题标题】:Understanding snake game extension logic了解贪吃蛇游戏扩展逻辑
【发布时间】:2022-12-05 05:57:47
【问题描述】:

有一个“扩展”功能按预期运行,但我不明白如何。代码的编写者使用 -1 作为项目在列表“段”中的位置。这不应该在其最后一段的位置向已创建的蛇添加额外的元素吗?如果是这样,那将如何延长蛇,因为最后创建的段将与已经存在的段重叠?相关文件的完整代码在文末说明。

def extend(self):
        self.add_segment(self.segments[-1].position())

main.py 的代码如下:

from turtle import Screen
from snake import Snake
from food import Food
from scoreboard import ScoreBoard
import time

screen = Screen()
screen.setup(width=600, height=600)
screen.bgcolor("black")
screen.title("My Snake Game")
screen.tracer()

scoreboard = ScoreBoard()
snake = Snake()
food = Food()

screen.listen()
screen.onkey(snake.up, "Up")
screen.onkey(snake.down, "Down")
screen.onkey(snake.left, "Left")
screen.onkey(snake.right, "Right")

game_is_on = True

while game_is_on:
    screen.update()

    snake.move()

    if snake.head.distance(food) < 15:
        food.refresh()
        scoreboard.increase_score()
        snake.extend()

    #Detect collision with wall
    if snake.head.xcor() > 280 or snake.head.xcor() < -280 or snake.head.ycor() > 280 or snake.head.ycor() < -280:
        game_is_on = False
        scoreboard.game_over()

    #Detect collision with tail
    for segment in snake.segments:
        if segment == snake.head:
            pass
        elif snake.head.position() == segment.position():
            game_is_on = False
            scoreboard.game_over()

screen.exitonclick()

snake.py 的代码如下:

from turtle import Turtle

STARTING_POSITIONS = [(0, 0), (-20, 0), (-40, 0)]
MOVE_DISTANCE = 20
UP = 90
DOWN = 270
LEFT = 180
RIGHT = 0

class Snake:

    def __init__(self):
        self.segments = []
        self.create_snake()
        self.head = self.segments[0]

    def create_snake(self):
        for position in STARTING_POSITIONS:
            self.add_segment(position)

    def add_segment(self, position):
        new_segment = Turtle("square")
        new_segment.color("white")
        new_segment.penup()
        new_segment.goto(position)
        self.segments.append(new_segment)

    ################
    def extend(self):
        self.add_segment(self.segments[-1].position())
    ################

    def move(self):
        for seg_num in range(len(self.segments) - 1, 0, -1):
            new_x = self.segments[seg_num - 1].xcor()
            new_y = self.segments[seg_num - 1].ycor()
            self.segments[seg_num].goto(new_x, new_y)
        self.segments[0].forward(MOVE_DISTANCE)

    def up(self):
        if self.head.heading() != DOWN:
            self.head.setheading(UP)

    def down(self):
        if self.head.heading() != UP:
            self.head.setheading(DOWN)

    def left(self):
        if self.head.heading() != RIGHT:
            self.head.setheading(LEFT)

    def right(self):
        if self.head.heading() != LEFT:
            self.head.setheading(RIGHT)

【问题讨论】:

    标签: python turtle-graphics python-turtle


    【解决方案1】:

    这不应该在其最后一段的位置向已创建的蛇添加额外的元素吗?如果是这样,那将如何延长蛇,因为最后创建的段将与已经存在的段重叠?

    一个好问题:直觉上,它似乎应该如此。但是检查移动代码:

    def move(self):
        for seg_num in range(len(self.segments) - 1, 0, -1):
            new_x = self.segments[seg_num - 1].xcor()
            new_y = self.segments[seg_num - 1].ycor()
            self.segments[seg_num].goto(new_x, new_y)
        self.segments[0].forward(MOVE_DISTANCE)
    

    这会从尾部到头部迭代蛇段,将每个段移动到它前面的段的位置,然后最后将头部向蛇前进的任何方向向前移动一步。

    很明显,这在正常运动下工作正常。蛇的尾巴将腾出其先前的位置,并且没有任何东西可以填充它,留下一个空白空间,而头部将占据一个新的、以前是空白的空间。这是一个正常的 move 调用示例,长度为 5 的蛇向右移动一步:

    4 3 2 1 H
    -------->
    
      4 3 2 1 H
    ^
    |
    empty
    

    现在,在调用 extend 之后,我们得到了这个看似无效的情况(想象一下,两个 4 在 1-d 轴上共享完全相同的正方形/位置,而不是在其上方垂直放置一个正方形):

    4
    4 3 2 1 H
    -------->
    

    但是下一个 move 调用就很好地解决了这种情况。即使有两个 4 共享同一个位置,蛇也会在向右移动一格后如下移动:

    4 4 3 2 1 H
    ^
    |
    filled in by new segment
    

    虽然我仍然使用 4,但它确实是第 5 个尾段,具有其独特的位置:

    5 4 3 2 1 H
    ^
    |
    filled in by new segment
    

    蛇已经向右移动了,但最后一个元素自然落到了位,因为它被分配到它前面的段所占据的坐标空间,self.segments[seg_num - 1],在正常移动下它会留空。

    这个空白空间正是第 length - 2 元素的先前位置,而这正是 extend 设置的新(看似)重复的尾元素。

    简明扼要地总结一下:

    • 在正常运动下,没有段分配给尾部的旧位置,留下空白空间。
    • 在蛇长大时调用extend后,复制的尾巴被分配到旧尾巴本应腾出的空白空间,并填充它。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多