Python 我的蛇正径直穿过它自己,它正穿过边界

Python 我的蛇正径直穿过它自己,它正穿过边界,python,pygame,Python,Pygame,我刚开始学习python并尝试了snake游戏,我遇到了一个问题。当我运行程序并使蛇向左移动时,我可以将它向右移动,然后它会自行崩溃。上下都一样。我想让它这样蛇就不会向后撞到自己了。而且,当我让蛇走出边界时,它不会死,它只是从另一面墙中穿过。例如,如果我的蛇从右边的墙跑出来,它会从另一边的左边穿过 import pygame import math import random import tkinter as tk from tkinter import messagebox from pyg

我刚开始学习python并尝试了snake游戏,我遇到了一个问题。当我运行程序并使蛇向左移动时,我可以将它向右移动,然后它会自行崩溃。上下都一样。我想让它这样蛇就不会向后撞到自己了。而且,当我让蛇走出边界时,它不会死,它只是从另一面墙中穿过。例如,如果我的蛇从右边的墙跑出来,它会从另一边的左边穿过

import pygame
import math
import random
import tkinter as tk
from tkinter import messagebox
from pygame.locals import *
import time



pygame.display.set_caption('SNAKE GAME!!! HAVE FUN PLAYING')

class cube(object):
    rows = 30
    w = 750

    def __init__(self,start,dirnx=1,dirny=0,color=(30,144,255)):
        self.pos = start
        self.dirnx = 1
        self.dirny = 0
        self.color = color

    def move(self,dirnx,dirny):
        self.dirnx = dirnx
        self.dirny = dirny
        self.pos = (self.pos[0] + self.dirnx, self.pos[1] + self.dirny)

    def draw(self,surface,eyes=False):
        dis = self.w //self.rows
        i = self.pos[0]
        j = self.pos[1]

        pygame.draw.rect(surface,self.color, (i*dis+1, j*dis+1, dis-2, dis-2))

        if eyes:
            centre = dis//2
            radius = 3
            circleMiddle = (i*dis+centre-radius,j*dis+8)
            circleMiddle2 = (i*dis+dis-radius*2, j*dis+8)
            pygame.draw.circle(surface, (0,128,0), circleMiddle, radius)
            pygame.draw.circle(surface, (0,128,0), circleMiddle2, radius)


class snake(object):
    body= []
    turns = {}

    def __init__(self,color,pos):
        self.color = color
        self.head = cube(pos)
        self.body.append(self.head)
        self.dirnx = 0
        self.dirny = 1

    def move(self):
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()

            keys = pygame.key.get_pressed()

            for key in keys:
                if keys[pygame.K_LEFT]:
                    self.dirnx = -1
                    self.dirny = 0
                    self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]

                elif keys[pygame.K_RIGHT]:
                    self.dirnx = 1
                    self.dirny = 0
                    self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]

                elif keys[pygame.K_UP]:
                    self.dirnx = 0
                    self.dirny = -1
                    self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]

                elif keys[pygame.K_DOWN]:
                    self.dirnx = 0
                    self.dirny = 1
                    self.turns[self.head.pos[:]] = [self.dirnx, self.dirny]

        for i, c in enumerate(self.body):
            p = c.pos[:]
            if p in self.turns:
                turn = self.turns[p]
                c.move(turn[0], turn[1])
                if i == len(self.body) - 1:
                    self.turns.pop(p)
            else:
                if c.dirnx == -1 and c.pos[0] <= 0:
                    c.pos = (c.rows - 1, c.pos[1])
                elif c.dirnx == 1 and c.pos[0] >= c.rows - 1:
                    c.pos = (0, c.pos[1])
                elif c.dirny == 1 and c.pos[1] >= c.rows - 1:
                    c.pos = (c.pos[0], 0)
                elif c.dirny == -1 and c.pos[1] <= 0:
                    c.pos = (c.pos[0], c.rows - 1)
                else:
                    c.move(c.dirnx, c.dirny)

    def reset(self,pos):
        self.head = cube(pos)
        self.body = []
        self.body.append(self.head)
        self.turns = {}
        self.dirnx = 0
        self.dirny = 1

    def addCube(self):
        tail = self.body[-1]
        dx,dy = tail.dirnx, tail.dirny

        if dx == 1 and dy == 0:
            self.body.append(cube((tail.pos[0]-1,tail.pos[1])))
        elif dx == -1 and dy == 0:
            self.body.append(cube((tail.pos[0]+1, tail.pos[1])))
        elif dx == 0 and dy == 1:
            self.body.append(cube((tail.pos[0], tail.pos[1]-1)))
        elif dx == 0 and dy == -1:
            self.body.append(cube((tail.pos[0], tail.pos[1]+1)))

        self.body[-1].dirnx = dx
        self.body[-1].dirny = dy



    def draw(self,surface):
        for i,c in enumerate(self.body):
            if i == 0:
                c.draw(surface, True)
            else:
                c.draw(surface)


