首页 > 解决方案 > snake keeps dying randomly pygame

问题描述

I'm learning pygame and I created a simple snake game, but the snake keeps dying randomly:

I think its because the if condition that makes it die when the head hits a part of the body:

if snake.headX in snake.bodyX and snake.headY in snake.bodyY:
    snake.alive = False
    snake.moveX = 0
    snake.moveY = 0

Don't really understand whats the problem.

An other issue I have is that you can exploit the if statement that prevents you from moving into the body by fast tapping down/up and the side you want to go. This is because you change the direction for a split second and then you can go where you want to go:

keys = pygame.key.get_pressed()

if snake.alive:
    if snake.direction != 'down':
        if keys[pygame.K_UP]:
            snake.moveY = -25
            snake.moveX = 0
            snake.direction = 'up'
    if snake.direction != 'up':
        if keys[pygame.K_DOWN]:
            snake.moveY = 25
            snake.moveX = 0
            snake.direction = 'down'
    if snake.direction != 'right':
        if keys[pygame.K_LEFT]:
            snake.moveX = -25
            snake.moveY = 0
            snake.direction = 'left'
    if snake.direction != 'left':
        if keys[pygame.K_RIGHT]:
            snake.moveX = 25
            snake.moveY = 0
            snake.direction = 'right'

All the code:

import random

import pygame

pygame.init()

pygame.display.set_caption('Snake')


class Grid(object):

    def __init__(self, rows, width, x, y):
        self.rows = rows
        self.width = width
        self.x = x
        self.y = y
        self.sizeBetween = width // rows

    def draw(self, surface):
        x, y = self.x, self.y
        for p in range(self.rows - 1):
            x += self.sizeBetween
            y += self.sizeBetween

            pygame.draw.line(surface, (255, 255, 255), (x, 0), (x, self.width), 1)
            pygame.draw.line(surface, (255, 255, 255), (0, y), (self.width, y), 1)
            pygame.draw.rect(surface, (255, 255, 255), (0, 0, self.width, self.width), 1)


class Player(object):
    def __init__(self, width, x, y):
        self.width = width
        self.headX = x
        self.headY = y
        self.alive = True
        self.moveX = 0
        self.moveY = 0
        self.direction = 'right'
        self.bodyParts = 0
        self.bodyX = []
        self.bodyY = []

    def draw(self, surface):
        if snake.alive:
            self.bodyX.insert(0, self.headX)
            self.bodyY.insert(0, self.headY)
        while len(self.bodyX) > self.bodyParts:
            del self.bodyX[-1]

        while len(self.bodyY) > self.bodyParts:
            del self.bodyY[-1]

        self.move()


        for x in range(self.bodyParts):
            pygame.draw.rect(surface, (255, 0, 0),
                             (round(self.bodyX[x]), round(self.bodyY[x]), self.width, self.width))
        pygame.draw.rect(surface, (0, 0, 255), (round(self.headX), round(self.headY), self.width, self.width))

    def move(self):
        self.headX += self.moveX
        self.headY += self.moveY


class Food(object):
    def __init__(self, width):
        self.width = width
        self.amount = 1
        self.amountCheck = 1
        self.x = 326
        self.y = 226

    def draw(self, surface):
        for i in range(self.amount):
            pygame.draw.rect(surface, (0, 255, 0), (self.x, self.y, self.width, self.width))


def window(surface):
    field.draw(surface)
    snake.draw(surface)
    snack.draw(surface)
    pygame.display.update()


snake = Player(24, 176, 226)
field = Grid(20, 500, 0, 0)
snack = Food(24)
clock = pygame.time.Clock()
win = pygame.display.set_mode((field.width, field.width))
run = True
while run:
    clock.tick(10)
    win.fill((0, 0, 0))

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False

    keys = pygame.key.get_pressed()

    if snake.alive:
        if snake.direction != 'down':
            if keys[pygame.K_UP]:
                snake.moveY = -25
                snake.moveX = 0
                snake.direction = 'up'
        if snake.direction != 'up':
            if keys[pygame.K_DOWN]:
                snake.moveY = 25
                snake.moveX = 0
                snake.direction = 'down'
        if snake.direction != 'right':
            if keys[pygame.K_LEFT]:
                snake.moveX = -25
                snake.moveY = 0
                snake.direction = 'left'
        if snake.direction != 'left':
            if keys[pygame.K_RIGHT]:
                snake.moveX = 25
                snake.moveY = 0
                snake.direction = 'right'

    if snake.headY >= 500:
        snake.alive = False
        snake.moveX = 0
        snake.moveY = 0
        snake.headY = 476
    elif snake.headY <= 0:
        snake.alive = False
        snake.moveX = 0
        snake.moveY = 0
        snake.headY = 1
    elif snake.headX >= 500:
        snake.alive = False
        snake.moveX = 0
        snake.moveY = 0
        snake.headX = 476
    elif snake.headX <= 0:
        snake.alive = False
        snake.moveX = 0
        snake.moveY = 0
        snake.headX = 1

    if snake.headX in snake.bodyX and snake.headY in snake.bodyY:
        snake.alive = False
        snake.moveX = 0
        snake.moveY = 0

    if snake.headX == snack.x and snake.headY == snack.y:
        snack.x = random.randint(0, 19) * 25 + 1
        snack.y = random.randint(0, 19) * 25 + 1
        snake.bodyParts += 1

    if not snake.alive:
        print('dead')

    window(win)

标签: pythonpygame

解决方案


您在第一个代码块中突出显示了逻辑问题:

if snake.headX in snake.bodyX and snake.headY in snake.bodyY:

用英文阅读:

if the head is in the same column as any body square AND
   the head is in the same row as any body square:

您的图形清楚地显示了 [B]ody 和 [H]ead 正方形的情况。

B B
B
B H

头部与尾部正方形在同一列,与“颈部”正方形在同一行。你把它编码为死亡。

您需要检查的是头部正方形是否与身体正方形匹配。您必须配对坐标才能使其工作。就像是:

if (snake.headX, snake.headY in zip(snake.budyX, snake.bodyY):

推荐阅读