【问题标题】:Need help on snake program about user's input需要有关用户输入的蛇程序的帮助
【发布时间】:2019-12-18 21:34:23
【问题描述】:

所以,我正在使用 tkinter 库编写一个蛇程序。该程序在全球范围内工作,但如果我给两个输入太快,我对输入的处理确实有一点问题,只有最后一个会被解释。而且我真的不知道如何解决这个问题,我尝试在每个玩家输入后强制更新,但这显然不是一个好的解决方案,因为它会强制蛇移动并使其能够传送,所以如果有人我会很高兴有一个想法来解决这个问题。有我的代码,我确信它可以改进,但现在我想专注于第一个问题。

import tkinter as tk
import numpy.random as rd

class snake:
    def __init__(self,n,m):
        self.n = n
        self.m = m
        self.body = [(n//2,m//2),(n//2,m//2-1)]
        self.lenght = 2
        self.food = (0,0)
        self.relocate_food()
        self.Game = -2
        self.vector = (0,1)  #(0,-1) = up, (0,1) = right, (0,1) = down, (-1,0) = left
        self.speed = 120

    def up(self):
        self.vector = (-1,0)  
    def right(self):
        self.vector = (0,1) 
    def down(self):
        self.vector = (1,0)      
    def left(self):
        self.vector = (0,-1)


    def relocate_food(self):
        x = rd.randint(0,self.n)
        y = rd.randint(0,self.m)
        i = 0
        test = True
        while i<self.lenght and test:
            if (x,y) == self.body[i]:
                test = False
                self.relocate_food()
            else:
                i += 1
        if i == self.lenght:
            self.food = (x,y)


    def collide(self):
        head = self.body[0]
        for i in range(1,self.lenght):
            if head == self.body[i]:
                self.Game = -1
                break
            x,y = head
            if x>=self.n or y>=self.m or x<0 or y<0:
                self.Game = -1

    def eat(self):
        head = self.body[0]
        if head == self.food:           
            self.lenght +=1
            x0, y0 = self.body[-1]
            x1, y1 = self.body[-2]
            x = x0 - x1
            y = y0 - y1
            self.body.append((x0+x,y0+y))
            self.relocate_food()
            if self.lenght%5 == 0:
                self.speed = int(self.speed * 0.90)




    def move(self):
        dx, dy = self.vector     
        last_x, last_y = self.body[0]
        new_x = last_x + dx
        new_y = last_y + dy
        self.body[0] = (new_x, new_y)
        for k in range(1, self.lenght):
            x, y = self.body[k]
            self.body[k] = (last_x,last_y)
            last_x, last_y = x, y
        return 




class screen(snake):
    def __init__(self,root,n,m):
        snake.__init__(self,n,m)
        root.minsize(n*20,m*20)
        root.maxsize(n*20,m*20)
        root.configure(background='white')
        self.root = root
        self.n = n
        self.m = m
        self.speed = 130
        self.canvas = tk.Canvas(root, width = n*20, height =m*20,bg='black')
        self.canvas.bind_all("<Key-Up>",self.move_up)
        self.canvas.bind_all("<Key-Down>",self.move_down)
        self.canvas.bind_all("<Key-Left>",self.move_left)
        self.canvas.bind_all("<Key-Right>",self.move_right)
        self.canvas.grid(row=1,column=0)
        self.draw_snake()
        self.draw_food()


    def draw_snake(self):
        y,x = self.body[0]
        self.canvas.create_rectangle(x*20,y*20,(x+1)*20,(y+1)*20,fill= 'red4')
        for k in range(1,self.lenght):
            y,x = self.body[k]
            self.canvas.create_rectangle(x*20,y*20,(x+1)*20,(y+1)*20,fill= 'red')

    def draw_food(self):
        y,x =self.food
        self.canvas.create_rectangle(x*20,y*20,(x+1)*20,(y+1)*20,fill= 'green')

    def move_up(self,event):
        if self.Game == -2:
            self.Game =0
            self.up()
            self.update()
        else:
            self.up()


    def move_down(self,event):
        if self.Game == -2:
            self.Game =0
            self.down()
            self.update()
        else:
            self.down()

    def move_left(self,event):
        if self.Game == -2:
            self.Game =0
            self.left()
            self.update()
        else:
            self.left()

    def move_right(self,event):
        if self.Game == -2:
            self.Game =0
            self.right()
            self.update()
        else:
            self.right()


    def update(self):
        if self.Game == -2:
            return 
        self.move()
        self.eat()
        self.collide()
        if self.Game == -1:
            self.root.destroy()
            return 
        self.canvas.delete("all")
        self.draw_snake()
        self.draw_food()
        self.root.after(self.speed,self.update)

window = tk.Tk()
snake = screen(window,35,35)
snake.update()
window.mainloop()     

【问题讨论】:

  • 标准规则:如果您有很多元素,则将它们保留在列表中。似乎你有变量只保留一个输入,所以最后一个输入替换前一个输入,然后代码可以使用它来移动蛇。您必须将新输入添加到某个列表的末尾,以后的代码必须使用for-loop 来使用列表中的所有输入来移动蛇。
  • 使用来自任何关键事件处理程序的self.update(),您正在执行并发更新。删除所有self.update()__init__self.Game = 0 对我有用。

标签: python tkinter input tkinter-canvas


【解决方案1】:

这并不是真正的错误。您的动画使用每 120 毫秒执行一次的“更新”功能。因此,如果您在 120 毫秒内(即在两次连续调用“更新”之间)点击 2 个箭头键,则只考虑最后一次点击,因为每次蛇更新只能考虑一个平移向量。在这一点上没有人可以责怪你,因为时间控制的动画是一个具有给定时间窗口的离散过程。这是获得流畅和规则动画的唯一解决方案(所有视频游戏都基于这样的过程),所以这显然是正确的。

但是,您的代码仍可能在多个方面得到改进。例如,在每个动画帧中,您删除所有 Canvas 项目并为蛇元素和食物创建一组全新的项目 ('create_rectangle')。这不是很有效。最好简单地更改项目的坐标(检查文档中的 Canvas.coords 函数)。请注意,为蛇设置动画只需要将先前的尾巴位置移动到新的头部位置,以产生移动野兽的错觉。因此,每帧只需要移动 1 个项目(进食时为 2 个项目),这必须更快地处理。

【讨论】:

  • 感谢改进的想法我会尝试的
【解决方案2】:

感谢 Furas 的基本想法,这是我所需要的。我更正的新代码:

def __init__(self, root,n,m):
"""

    """
    self.input = []

"""


     """
def move_up(self,event):
    if self.Game == -2:
        self.Game =0
        self.up()
        self.update()
    else:
        self.input.append(0)

"""
    Same for all the move
    """


def update(self):
    if self.Game == -2:
        return 
    if len(self.input)>3: #Make sure that the player doesn't stack instruction
        self.pop()
    try:
        input = self.input.pop(0)
    except:
        input = -1
    if input == 0:
        self.up()
    elif input == 1:
        self.right()
    elif input == 2:
        self.down()
    elif input == 3:
        self.left()
    self.move()
    self.eat()
    self.collide()
    if self.Game == -1:
        self.root.destroy()
        return 
    self.canvas.delete("all")
    self.draw_snake()
    self.draw_food()
    self.root.after(self.speed,self.update)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    相关资源
    最近更新 更多