Кибор » Кибор - Интегрированная среда разработки ботов » Вопросы и решение проблем » Найти путь по лабиринту (не findpath)

Страниц (1): [1]
 

1. Dantes3000 - 24 Марта, 2023 - 06:44:52 - перейти к сообщению
CODE:
string key_order[3]={"Ж", "К", "З"};
string lab[4][7];
/*
[Ж][З][Ж][З]
[К][З][Ж][Ж]
[Ж][К][К][К]
[К][Ж][З][Ж]
[З][З][К][З]
[Ж][З][Ж][З]
[К][Ж][К][Ж]
*/

lab[0][0]="Ж"; lab[1][0]="З"; lab[2][0]="Ж"; lab[3][0]="З";
lab[0][1]="К"; lab[1][1]="З"; lab[2][1]="Ж"; lab[3][1]="Ж";
lab[0][2]="Ж"; lab[1][2]="К"; lab[2][2]="К"; lab[3][2]="К";
lab[0][3]="К"; lab[1][3]="Ж"; lab[2][3]="З"; lab[3][3]="Ж";
lab[0][4]="З"; lab[1][4]="З"; lab[2][4]="К"; lab[3][4]="З";
lab[0][5]="Ж"; lab[1][5]="З"; lab[2][5]="Ж"; lab[3][5]="З";
lab[0][6]="К"; lab[1][6]="Ж"; lab[2][6]="К"; lab[3][6]="Ж";


Есть лабиринт по цветам - желтый, красный, зеленый.
Идти можно только поочередно по каждому цвету, после зеленого идет снова желтый.
Назад идти нельзя. Есть только один путь. Размер лабаринта одинаковый.

Есть идеи как можно реализовать? Нужно получить массив в какую сторону идти дальше.
Пример решения лабиринта со скриншота:

начало в клетке 1, потом низ - право - право - низ - низ - лево - лево - низ - низ - низ


Нажмите для увеличения
2. Zireael - 24 Марта, 2023 - 07:36:53 - перейти к сообщению
Начало всегда в левой верхней клетке?
Как определять где конец лабиринта? Всегда на нижней границе или может сбоку?
Лучше несколько вариантов лабиринта выложить.
3. Kibor - 24 Марта, 2023 - 07:50:40 - перейти к сообщению
 Dantes3000 пишет:
Есть идеи как можно реализовать? Нужно получить массив в какую сторону идти дальше.


