# 在迷宫中创建精灵和列表(不是精灵)之间的冲突 ### 问题描述

``````class Cell(object):
def __init__(self, x, y, cell_size, screen, black, white, red, blue):
# position in matrix
self.x = x
self.y = y
# keeps track of which walls are still visible
self.walls = [True, True, True, True]
# checks if cell has been visited during generation
self.generated = False
# checks if cell is on path during solving
self.on_path = False
# checks if cell has been visited during solving
self.visited = False
self.cell_size = cell_size
self.screen = screen
self.black = black
self.white = white
self.red = red
self.blue = blue

def draw_cell(self):
# coordinates on screen
x = self.x * self.cell_size
y = self.y * self.cell_size
# draws a wall if it still exists
if self.walls:
pygame.draw.line(self.screen, self.black, (x, y), (x + self.cell_size, y), 5)

if self.walls:
pygame.draw.line(self.screen, self.black,
(x, y + self.cell_size), (x + self.cell_size, y + self.cell_size), 5)
if self.walls:
pygame.draw.line(self.screen, self.black,
(x + self.cell_size, y), (x + self.cell_size, y + self.cell_size), 5)
if self.walls:
pygame.draw.line(self.screen, self.black, (x, y), (x, y + self.cell_size), 5)
# marks out white if generated during generation
if self.generated:
pygame.draw.rect(self.screen, self.white, (x, y, self.cell_size, self.cell_size))

class Maze():
def __init__(self, screen, cell_size, rows, cols, white, black, red, blue):
self.screen = screen
self.cell_size = cell_size
self.rows = rows
self.cols = cols
self.state = None
self.maze = []
self.stack = []
self.current_x = 0
self.current_y = 0
self.row = []
self.neighbours = []
self.black = black
self.white = white
self.red = red
self.blue = blue
self.cell = None
self.maze_generated = False

def on_start(self):
# maintains the current state
# maze matrix of cell instances
self.maze = []
# stack of current cells on path
self.stack = []
self.current_x, self.current_y = 0, 0

self.maze.clear()
self.stack.clear()
for x in range(self.cols):
self.row = []
for y in range(self.rows):
self.cell = Cell(x, y, self.cell_size, self.screen,
self.black, self.white, self.red, self.blue)
self.row.append(self.cell)
self.maze.append(self.row)

def in_bounds(self, x, y):
return 0 <= x < self.cols and 0 <= y < self.rows
# if x and y are within the bounds of the walls

def find_next_cell(self, x, y):
# keeps track of valid neighbors
self.neighbours = []

# loop through these two arrays to find all 4 neighbor cells
dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]
for d in range(4):
# add cell to neighbor list if it is in bounds and not generated
if self.in_bounds(x + dx[d], y + dy[d]):
if not self.maze[x + dx[d]][y + dy[d]].generated:
self.neighbours.append((x + dx[d], y + dy[d]))
# returns a random cell in the neighbors list, or -1 -1 otherwise
if len(self.neighbours) > 0:
return self.neighbours[random.randint(0, len(self.neighbours) - 1)]
else:
return -1, -1

def remove_wall(self, x1, y1, x2, y2):
# x distance between original cell and neighbor cell
xd = self.maze[x1][y1].x - self.maze[x2][y2].x
# to the bottom
if xd == 1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False
# to the top
elif xd == -1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False
# y distance between original cell and neighbor cell
xy = self.maze[x1][y1].y - self.maze[x2][y2].y
# to the right
if xy == 1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False
# to the left
elif xy == -1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False

def create_maze(self):
# if self.maze_generated == False:
self.maze[self.current_x][self.current_y].generated = True
# self.maze[self.current_x][self.current_y].draw_current()
next_cell = self.find_next_cell(self.current_x, self.current_y)
# checks if a neighbor was returned
if next_cell >= 0 and next_cell >= 0:
self.stack.append((self.current_x, self.current_y))
self.remove_wall(self.current_x, self.current_y, next_cell, next_cell)
self.current_x = next_cell
self.current_y = next_cell
# no neighbor, so go to the previous cell in the stack
elif len(self.stack) > 0:
previous = self.stack.pop()
self.current_x = previous
self.current_y = previous
# else:
self.maze_generated = True
``````

