我在C#中有这个SokobanSolver控制台应用程序,它主要来自某些网站,但是我做了一些改动。问题是,它太慢了,当我使用大型拼图(例如192x24网格)时,它会由于内存不足异常而崩溃。我有各种想法可以解决此问题,但似乎没有一个可行。
问题是它创建了一个大字符串列表,并以192x24网格包含4608个字符。由于使用了BFS,因此它会检查所有可能性,即使仅举一个小例子,也需要大约400次尝试才能获得正确的路径。因此,现在我有了一个长度为859251的数组,其中包含4608个字符,每个数组最后都太多了。完成大约需要6-8分钟。
下面是一个示例,其中W是一堵墙?是一个目标,!是一个盒子,+是一个玩家。解决方案将是9,LLUUULURR。 (左,上,右)。
WWWWWWWW
W....?.W
W....WWW
W....WWW
W..!...W
W....+.W
W......W
WWWWWWWW
这是我查看玩家是否可以推箱子的方法,我为玩家几乎拥有一个相同的箱子。最终方法就是当盒子对准目标时。
public string Push(string smap, int x, int y, int dx, int dy)
{
// w = width
int cur = y * w + x;
int newcur = (y + 2 * dy) * w + x + 2 * dx;
int player = (y + dy) * w + (x + dx);
if (smap[newcur] != '.')
return "false";
char[] map = smap.ToCharArray();
map[player] = '+';
map[cur] = '.';
map[newcur] = '!';
string res = string.Join("", map);
return res;
}
这是我的使用队列的BFS方法
public string BFS()
{
Queue<Node> Q = new Queue<Node>();
Dictionary<Node, char> D = new Dictionary<Node, char>();
ISet<string> visited = new HashSet<string>();
Queue<string> steps = new Queue<string>();
Queue<string> blueprint = new Queue<string>();
steps.Enqueue("");
Node North = new Node(-1, 0);
Node South = new Node(1, 0);
Node East = new Node(0, 1);
Node West = new Node(0, -1);
D.Add(North, 'U');
D.Add(South, 'D');
D.Add(East, 'R');
D.Add(West, 'L');
Q.Enqueue(new Node(posx, posy));
// mapvar is the original blueprint
blueprint.Enqueue(mapvar);
while (Q.Count > 0)
{
Node start = Q.Dequeue();
int x = start.x;
int y = start.y;
string map1 = blueprint.Dequeue();
string step = steps.Dequeue();
for (int i = 0; i < 4; i++)
{
int DX = 0; int DY = 0;
List<int> dxl = new List<int>();
List<int> dyl = new List<int>();
string map = map1;
foreach (KeyValuePair<Node, char> kp in D)
{
DX = kp.Key.x;
DY = kp.Key.y;
dxl.Add(kp.Key.x);
dyl.Add(kp.Key.y);
}
int dx = dxl[i];
int dy = dyl[i];
int move = b * (y + dy) + x + dx;
if (map[(y + dy) * b + x + dx] == '!')
{
if ((map = Push(map, x, y, dx, dy)) != "false")
{
if (!visited.Contains(map))
{
string st = "";
if (dy == -1)
st = step + D[North];
if (dy == 1)
st = step + D[South];
if (dx == 1)
st = step + D[East];
if (dx == -1)
st = step + D[West];
steps.Enqueue(st);
Q.Enqueue(new Node(x + dx, y + dy));
visited.Add(map);
blueprint.Enqueue(map);
if (End(map))
return st;
}
}
}
else if ((map = Push(map, x, y, dx, dy)) != "false")
{
if (!visited.Contains(map))
{
string st = "";
if (dy == -1)
st = step + D[North];
if (dy == 1)
st = step + D[South];
if (dx == 1)
st = step + D[East];
if (dx == -1)
st = step + D[West];
steps.Enqueue(st);
Q.Enqueue(new Node(x + dx, y + dy));
blueprint.Enqueue(map);
visited.Add(map);
}
}
}
}
return "false";
}
我认为用节点或坐标而不是字符串来做可能更聪明。问题是,我不确定怎么做,因为我尝试的方法不起作用。我希望有人能帮帮忙。它可以工作,但是太慢了。我真的很想使用BFS,所以我希望有一个可以使用它的解决方案。