慢python程序

问题描述

我试图通过使用乌龟来制作这个蛇游戏(还没有食物)。长度为 1 时,它仍然很快,但随着时间的推移,它运行得越来越慢。

from turtle import Turtle,Screen

SIZE = 500
GRID_NUM = 20
GRID_SIZE = SIZE // GRID_NUM

screen = Screen()
screen.setup(SIZE,SIZE)
screen.bgcolor('black')
screen.setworldcoordinates(10,8,SIZE + 2,SIZE)

class Snake:
  def __init__(self):
    self.head = init_turtle()
    self.head.setpos((GRID_SIZE // 2 + GRID_SIZE * 9,GRID_SIZE // 2 + GRID_SIZE * 10))
    self.body = []
    self.direction = 0 # 0 = left,1 = up,2 = right,3 = down
    self.speed = 100 * len(self.body) if len(self.body) > 0 else 100

  def levelup(self):
    if len(self.body) == 0:
      self.body.append(self.head.clone())
    else:
      self.body.append(self.body[len(self.body) - 1].clone())
    
  def update(self):
    for i in range(len(self.body) - 1,-1,-1):
      if i == 0:
        self.body[i].setpos(self.head.pos())
      else:
        self.body[i].setpos(self.body[i - 1].pos())
  

def init_turtle():
  turtle = Turtle()
  turtle.shape('square')
  turtle.shapesize(1.25)
  turtle.color('red')
  turtle.pencolor('#404040')
  turtle.speed('fastest')
  turtle.up()
  return turtle
def init_border():
  def border():
    turtle = init_turtle()
    for _ in range(4):
      turtle.down()
      turtle.forward(SIZE)
      turtle.left(90)
      yield(0)
    turtle.penup()
    turtle.hideturtle()

  def horizontal():
    turtle = init_turtle()
    for x in range(GRID_SIZE,SIZE,GRID_SIZE):
      turtle.goto(x,0)
      turtle.pendown()
      turtle.goto(x,SIZE)
      turtle.penup()
      yield(0)
    turtle.hideturtle()

  def vertical():
    turtle = init_turtle()
    for y in range(GRID_SIZE,GRID_SIZE):
      turtle.goto(0,y)
      turtle.pendown()
      turtle.goto(SIZE,y)
      turtle.penup()
      yield(0)
    turtle.hideturtle()

  generator1 = border()
  generator2 = horizontal()
  generator3 = vertical()
  while(next(generator1,1) + next(generator2,1) + next(generator3,1) < 3):
    pass

def start_game():
  snake = Snake()

  def pop():
    snake.body.pop()
  def right():
    snake.direction = 0
  def up():
    snake.direction = 1
  def left():
    snake.direction = 2
  def down():
    snake.direction = 3
  def exit():
    screen.bye()

  screen.onkey(pop,'q')
  screen.onkey(left,'Left')
  screen.onkey(up,'Up')
  screen.onkey(right,'Right')
  screen.onkey(down,'Down')
  screen.onkey(exit,'Escape')
  screen.onkey(snake.levelup,'Return')
  screen.listen()

  while True:
    snake.update()
    snake.head.setheading(snake.direction * 90)
    snake.head.forward(GRID_SIZE)
    print('snake',snake.head.pos())


init_border()
start_game()
screen.mainloop()

起初我认为问题的原因是定义了很多功能,但我不知道。另外我是python的新手,所以我不知道任何类型的优化方法

有什么优化这个程序的想法吗?

解决方法

我们可以通过在屏幕外绘制并发送显式更新来加速长蛇。下面是您的代码的返工,它只是这样做,并包括一个临时补丁,使蛇在一个正方形中移动,因此您只需点击即可查看蛇受其他身体部位的影响:

from turtle import Turtle,Screen

SIZE = 525
GRID_NUM = 20
GRID_SIZE = SIZE // GRID_NUM

RIGHT,UP,LEFT,DOWN = range(4)

class Snake:
    def __init__(self):
        self.head = init_turtle()
        self.head.setpos(GRID_NUM//2,GRID_NUM//2)
        self.direction = LEFT
        self.body = []

    def levelup(self):
        if self.body:
            self.body.append(self.body[-1].clone())
        else:
                self.body.append(self.head.clone())

    def update(self):
        for i in range(len(self.body) - 1,-1,-1):
            if i == 0:
                self.body[i].setposition(self.head.position())
            else:
                self.body[i].setposition(self.body[i - 1].position())

def init_turtle():
    turtle = Turtle()
    turtle.shape('square')
    print(GRID_SIZE)
    turtle.shapesize((GRID_SIZE - 1) / 20)
    turtle.color('#404040','red')
    turtle.speed('fastest')
    turtle.penup()

    return turtle

def init_border():
    def border():
        turtle = init_turtle()

        turtle.goto(-0.5,-0.5)

        for _ in range(4):
            turtle.pendown()
            turtle.forward(GRID_NUM)
            turtle.left(90)

        turtle.penup()
        turtle.hideturtle()

    def vertical():
        turtle = init_turtle()

        for x in range(GRID_NUM):
            turtle.goto(x - 0.5,-0.5)
            turtle.pendown()
            turtle.goto(x - 0.5,GRID_NUM - 0.5)
            turtle.penup()
            yield 0

        turtle.hideturtle()

    def horizontal():
        turtle = init_turtle()

        for y in range(GRID_NUM):
            turtle.goto(-0.5,y + 0.5)
            turtle.pendown()
            turtle.goto(GRID_NUM - 0.5,y + 0.5)
            turtle.penup()
            yield 0

        turtle.hideturtle()

    border()
    generator1 = horizontal()
    generator2 = vertical()

    while next(generator1,1) + next(generator2,1) < 2:
        pass

def start_game():
    snake = Snake()

    def right():
        snake.direction = RIGHT

    def up():
        snake.direction = UP

    def left():
        snake.direction = LEFT

    def down():
        snake.direction = DOWN

    screen.onkey(snake.body.pop,'q')
    screen.onkey(left,'Left')
    screen.onkey(up,'Up')
    screen.onkey(right,'Right')
    screen.onkey(down,'Down')
    screen.onkey(screen.bye,'Escape')
    screen.onkey(snake.levelup,'Return')
    screen.listen()

    while True:
        snake.update()
        snake.head.setheading(snake.direction * 90)
        snake.head.forward(1)

        # Run snake around in a square for testing purposes
        x,y = snake.head.position()

        if round(x) == 1 and snake.direction == LEFT:
            up()
        elif round(y) == GRID_NUM - 2 and snake.direction == UP:
            right()
        elif round(x) == GRID_NUM - 2 and snake.direction == RIGHT:
            down()
        elif round(y) == 1 and snake.direction == DOWN:
            left()

        screen.update()

screen = Screen()
screen.setup(SIZE,SIZE)
screen.bgcolor('black')
screen.setworldcoordinates(-0.75,-0.75,GRID_NUM + 0.25,GRID_NUM + 0.25)

init_border()

screen.tracer(False)

start_game()

screen.mainloop()  # never reached!

我推荐这两种方法,因为当您添加食物和边界检测时,主循环只会变得更复杂(更慢)。

我更改了您的坐标系,使其以蛇为中心。也就是说,forward(1) 在网格上移动一格而不必进行数学运算。如果您无论如何都要弄乱坐标,为什么不调整它们以发挥最大的优势。