入门小白,大佬慎入
讲的比较简单,不是很详细,提供一个思路。
目录:
- 成果展示
- 代码说明
- 完整代码
- 其他补充和参考资料
——————分割线————————
1.成果展示
实现功能:
1.显示走过的路径(再次走过可消除)
2.自动追踪并显示最优路径
2.代码说明
(1)创建基础的Map类
import pygame
from random import randint, choice
from enum import Enum
from sys import exit
REC_SIZE = 10
REC_WIDTH = 51 # must be odd number
REC_HEIGHT = 51 # must be odd number
SCREEN_WIDTH = REC_WIDTH * REC_SIZE
SCREEN_HEIGHT = REC_HEIGHT * REC_SIZE
# 创建地图格子种类枚举类
class MAP_ENTRY_TYPE(Enum):
MAP_EMPTY = 0,
MAP_BLOCK = 1,
MAP_TARGET = 2,
MAP_PATH = 3,
MAP_DONE = 4
# 创建一个格子方法枚举类
class WALL_DIRECTION(Enum):
WALL_LEFT = 0,
WALL_UP = 1,
WALL_RIGHT = 2,
WALL_DOWN = 3,
# 用字典存储格子枚举类型
map_entry_types = {0: MAP_ENTRY_TYPE.MAP_EMPTY, 1: MAP_ENTRY_TYPE.MAP_BLOCK,
2: MAP_ENTRY_TYPE.MAP_TARGET, 3: MAP_ENTRY_TYPE.MAP_PATH, 4: MAP_ENTRY_TYPE.MAP_DONE}
"""基础MAP类生成并控制格子"""
class Map:
# 初始化地图长宽
def __init__(self, width, height):
self.width = width
self.height = height
self.map = [[0 for x in range(self.width)] for y in range(self.height)]
# 创建一定数量的墙壁
def createBlock(self, block_num):
for i in range(block_num):
x, y = (randint(0, self.width - 1), randint(0, self.height - 1))
self.map[y][x] = 1
# 在范围内随机选找到路径
def generatePos(self, rangeX, rangeY):
x, y = (randint(rangeX[0], rangeX[1]), randint(rangeY[0], rangeY[1]))
while self.map[y][x] == 1:
x, y = (randint(rangeX[0], rangeX[1]), randint(rangeY[0], rangeY[1]))
return x, y
# 将整个地图重置为指定类型
def resetMap(self, value):
for y in range(self.height):
for x in range(self.width):
self.setMap(x, y, value)
# 将一个格子设置为指定类型
def setMap(self, x, y, value):
if value == MAP_ENTRY_TYPE.MAP_EMPTY:
self.map[y][x] = 0
elif value == MAP_ENTRY_TYPE.MAP_BLOCK:
self.map[y][x] = 1
elif value == MAP_ENTRY_TYPE.MAP_TARGET:
self.map[y][x] = 2
elif value == MAP_ENTRY_TYPE.MAP_PATH:
self.map[y][x] = 3
else:
self.map[y][x] = 4
# 判断一个格子是否可以访问
def isVisited(self, x, y):
return self.map[y][x] != 1
# 判断一个格子是否可移动
def isMovable(self, x, y):
return self.map[y][x] != 1
# 判断格子是否在地图内
def isValid(self, x, y):
if x < 0 or x >= self.width or y < 0 or y >= self.height:
return False
return True
# 返回格子类型
def getType(self, x, y):
return map_entry_types[self.map[y][x]]
创建Map类,用来生成地图,并操控地图中每个格子(或者点)
两个枚举类是便于后面操作格子,便于理解
(2)创建迷宫生成函数
"""迷宫生成算法"""
# 找到四个相位中没有被遍历过的格子
# 随机遍历一个,将其放入遍历过的方格列表
def checkAdjacentPos(map, x, y, width, height, checklist):
directions = []
if x > 0:
if not map.isVisited(2 * (x - 1) + 1, 2 * y + 1):
directions.append(WALL_DIRECTION.WALL_LEFT)
if y > 0:
if not map.isVisited(2 * x + 1, 2 * (y - 1) + 1):
directions.append(WALL_DIRECTION.WALL_UP)
if x < width - 1:
if not map.isVisited(2 * (x + 1) + 1, 2 * y + 1):
directions.append(WALL_DIRECTION.WALL_RIGHT)
if y < height - 1:
if not map.isVisited(2 * x + 1, 2 * (y + 1) + 1):
directions.append(WALL_DIRECTION.WALL_DOWN)
if len(directions):
direction = choice(directions)
# print("(%d, %d) => %s" % (x, y, str(direction)))
if direction == WALL_DIRECTION.WALL_LEFT:
map.setMap(2 * (x - 1) + 1, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x - 1, y))
elif direction == WALL_DIRECTION.WALL_UP:
map.setMap(2 * x + 1, 2 * (y - 1) + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x + 1, 2 * y, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x, y - 1))
elif direction == WALL_DIRECTION.WALL_RIGHT:
map.setMap(2 * (x + 1) + 1, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x + 2, 2 * y + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x + 1, y))
elif direction == WALL_DIRECTION.WALL_DOWN:
map.setMap(2 * x + 1, 2 * (y + 1) + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
map.setMap(2 * x + 1, 2 * y + 2, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist.append((x, y + 1))
return True
else:
# 如果没有找到相邻的未遍历方格
return False
# 递归回溯实现
def recursiveBacktracker(map, width, height):
startX, startY = (randint(0, width - 1), randint(0, height - 1))
print("start(%d, %d)" % (startX, startY))
map.setMap(2 * startX + 1, 2 * startY + 1, MAP_ENTRY_TYPE.MAP_EMPTY)
checklist = []
checklist.append((startX, startY))
while len(checklist):
# 将检查列表用作堆栈,从栈顶获取元素
entry = checklist[-1]
if not checkAdjacentPos(map, entry[0], entry[1], width, height, checklist):
# 格子四周没有可以未遍历的路径,则将这个格子从栈顶删除
checklist.remove(entry)
# 迷宫生成
def doRecursiveBacktracker(map):
# 将所以有格子设为墙壁
map.resetMap(MAP_ENTRY_TYPE.MAP_BLOCK)
# 用算法产生迷宫
recursiveBacktracker(map, (map.width - 1) // 2, (map.height - 1) // 2)
这里我使用的是以深度优先为主的递归回溯算法
随机选择一个空白方格开始,然后随机选择一个不在checklist内的相邻空白方格,将它们之间的墙壁格子转换为空白格子,然后把选择的空白方格放入checklis列表里。
递归上面的步骤没有可选择的空白方格,就删除这个方格,继而遍历前一个方格。如此往复,直到checklist列表里没有元素(即所有的方格都被遍历完),停止。
(3)实现A*算法自动寻路
"&#