def drawGrid(w,rows,surface):
    sizeBtwn = w // rows
    x = 0
    y = 0
    for l in range(rows):
        x = x + sizeBtwn
        y = y + sizeBtwn
        pygame.draw.line(surface,(255,255,255),(x,0),(x,w))
        pygame.draw.line(surface,(255,255,255),(0,y),(w,y))


def redrawWindow(surface):
    global rows,width,s,snack
    surface.fill((154,205,50))
    s.draw(surface)
    snack.draw(surface)
    drawGrid(width,rows,surface)
    pygame.display.update()

def randomSnack(rows,item):
    positions = item.body

    while True:
        x = random.randrange(rows)
        y = random.randrange(rows)
        if len(list(filter(lambda z:z.pos == (x,y), positions)))>0:
            continue
        else:
            break
    return (x,y)


def message_box(subject,content):
    root = tk.Tk()
    root.attributes("-topmost", True)
    root.withdraw()
    messagebox.showinfo(subject,content)
    try:
        root.destroy()
    except:
        pass

def main():
    global width,rows,s,snack
    width = 750
    height = 500
    rows = 30
    win = pygame.display.set_mode((width,width))
    s = snake((30,144,255),(10,10))
    snack = cube(randomSnack(rows,s), color=(255,0,0))
    flag = True
    clock = pygame.time.Clock()
    while flag:
        pygame.time.delay(1)
        clock.tick(10)
        s.move()
        if s.body[0].pos == snack.pos:
            s.addCube()
            snack = cube(randomSnack(rows,s), color=(255,0,0))

        for x in range(len(s.body)):
            if s.body[x].pos in list(map(lambda z: z.pos, s.body[x + 1:])):
                print('Score: ', len(s.body))
                score = str(len(s.body))
                s.reset((10, 15))
                pygame.display.set_caption("Score:", score)

        redrawWindow(win)
        pass

main()