### 推荐答案

``````col_l = player.rect.left // CELL_SIZEcol_r = player.rect.right // CELL_SIZE
row_t = player.rect.top // CELL_SIZErow_b = player.rect.bottom // CELL_SIZE``````

``````keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
new_rect = player.rect.move(-1, 0)
next_col = new_rect.left // CELL_SIZE
if col_l == next_col or not (m.maze[col_l][row_t].walls or m.maze[col_l][row_b].walls):
player.rect = new_rect
if keys[pygame.K_RIGHT]:
new_rect = player.rect.move(1, 0)
next_col = new_rect.right // CELL_SIZE
if col_r == next_col or not (m.maze[col_r][row_t].walls or m.maze[col_r][row_b].walls):
player.rect = new_rect
if keys[pygame.K_UP]:
new_rect = player.rect.move(0, -1)
next_row = new_rect.top // CELL_SIZE
if row_t == next_row or not (m.maze[col_l][row_t].walls or m.maze[col_r][row_t].walls):
player.rect = new_rect
if keys[pygame.K_DOWN]:
new_rect = player.rect.move(0, 1)
next_row = new_rect.bottom // CELL_SIZE
if row_b == next_row or not (m.maze[col_l][row_b].walls or m.maze[col_r][row_b].walls):
player.rect = new_rect
``````

``````import pygame
import random

class Cell(object):
def __init__(self, x, y, cell_size, screen, black, white, red, blue):
# position in matrix
self.x = x
self.y = y
# keeps track of which walls are still visible
self.walls = [True, True, True, True]
# checks if cell has been visited during generation
self.generated = False
# checks if cell is on path during solving
self.on_path = False
# checks if cell has been visited during solving
self.visited = False
self.cell_size = cell_size
self.screen = screen
self.black = black
self.white = white
self.red = red
self.blue = blue

def draw_cell(self):
# coordinates on screen
x = self.x * self.cell_size
y = self.y * self.cell_size
# draws a wall if it still exists
if self.walls:
pygame.draw.line(self.screen, self.black, (x, y), (x + self.cell_size, y), 5)
if self.walls:
pygame.draw.line(self.screen, self.black,
(x, y + self.cell_size), (x + self.cell_size, y + self.cell_size), 5)
if self.walls:
pygame.draw.line(self.screen, self.black,
(x + self.cell_size, y), (x + self.cell_size, y + self.cell_size), 5)
if self.walls:
pygame.draw.line(self.screen, self.black, (x, y), (x, y + self.cell_size), 5)
# marks out white if generated during generation
if self.generated:
pygame.draw.rect(self.screen, self.white, (x, y, self.cell_size, self.cell_size))

class Maze:
def __init__(self, screen, cell_size, rows, cols, white, black, red, blue):
self.screen = screen
self.cell_size = cell_size
self.rows = rows
self.cols = cols
self.state = None
self.maze = []
self.stack = []
self.current_x = 0
self.current_y = 0
self.row = []
self.neighbours = []
self.black = black
self.white = white
self.red = red
self.blue = blue
self.cell = None

def on_start(self):
# maintains the current state
# maze matrix of cell instances
self.maze = []
# stack of current cells on path
self.stack = []
self.current_x, self.current_y = 0, 0

self.maze.clear()
self.stack.clear()
for x in range(self.cols):
self.row = []
for y in range(self.rows):
self.cell = Cell(x, y, self.cell_size, self.screen, self.black, self.white, self.red, self.blue)
self.row.append(self.cell)
self.maze.append(self.row)

def in_bounds(self, x, y):
return 0 <= x < self.cols and 0 <= y < self.rows

def find_next_cell(self, x, y):
# keeps track of valid neighbors
self.neighbours = []

