gpt4 book ai didi

python - Pygame 似乎崩溃但没有错误消息

转载 作者:行者123 更新时间:2023-12-04 09:54:51 25 4
gpt4 key购买 nike

我正在努力创建一个 AI 来玩经典游戏 Snake,并且已经成功地实现了它,但是程序在达到目标时经常崩溃。我使用 A* 的修改版本进行寻路,使用 pygame 进行图形处理。

import numpy as np
import pygame
import random


# Set constants for program
GRID_WIDTH = 25
GRID_HEIGHT = 25

WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)


displayX = 500
displayY = 500

SCALEX = displayX/GRID_WIDTH
SCALEY = displayY/GRID_HEIGHT



# Setyp pygame
gameDisplay = pygame.display.set_mode((displayX,displayY))
pygame.display.set_caption('Snake')
clock = pygame.time.Clock()



# Mainly stores values at each point in the game area
class Block():
def __init__(self, x, y, val):
self.x = x
self.y = y
self.val = val # Stores what type this block is e.g. snake or fruit

self.f = 0 # Values for A-Star Algorithm
self.g = 0
self.h = 0

def get_value(self):
return self.val

def set_value(self, new_val):
self.val = new_val

def set_cost(self, g, h):
self.g = g
self.h = h
self.f = self.h - self.g

def set_parent(self, parent):
self.parent = parent # Used for retracing the path

class Snake():
def __init__(self, x, y):
self.x = x
self.y = y
self.L = 4 # Length of snake
self.body = [] # List of all parts in snake
self.body.append([x, y])

self.path = None

def move(self, board):
print(self.path)
if self.path == None or self.path == []: # Check if a path exists
self.A_Star(board) # If not calculate path
else:
self.x = self.path[0][0] # Move to next point in path then remove it from list
self.y = self.path[0][1]
self.path.pop(0)
self.body.append([self.x, self.y]) # Add body part
self.body = self.body[-self.L:]

def get_snake(self):
return self.body[-self.L:]

def get_head(self):
return [self.x, self.y]

def eat(self): # Increase length and reset path
self.L += 1
self.path = None


def A_Star(self, board): # Modified version of A Star to prioritise moving away from target
start = board.get_grid()[self.x, self.y]
end = board.get_fruit()

if start != None and end != None:
open_list = []
closed_list = []

current = start
open_list.append(current)
while open_list != []:
current = open_list[0]
for block in open_list:
if block.f > current.f:
current = block
open_list.remove(current)
closed_list.append(current)

if current == end:
path = self.retrace_path(start, end)
return True

neighbours = board.get_node_neighbours(current)
for neighbour in neighbours:
if neighbour.get_value() != "body" and not neighbour in closed_list:
if not neighbour in open_list:
neighbour.set_cost(neighbour.g, board.get_distance(current, end))
neighbour.set_parent(current)
if not neighbour in open_list:
open_list.append(neighbour)
return False

def retrace_path(self, start, end):
current = end
path = []
while current != start:
path.append([current.x, current.y])
current = current.parent
self.path = path
self.path.reverse()

'''def survive(self, board):
neighbours = board.get_node_neighbours(board.get_grid()[self.x, self.y])
for neighbour in neighbours:
if neighbour.val == "empty":
self.path = [neighbour.x, neighbour.y]
break'''




class Board():
def __init__(self, snake):
self.grid = np.empty((GRID_WIDTH, GRID_HEIGHT), dtype=object)
for x in range(0, GRID_WIDTH):
for y in range(0, GRID_HEIGHT):
self.grid[x,y] = Block(x, y, "empty") # 2D Array containing all blocks
self.fruit = self.new_fruit(snake) # Generate new fruit
self.score = 0

def check_fruit(self, snake): # Check collision between snake and fruit
snake_head = snake.get_head()
if snake_head[0] == self.fruit[0] and snake_head[1] == self.fruit[1]:
snake.eat()
self.score += 1
self.fruit = self.new_fruit(snake)