导入pygame
输入数学
随机输入
将tkinter作为tk导入
从tkinter导入消息框
从pygame.locals导入*
导入时间
pygame.display.set_标题('蛇游戏!!!玩得开心')
类多维数据集(对象):
行数=30
w=750
定义初始化(self,start,dirnx=1,dirny=0,color=(30144255)):
self.pos=开始
self.dirnx=1
self.dirny=0
self.color=颜色
def移动(自身、dirnx、dirny):
self.dirnx=dirnx
self.dirny=dirny
self.pos=(self.pos[0]+self.dirnx,self.pos[1]+self.dirny)
def绘制(自身、表面、眼睛=假):
dis=self.w//self.rows
i=自身位置[0]
j=自身位置[1]
pygame.draw.rect(曲面,self.color,(i*dis+1,j*dis+1,dis-2,dis-2))
如果眼睛:
中心=dis//2
半径=3
圆心=(i*dis+中心半径,j*dis+8)
圆IDDLE2=(i*dis+dis半径*2,j*dis+8)
pygame.draw.圆(曲面,(0128,0),圆中间,半径)
pygame.draw.circle(曲面,(0128,0),circleMiddle2,半径)
类(对象):
正文=[]
圈数={}
定义初始(自身、颜色、位置):
self.color=颜色
self.head=立方体(位置)
self.body.append(self.head)
self.dirnx=0
self.dirny=1
def移动(自我):
对于pygame.event.get()中的事件:
如果event.type==pygame.QUIT:
pygame.quit()
keys=pygame.key.get_pressed()
对于键入键:
如果键[pygame.K_左]:
self.dirnx=-1
self.dirny=0
self.turns[self.head.pos[:]=[self.dirnx,self.dirny]
elif keys[pygame.K_RIGHT]:
self.dirnx=1
self.dirny=0
self.turns[self.head.pos[:]=[self.dirnx,self.dirny]
elif keys[pygame.K_UP]:
self.dirnx=0
self.dirny=-1
self.turns[self.head.pos[:]=[self.dirnx,self.dirny]
elif keys[pygame.K_DOWN]:
self.dirnx=0
self.dirny=1
self.turns[self.head.pos[:]=[self.dirnx,self.dirny]
对于枚举中的i,c(self.body):
p=c.pos[:]
如果p在self.turns中:
旋转=自旋转[p]
c、 移动(转动[0],转动[1])
如果i==len(self.body)-1:
自转.弹出(p)
其他:
如果c.dirnx==-1和c.pos[0]=c.rows-1:
c、 pos=(0,c.pos[1])
elif c.dirny==1和c.pos[1]>=c.rows-1:
c、 pos=(c.pos[0],0)
elif c.dirny==-1和c.pos[1]0:
持续
其他:
打破
返回(x,y)
def消息框(主题、内容):
root=tk.tk()
属性(“-top”,True)
root.draw()
messagebox.showinfo(主题、内容)
尝试:
root.destroy()
除:
通过
def main():
全局宽度、行数、行数
宽度=750
高度=500
行数=30
win=pygame.display.set_模式((宽度,宽度))
s=蛇((30144255),(10,10))
零食=立方体(随机零食(行,s),颜色=(255,0,0))
flag=True
clock=pygame.time.clock()
而国旗:
pygame.time.delay(1)
时钟滴答(10)
s、 移动()
如果s.body[0].pos==snack.pos:
s、 addCube()
零食=立方体(随机零食(行,s),颜色=(255,0,0))
对于范围内的x(透镜体):
如果列表中的s.body[x].pos(映射(lambda z:z.pos,s.body[x+1:]):
打印('Score:',len(s.body))
分数=str(len(s.body))
s、 重置((10,15))
pygame.display.set_标题(“分数:”,分数)
重画窗口(win)
通过
main()

请帮忙

首先,当有精灵而不是简单的对象类时,阅读pygame代码要容易得多。 第二,你的例子比它应该的要大得多,请保持简单,并将其局限于实际问题

为了防止蛇在走向相反方向时自杀我看到了两种解决方案:

  • 当snake向任何方向移动(例如self.dirny=1)时,您可能会禁止将方向更改为相反的方向(因此,当用户按下
    pygame.K\u UP
    时,方向不会更改,并且忽略键)
  • 更难的解决方案-检查哪一个方向是尾巴,并根据此改变方向(这将包括移动的头部,并在这种情况下与尾巴交换)

  • 为了在蛇到达边界时杀死蛇-在蛇中
    move()
    方法您应该检查立方体是否击中边界,以及何时击中边界-杀死蛇,而不是将立方体的位置移动到棋盘的另一侧。

    首先-当存在精灵而不是简单的对象类时,阅读pygame代码要容易得多。 第二,你的例子比它应该的要大得多,请保持简单,并将其局限于实际问题

    为了防止蛇在走向相反方向时自杀我看到了两种解决方案:

  • 当snake向任何方向移动(例如self.dirny=1)时,您可能会禁止将方向更改为oppo