Как остановить появление случайных диапазонов в определенных областях, которые различаются?

Я делаю змею, используя pygame для школьного задания, и она функциональна и работает, но проблема в том, что иногда, когда змея ест пищу, новая еда появляется внутри хвоста змеи. Причина, по которой я не уверен, как это изменить, заключается в том, что способ, которым он генерирует случайное размещение еды, использует случайный диапазон в сетке, и я в любом случае не знаю, как исключить хвост змеи из этого диапазона/регенерировать его, если он появляется внутри там. Это фундаментальная проблема с использованием random.randrange или есть простое решение, сохраняющее большую часть кода. Выделенный код сверху двумя строками ниже

foodX = round(random.randrange(0,display_width-snake_block)/snake_block)*snake_block
foodY = round(random.randrange(0,display_height-snake_block)/snake_block)*snake_block

import pygame
import time
import random

pygame.init()

display_width = 600
display_height = 600
display = pygame.display.set_mode((display_width,display_height))
pygame.display.set_caption("Snake")

pureblue = (0,0,255)
purered = (255,0,0)
puregreen = (0,255,0)
red = (125,25,25)
green = (25,125,25)
white = (255,255,255)
black = (1,1,1)
grey = (20,20,20)
darkgrey = (15,15,15)


clock = pygame.time.Clock()

snake_block = 30
snake_speed = 10

font_style = pygame.font.SysFont(None, 50)

def user_snake(snake_block, snake_List):
    for x in snake_List:
        pygame.draw.rect(display,green,[x[0],x[1], snake_block, snake_block])

def drawGrid(surf):
    blockSize = snake_block
    surf.fill(grey)
    for x in range(display_width):
        for y in range(display_height):
            rect = pygame.Rect(x*blockSize, y*blockSize,blockSize, blockSize)
            pygame.draw.rect(surf,darkgrey, rect, 1)
grid_surf = pygame.Surface(display.get_size())
drawGrid(grid_surf)

def message(msg, colour):
    text = font_style.render(msg, True, colour)
    display.blit(text, [0, display_height/4])

def SnakeGameLoop():
    game_over = False
    game_close = False
    X = display_width/2
    Y = display_height/2

    X_change = 0
    Y_change = 0
    
    snake_List = []
    Length_of_snake = 1

    foodX = round(random.randrange(0,display_width-snake_block)/snake_block)*snake_block
    foodY = round(random.randrange(0,display_height-snake_block)/snake_block)*snake_block

    while not game_over:
        while game_close == True:
            message("You Lost! Press Q-Quit or C-Play Again", purered)
            pygame.display.update()
 
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_q:
                        game_over = True
                        game_close = False
                    if event.key == pygame.K_c:
                        SnakeGameLoop()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                game_over = True
            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    X_change = -snake_block
                    Y_change = 0
                elif event.key == pygame.K_RIGHT:
                    X_change = snake_block
                    Y_change = 0
                elif event.key == pygame.K_UP:
                    X_change = 0
                    Y_change = -snake_block
                elif event.key == pygame.K_DOWN:
                    X_change = 0
                    Y_change = snake_block

                if event.key == pygame.K_a:
                    X_change = -snake_block
                    Y_change = 0
                elif event.key == pygame.K_d:
                    X_change = snake_block
                    Y_change = 0
                elif event.key == pygame.K_w:
                    X_change = 0
                    Y_change = -snake_block
                elif event.key == pygame.K_s:
                    X_change = 0
                    Y_change = snake_block

        if X >= display_width or X < 0 or Y >= display_height or Y < 0:
            game_close = True

        X += X_change
        Y += Y_change
        display.blit(grid_surf, (0,0))
        pygame.draw.rect(display, red, [foodX, foodY, snake_block, snake_block])
        snake_Head = []
        snake_Head.append(X)
        snake_Head.append(Y)
        snake_List.append(snake_Head)

        if len(snake_List) > Length_of_snake:
            del snake_List[0]

        for x in snake_List[:-1]:
            if x == snake_Head:
                game_close = True

        user_snake(snake_block,snake_List)

        pygame.display.update()

        if X == foodX and Y == foodY:
            foodX = round(random.randrange(0, display_width - snake_block) / snake_block) * snake_block
            foodY = round(random.randrange(0, display_height - snake_block) / snake_block) * snake_block
            Length_of_snake += 1

        clock.tick(snake_speed)


    pygame.quit()
    quit()
SnakeGameLoop()
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
0
72
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Есть несколько способов решить эту проблему. Одним из простых способов было бы просто сгенерировать координаты, проверить, не сталкиваются ли они со змеей, и зациклиться, пока этого не происходит. Хотя это просто, это может быть очень неэффективно, когда ваша змея занимает много места на экране, и может потребоваться несколько итераций для размещения каждого нового элемента.

Другим способом было бы генерировать случайные координаты, как вы это делаете, и, если они сталкиваются со змеей, проверять ближайший доступный квадрат вокруг этой случайной точки. Это может быть немного сложнее, но должно быть более эффективным. Может произойти случай, когда ваша змея занимает много сжатого пространства (скажем, вы немного ходили по узким кругам), что также может сделать этот случай немного медленным.

Интересным подходом может быть объединение обоих подходов: сгенерировать случайные координаты, если квадрат занят, проверить ближайший доступный квадрат на максимальном расстоянии n квадратов, и если это не поможет, сгенерировать новые координаты. Однако это может быть излишним.

Вы также можете взять разницу между набором всех координат и набором всех координат, которые в данный момент занимает змея. Затем выберите координату из этой разницы.

Paul M. 23.12.2020 17:34

Спасибо, я понимаю, как я мог реализовать первое, но как вы могли сделать второе. Моей первой мыслью было добавить +1 к значению X/Y, но я не совсем уверен, что это сработает.

user14530934 23.12.2020 20:44

Другие вопросы по теме