推箱子游戏界面
将推箱子的游戏界面定义为一个矩阵,通过矩阵中存储的数字表示游戏的初始状态。
4代表人物
3代表箱子
2代表箱子的目标位置
1代表障碍物
-1代表初始界面外,人物不可走到界面外
条件约束
人物不可穿过箱子,也不可与箱子同位置
人物只能推动箱子,即人物在箱子移动方向的反侧,例如箱子向左移动时,人物在箱子的右侧
BFS广度优先搜素
import numpy as np
from collections import deque
def find_path(started_matrix):
rows, cols = started_matrix.shape
# 找到人物和箱子的初始位置
start_person_pos = None
boxes = []
targets = []
for i in range(rows):
for j in range(cols):
if started_matrix[i, j] == 4:
start_person_pos = (i, j)
elif started_matrix[i, j] == 3:
boxes.append((i, j))
elif started_matrix[i, j] == 2:
targets.append((i, j))
# 初始化队列和访问集合,保留箱子顺序
initial_boxes = tuple(boxes)
queue = deque([(start_person_pos, initial_boxes, [start_person_pos])])
visited = set([(start_person_pos, initial_boxes)])
#定义上下左右四个方向
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
while queue:
person_pos, current_boxes, path = queue.popleft()
x, y = person_pos
# 检查胜利条件:所有箱子在目标位置且不重复
if all(box in targets for box in current_boxes) and len(set(current_boxes)) == len(targets):
return path
for dx, dy in directions:
new_x, new_y = x + dx, y + dy
new_person_pos = (new_x, new_y)
# 检查新位置是否越界或障碍
if (new_x < 0 or new_x >= rows or new_y < 0 or new_y >= cols or
started_matrix[new_x, new_y] == -1 or started_matrix[new_x, new_y] == 1):
continue
new_boxes = list(current_boxes)
box_pushed = False
# 检查是否推动箱子
if new_person_pos in current_boxes:
box_index = current_boxes.index(new_person_pos)
box_new_x, box_new_y = new_x + dx, new_y + dy
box_new_pos = (box_new_x, box_new_y)
# 检查箱子新位置是否合法
if (box_new_x < 0 or box_new_x >= rows or box_new_y < 0 or box_new_y >= cols or
started_matrix[box_new_x, box_new_y] in (-1, 1) or
box_new_pos in new_boxes):
continue
new_boxes[box_index] = box_new_pos
box_pushed = True
# 未推动时,检查是否移动到箱子位置
if not box_pushed and new_person_pos in current_boxes:
continue
# 死锁检测
deadlock = False
for box in new_boxes:
if box in targets:
continue
can_move = False
for ddx, ddy in directions:
next_box = (box[0] + ddx, box[1] + ddy)
# 检查箱子新位置是否合法
if (next_box[0] < 0 or next_box[0] >= rows or
next_box[1] < 0 or next_box[1] >= cols or
started_matrix[next_box[0], next_box[1]] in (-1, 1)):
continue
# 检查人物能否到达推动位置
person_needed = (box[0] - ddx, box[1] - ddy)
if (person_needed[0] < 0 or person_needed[0] >= rows or
person_needed[1] < 0 or person_needed[1] >= cols or
started_matrix[person_needed[0], person_needed[1]] in (-1, 1)):
continue
# 检查推动位置是否被其他箱子占据
if person_needed in new_boxes:
continue
can_move = True
break
if not can_move:
deadlock = True
break
if deadlock:
continue
new_state = (new_person_pos, tuple(new_boxes))
if new_state not in visited:
visited.add(new_state)
new_path = path + [new_person_pos]
queue.append((new_person_pos, tuple(new_boxes), new_path))
return None
# 测试代码
started = [[-1,0, 2, 0],
[0, 0, 0, 0],
[0, 3, 2, 0],
[0, 3, 1, 0],
[4, 0, 0, 0]]
started_matrix = np.array(started)
path = find_path(started_matrix)
if path:
print("人物的移动路径坐标:", path)
else:
print("未找到可行路径。")
目前,该解法适用于箱子较少场景,解法还有待改进。