def check_death(self, snake): # Check to see if snake is dead
snake_head = snake.get_head()
snake_body = snake.get_snake()
if snake_head[0] >= GRID_WIDTH or snake_head[0] < 0 or snake_head[1] >= GRID_HEIGHT or snake_head[1] < 0:
return True
collisions = 0
for part in snake_body:
if snake_head == part:
collisions += 1
if collisions == 2:
return True

def draw(self, snake): # Draw everything to screen
self.grid = np.empty((GRID_WIDTH, GRID_HEIGHT), dtype=object)
for x in range(0, GRID_WIDTH):
for y in range(0, GRID_HEIGHT):
self.grid[x,y] = Block(x, y, "empty")
for part in snake.get_snake():
self.grid[part[0], part[1]].set_value("body")
self.grid[snake.get_head()[0], snake.get_head()[1]].set_value("head")
self.grid[self.fruit[0], self.fruit[1]].set_value("fruit")

for x in range(0, GRID_WIDTH):
for y in range(0, GRID_HEIGHT):
if self.grid[x, y].get_value() == "fruit":
pygame.draw.rect(gameDisplay,RED,(x*SCALEX,y*SCALEY,SCALEX,SCALEY))
elif self.grid[x, y].get_value() == "body" or self.grid[x, y].get_value() == "head":
pygame.draw.rect(gameDisplay,WHITE,(x*SCALEX,y*SCALEY,SCALEX,SCALEY))


def new_fruit(self, snake): # Generate a new fruit location
complete = False
fail = False
while not complete:
fruit_loc = [random.randint(0, GRID_WIDTH-1), random.randint(0, GRID_HEIGHT-1)]
for part in snake.get_snake(): # Check that fruit is not in snake
if part == fruit_loc:
fail = True
if not fail:
complete = True
return fruit_loc


def get_node_neighbours(self, block): # Get surrounding blocks from block
neighbours = []
options = [[-1, 0], [1, 0], [0, -1], [0, 1]]
for option in options:
checkX = block.x + option[0]
checkY = block.y + option[1]

if checkX >= 0 and checkX < GRID_WIDTH and checkY >= 0 and checkY < GRID_HEIGHT:
neighbours.append(self.grid[checkX,checkY])
return neighbours

def get_distance(self, start, end): # Get distance between two points
dx = abs(start.x - end.x)
dy = abs(start.y - end.y)

return dx + dy - 1

def get_grid(self):
return self.grid

def get_fruit(self):
return self.grid[self.fruit[0], self.fruit[1]]


def main():
snake = Snake(0, 0)
board = Board(snake)
running = True

while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
break

snake.move(board) # Move snake


if board.check_death(snake): # End program if snake is dead
running = False
break

board.check_fruit(snake) # Call fruit check

gameDisplay.fill(BLACK) # Draw to screen
board.draw(snake)

pygame.display.update()
clock.tick(100)

main()
pygame.quit()

不会出现任何错误消息,并且表明程序已停止的唯一方法是 pygame 不再允许您退出并崩溃。据我所知,如果完全随机但发生在大多数回合中,它会在什么时候发生。蛇会到达水果,​​但会在吃它之前停下来。

最佳答案

问题是方法new_fruit在类(class)Board .你已经生成了无限循环。实际上,如果第一次尝试随机位置失败,fail会留下True永远。
fail = False必须在外循环中设置,而不是在循环之前:

class Board():
# [...]

def new_fruit(self, snake): # Generate a new fruit location
complete = False
# fail = False
while not complete:

fail = False # <----

fruit_loc = [random.randint(0, GRID_WIDTH-1), random.randint(0, GRID_HEIGHT-1)]
for part in snake.get_snake(): # Check that fruit is not in snake
if part == fruit_loc:
fail = True
if not fail:
complete = True
return fruit_loc

关于python - Pygame 似乎崩溃但没有错误消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61941958/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com