【推箱子问题求解】

计算推箱子游戏的人物行走路径

推箱子游戏界面

将推箱子的游戏界面定义为一个矩阵,通过矩阵中存储的数字表示游戏的初始状态。
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("未找到可行路径。")

目前,该解法适用于箱子较少场景,解法还有待改进。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值