2 hours ago, swiftcoder said:
Breadth-first search is sufficient for this case, is simpler to write, and has the better time-complexity than the most optimal variants of A* or Djikstra.
I became a bit uncertain. Below is the code i've in mind, please take a look if you think it can be improved. To me this is still Dijkstra, it just uses BFS instead priority queue.
@EddieK
This proofs additional flag like in your code is not necessary, i use only one stream of data for everything.
It should also be possible to avoid the previous array, and instead search for the closest neighbour by looking at the distance stored in data to build the path. Depends on how many paths you extract what's better.
int data [8*8] = {
1,1,1,1,1,1,1,1,
1,0,0,0,0,7,0,1,
1,0,0,0,0,0,0,1,
1,0,0,1,1,1,1,1,
1,0,0,1,0,9,0,1,
1,0,0,1,0,0,0,1,
1,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1};
int start = 0, target = 0;
for (int i=0; i<64; i++)
{
int x = data[i];
if (x==7) start = i;
if (x==9) target = i;
data[i] = (x == 1 ? 1000 : 999);
}
int previous[64] = {};
int stack[64];
stack[0] = target;
data[target] = 0;
int tail = 1;
for (int i=0; i<tail; i++)
{
int c = stack[i];
int distC = data[c];
int distN = distC + 1;
//if (c==start) break; // optional early out if we want only one path
int x = c&7;
int y = (c>>3);
for (int j=0; j<4; j++)
{
int n = c;
switch (j)
{
case 0: n++; break;
case 1: n--; break;
case 2: n+=8; break;
default: n-=8;
}
if (data[n] == 1000) continue;
if (distN < data[n])
{
data[n] = distN;
previous[n] = c;
stack[tail++] = n;
}
}
}
char output[8][9] = {};
for (int y=0; y<8; y++) for (int x=0; x<8; x++)
{
output[y][x] = data[y*8+x] == 1000 ? 'X' : ' ';
}
int path = start;
while (path)
{
output[path>>3][path&7] = '@';
path = previous[path];
}
for (int y=0; y<8; y++)
{
SystemTools::Log(output[y]);
SystemTools::Log("\n");
}
ouput:
XXXXXXXX
X @ X
X @@@@ X
X @XXXXX
X @X@@ X
X @X@ X
X @@@ X
XXXXXXXX