Если не заморачиваясь примитивно разжевано так:
CODE:
string lab[4][7];
int X=sizearray(lab);
int Y=sizearray(lab[]);
new int LAB[X][Y];
initialarray(#LAB[0][0], 0);
/*
[Ж][З][Ж][З]
[К][З][Ж][Ж]
[Ж][К][К][К]
[К][Ж][З][Ж]
[З][З][К][З]
[Ж][З][Ж][З]
[К][Ж][К][Ж]
*/

lab[0][0]="Ж"; lab[1][0]="З"; lab[2][0]="Ж"; lab[3][0]="З";
lab[0][1]="К"; lab[1][1]="З"; lab[2][1]="Ж"; lab[3][1]="Ж";
lab[0][2]="Ж"; lab[1][2]="К"; lab[2][2]="К"; lab[3][2]="К";
lab[0][3]="К"; lab[1][3]="Ж"; lab[2][3]="З"; lab[3][3]="Ж";
lab[0][4]="З"; lab[1][4]="З"; lab[2][4]="К"; lab[3][4]="З";
lab[0][5]="Ж"; lab[1][5]="З"; lab[2][5]="Ж"; lab[3][5]="З";
lab[0][6]="К"; lab[1][6]="Ж"; lab[2][6]="К"; lab[3][6]="Ж";


int N=1;
int x=0, y=0;
LAB[x][y]=N;
loop()
{
if (lab[x][y]=="Ж")
{
if (x>0){if (LAB[x-1][y]==0){if(lab[x-1][y]=="К") {N++; LAB[x-1][y]=N; x--; continue;}}}
if (y>0){if (LAB[x][y-1]==0){if(lab[x][y-1]=="К") {N++; LAB[x][y-1]=N; y--; continue;}}}
if (x+1<X){if (LAB[x+1][y]==0){if(lab[x+1][y]=="К") {N++; LAB[x+1][y]=N; x++; continue;}}}
if (y+1<Y){if (LAB[x][y+1]==0){if(lab[x][y+1]=="К") {N++; LAB[x][y+1]=N; y++; continue;}}}
}
if (lab[x][y]=="К")
{

if (x>0){if (LAB[x-1][y]==0){if(lab[x-1][y]=="З") {N++; LAB[x-1][y]=N; x--; continue;}}}
if (y>0){if (LAB[x][y-1]==0){if(lab[x][y-1]=="З") {N++; LAB[x][y-1]=N; y--; continue;}}}
if (x+1<X){if (LAB[x+1][y]==0){if(lab[x+1][y]=="З") {N++; LAB[x+1][y]=N; x++; continue;}}}
if (y+1<Y){if (LAB[x][y+1]==0){if(lab[x][y+1]=="З") {N++; LAB[x][y+1]=N; y++; continue;}}}
}
if (lab[x][y]=="З")
{
if (x>0){if (LAB[x-1][y]==0){if(lab[x-1][y]=="Ж") {N++; LAB[x-1][y]=N; x--; continue;}}}
if (y>0){if (LAB[x][y-1]==0){if(lab[x][y-1]=="Ж") {N++; LAB[x][y-1]=N; y--; continue;}}}
if (x+1<X){if (LAB[x+1][y]==0){if(lab[x+1][y]=="Ж") {N++; LAB[x+1][y]=N; x++; continue;}}}
if (y+1<Y){if (LAB[x][y+1]==0){if(lab[x][y+1]=="Ж") {N++; LAB[x][y+1]=N; y++; continue;}}}
}
break;
}







string Rez="";
for (y=0; y<Y; y++)
{
for (x=0; x<X; x++)
{
Rez=Rez+format(LAB[x][y])+" ";
}
Rez=Rez+"^r^n";
}

messagebox (Rez);


И проверки типа if (LAB[x-1][y]==0) вообще не нужны, так как строгая очередность цветов и назад он все равно не пойдет. Они нужны только если есть клетка проходи и тупика. И он может пойти назад.


 Цитата:
int x=0, y=0;

Это координата входа. Может быть в другом месте. Алгоритм будет идти пока есть куда. Или не выйдет с лабиринта.


Или сжато. То же самое
CODE:
string key_order[3]={"Ж", "К", "З"};
string lab[4][7];
int X=sizearray(lab);
int Y=sizearray(lab[]);
new int LAB[X][Y];
initialarray(#LAB[0][0], 0);
/*
[Ж][З][Ж][З]
[К][З][Ж][Ж]
[Ж][К][К][К]
[К][Ж][З][Ж]
[З][З][К][З]
[Ж][З][Ж][З]
[К][Ж][К][Ж]
*/

lab[0][0]="Ж"; lab[1][0]="З"; lab[2][0]="Ж"; lab[3][0]="З";
lab[0][1]="К"; lab[1][1]="З"; lab[2][1]="Ж"; lab[3][1]="Ж";
lab[0][2]="Ж"; lab[1][2]="К"; lab[2][2]="К"; lab[3][2]="К";
lab[0][3]="К"; lab[1][3]="Ж"; lab[2][3]="З"; lab[3][3]="Ж";
lab[0][4]="З"; lab[1][4]="З"; lab[2][4]="К"; lab[3][4]="З";
lab[0][5]="Ж"; lab[1][5]="З"; lab[2][5]="Ж"; lab[3][5]="З";
lab[0][6]="К"; lab[1][6]="Ж"; lab[2][6]="К"; lab[3][6]="Ж";

int t=0, g=t+1;
int N=1;
int x=0, y=0;
int E=0;
LAB[x][y]=N;
loop()
{
W:;
if (lab[x][y]==key_order[t])
{
if (x>0){if(lab[x-1][y]==key_order[g]) {N++; LAB[x-1][y]=N; x--; E=0; t++; if (t>2) t=0; g=t+1; if (g>2) g=0; continue;}}
if (y>0){if(lab[x][y-1]==key_order[g]) {N++; LAB[x][y-1]=N; y--; E=0; t++; if (t>2) t=0; g=t+1; if (g>2) g=0; continue;}}
if (x+1<X){if(lab[x+1][y]==key_order[g]) {N++; LAB[x+1][y]=N; x++; E=0; t++; if (t>2) t=0; g=t+1; if (g>2) g=0; continue;}}
if (y+1<Y){if(lab[x][y+1]==key_order[g]) {N++; LAB[x][y+1]=N; y++; E=0; t++; if (t>2) t=0; g=t+1; if (g>2) g=0; continue;}}
}
E++; if (E>3) break;
t++; if (t>2) t=0; g=t+1; if (g>2) g=0;
goto W;
break;
}







string Rez="";
for (y=0; y<Y; y++)
{
for (x=0; x<X; x++)
{
Rez=Rez+format(LAB[x][y])+" ";
}
Rez=Rez+"^r^n";
}

messagebox (Rez);


Или сжатый еще
CODE:
loop()
{
W:;
if (lab[x][y]==key_order[t])
{
if (x>0){if (find(-1, 0)) continue;}
if (y>0){if (find(0, -1)) continue;}
if (x+1<X){if (find(1, 0)) continue;}
if (y+1<Y){if (find(0, 1)) continue;}
}
E++; if (E>3) break;
t++; if (t>2) t=0; g=t+1; if (g>2) g=0;
goto W;
break;
}

function find(int xx, int yy)
{
if(lab[x+xx][y+yy]==key_order[g]) {N++; LAB[x+xx][y+yy]=N; x=x+xx; y=y+yy; E=0; t++; if (t>2) t=0; g=t+1; if (g>2) g=0; return 1;}
return 0;
}

Это к теме оптимизации кода по размеру у кого код такого рамера, что Кибор глючит
4. Dantes3000 - 25 Марта, 2023 - 03:29:53 - перейти к сообщению
 Zireael пишет:
Начало всегда в левой верхней клетке?
Как определять где конец лабиринта? Всегда на нижней границе или может сбоку?
Лучше несколько вариантов лабиринта выложить.


начало может быть в рандомном месте сверху. Конец в рандомном месте снизу. Сбоку не может быть.
(Добавление)
 Kibor пишет:
Это координата входа. Может быть в другом месте. Алгоритм будет идти пока есть куда. Или не выйдет с лабиринта.


да...забыл уточнить. Вход надо тоже определить
5. Zireael - 26 Марта, 2023 - 15:46:24 - перейти к сообщению
 Цитата:
Если не заморачиваясь

Тогда и не работает как надо. Если будет несколько вариантов куда можно двигаться, то проверит только 1 вариант.
 Цитата:
lab[1][3]="Ж"; lab[2][3]="З"; lab[3][3]="Ж";

С точки lab[2][3] двигаться можно влево и вправо...

 Цитата:
начало может быть в рандомном месте сверху. Конец в рандомном месте снизу.
Вход надо тоже определить

Длл распаковать и закинуть в папку с кибор. Проверял только на win10.
https://drive.google.com/file/d/...view?usp=sharing

Функция возвращает количество ходов, строку с направлением движения и координатами, такого вида:
 Цитата:
Start 0, 0
Down 1, 0
Right 1, 1
Right 1, 2
и т. д.

Right 1, 2 означает: Right - двигаемся вправо, 1 - номер строки, 2 - номер столбца.
Регуляркой можно получить необходимые данные.

CODE:
external(INT, "FindPath", "FindPath", "FindPath.dll");

char result[999];
int lab[7][4]; // 7 строк, 4 столбца

// 0 - Жёлтый, 1 - Красный, 2 - Зелёный.
lab[0][0] = 0; lab[0][1] = 2; lab[0][2] = 0; lab[0][3] = 2;
lab[1][0] = 1; lab[1][1] = 2; lab[1][2] = 0; lab[1][3] = 0;
lab[2][0] = 0; lab[2][1] = 1; lab[2][2] = 1; lab[2][3] = 1;
lab[3][0] = 1; lab[3][1] = 0; lab[3][2] = 2; lab[3][3] = 0;
lab[4][0] = 2; lab[4][1] = 2; lab[4][2] = 1; lab[4][3] = 2;
lab[5][0] = 0; lab[5][1] = 2; lab[5][2] = 0; lab[5][3] = 2;
lab[6][0] = 1; lab[6][1] = 0; lab[6][2] = 1; lab[6][3] = 0;

int CountHod = FindPath(address(#lab[0][0]), address(#result[0]));
if(CountHod>0)
{
messagebox("Всего ходов: "+format(CountHod));
messagebox(format(#result[0]));
}
else messagebox("Путь не найден");


Код длл (Отобразить)
6. Dantes3000 - 28 Марта, 2023 - 04:11:41 - перейти к сообщению
Спасибо за помощь, работает идеально.


Может еще есть идеи как распознать лабиринт? Разные цвета, оттенки, моргает всё.
Думаю можно через findshape или через обычный findimage.

через sumcolor не выходит, много ошибок. Но наверное можно найти иделаьные параметры.

Там проблема в том, что многие цвета совпадают для всех ячеек, тем более если с расбежностью делать


Нажмите для увеличения
7. Kibor - 28 Марта, 2023 - 06:31:53 - перейти к сообщению
findheapcolor
8. Zireael - 28 Марта, 2023 - 07:27:44 - перейти к сообщению
 Цитата:
через sumcolor не выходит, много ошибок.

Нужно использовать разницу каналов. Если цвет красный, значит в нём большое значение красного канала и маленькое (точнее значительно меньше) зелёного и синего. Если цвет зелёный, значит большое значение зелёного канала и маленькое остальных.
К примеру:
Красный: rgb(180, 34, 36) много красного
Зелёный: rgb(9, 188, 8) много зелёного
Жёлтый: rgb(204, 209, 131) много красного и зелёного

Тут правильнее искать по разнице каналов, но такого поиска нет, так что исходим из того что есть.
CODE:
// координаты поля
// левый верхний угол левой верхней клетки
// правый нижний угол правой нижней клетки
int coord_field[4] = {17, 160, 397, 818};


int i, j, k;
int lab[7][4], result[3];
int scr[999][999]; // массив для скрина поля

// считаем размер клетки
int cellX = (coord_field[2] - coord_field[0]) / 4;
int cellY = (coord_field[3] - coord_field[1]) / 7;

// искомые цвета цвета
int Yellow = rgb(100, 100, 0); // жёлтый
int Red = rgb(100, 0, 0); // красный
int Green = rgb(0, 100, 0); // зелёный
int Colors[3] = {Yellow, Red, Green};

// отклонение цвета
int Deviation[3][3];
Deviation[0][0] = 155; Deviation[0][1] = 155; Deviation[0][2] = 100; // для жёлтого
Deviation[1][0] = 155; Deviation[1][1] = 100; Deviation[1][2] = 100; // для зелёного
Deviation[2][0] = 100; Deviation[2][1] = 155; Deviation[2][2] = 100; // для красного

pause(500); // пауза чтоб кибор свернулся

// скрин поля
screen (#scr[0][0], coord_field[0], coord_field[1], coord_field[2], coord_field[3], -1);


// распознавание клеток
for(i=0; i<7; i++)
{
for(j=0; j<4; j++)
{
// получить количество цветов клетки
for(k=0; k<3; k++)
{
result[k] = sumcolor(-1, cellX * j + 5, cellY * i + 5, cellX * (j + 1) - 5, cellY * (i + 1) - 5,
Colors[k], 0, Deviation[k][0], 0, Deviation[k][1], 0, Deviation[k][2], #scr[0][0]);
}

// проверка какого цвета больше всего
if(result[0]>result[1] && result[0]>result[2]) lab[i][j] = 0; // жёлтый
else
{
if(result[1]>result[2]) lab[i][j] = 1; // красный
else lab[i][j] = 2; // зелёный
}
}
}


// вывод массива
for(i=0; i<7; i++)
{
string tmp = "";
for(j=0; j<4; j++) tmp = tmp + format(lab[i][j]);
textout(i, 200, 100 + i * 20, tmp, 0);
}
loop()sleep(10);

Powered by ExBB FM 1.0 Final