# loop through these two arrays to find all 4 neighbor cells
dx, dy = [1, -1, 0, 0], [0, 0, 1, -1]
for d in range(4):
# add cell to neighbor list if it is in bounds and not generated
if self.in_bounds(x + dx[d], y + dy[d]):
if not self.maze[x + dx[d]][y + dy[d]].generated:
self.neighbours.append((x + dx[d], y + dy[d]))
# returns a random cell in the neighbors list, or -1 -1 otherwise
if len(self.neighbours) > 0:
return self.neighbours[random.randint(0, len(self.neighbours) - 1)]
else:
return -1, -1

def remove_wall(self, x1, y1, x2, y2):
# x distance between original cell and neighbor cell
xd = self.maze[x1][y1].x - self.maze[x2][y2].x
# to the bottom
if xd == 1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False
# to the top
elif xd == -1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False
# y distance between original cell and neighbor cell
xy = self.maze[x1][y1].y - self.maze[x2][y2].y
# to the right
if xy == 1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False
# to the left
elif xy == -1:
self.maze[x1][y1].walls = False
self.maze[x2][y2].walls = False

def create_maze(self):
self.maze[self.current_x][self.current_y].generated = True
# self.maze[self.current_x][self.current_y].draw_current()
next_cell = self.find_next_cell(self.current_x, self.current_y)
# checks if a neighbor was returned
if next_cell >= 0 and next_cell >= 0:
self.stack.append((self.current_x, self.current_y))
self.remove_wall(self.current_x, self.current_y, next_cell, next_cell)
self.current_x = next_cell
self.current_y = next_cell
# no neighbor, so go to the previous cell in the stack
elif len(self.stack) > 0:
previous = self.stack.pop()
self.current_x = previous
self.current_y = previous

class Player(pygame.sprite.Sprite):
def __init__(self):
super().__init__()
self.image = pygame.Surface((20, 20))
self.image.fill((255, 0, 0))
self.rect = self.image.get_rect(center = (20, 20))

def main():
WIDTH, HEIGHT = 800, 800
CELL_SIZE = 40
ROWS, COLUMNS = int(HEIGHT / CELL_SIZE), int(WIDTH / CELL_SIZE)

# color variables
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)
RED = (255, 0, 0)
BLUE = (0, 0, 255)

# initialize pygame
pygame.init()
SCREEN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Maze Gen")
CLOCK = pygame.time.Clock()
FPS = 60

m = Maze(SCREEN, CELL_SIZE, ROWS, COLUMNS, WHITE, BLACK, RED, BLUE)
m.on_start()
while True:
m.create_maze()
if len(m.stack) == 0:
break

player = Player()
all_sprites = pygame.sprite.Group(player)

running = True
while running:
CLOCK.tick(FPS)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False

col_l = player.rect.left // CELL_SIZE  col_r = player.rect.right // CELL_SIZE
row_t = player.rect.top // CELL_SIZE  row_b = player.rect.bottom // CELL_SIZE
keys = pygame.key.get_pressed()
if keys[pygame.K_LEFT]:
new_rect = player.rect.move(-1, 0)
next_col = new_rect.left // CELL_SIZE
if col_l == next_col or not (m.maze[col_l][row_t].walls or m.maze[col_l][row_b].walls):
player.rect = new_rect
if keys[pygame.K_RIGHT]:
new_rect = player.rect.move(1, 0)
next_col = new_rect.right // CELL_SIZE
if col_r == next_col or not (m.maze[col_r][row_t].walls or m.maze[col_r][row_b].walls):
player.rect = new_rect
if keys[pygame.K_UP]:
new_rect = player.rect.move(0, -1)
next_row = new_rect.top // CELL_SIZE
if row_t == next_row or not (m.maze[col_l][row_t].walls or m.maze[col_r][row_t].walls):
player.rect = new_rect
if keys[pygame.K_DOWN]:
new_rect = player.rect.move(0, 1)
next_row = new_rect.bottom // CELL_SIZE
if row_b == next_row or not (m.maze[col_l][row_b].walls or m.maze[col_r][row_b].walls):
player.rect = new_rect

SCREEN.fill(WHITE)
for i in range(m.cols):
for j in range(m.rows):
m.maze[i][j].draw_cell()
all_sprites.draw(SCREEN)
pygame.display.flip()

if __name__ == "__main__":
main()
pygame.quit()
``````