Kibor |
Отправлено: 24 Марта, 2023 - 14:50:40
|
Эксперт
Просматривает форум
Сообщений всего: 8226
Дата рег-ции: Март 2013
Откуда: Одесса
Репутация: 357
|
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;
}
Это к теме оптимизации кода по размеру у кого код такого рамера, что Кибор глючит |
|
|
Dantes3000 |
Отправлено: 25 Марта, 2023 - 10:29:53
|
Эксперт
Покинул форум
Сообщений всего: 1489
Дата рег-ции: Июнь 2016
Репутация: 58
|
Zireael пишет: Начало всегда в левой верхней клетке?
Как определять где конец лабиринта? Всегда на нижней границе или может сбоку?
Лучше несколько вариантов лабиринта выложить.
начало может быть в рандомном месте сверху. Конец в рандомном месте снизу. Сбоку не может быть.
(Добавление)
Kibor пишет: Это координата входа. Может быть в другом месте. Алгоритм будет идти пока есть куда. Или не выйдет с лабиринта.
да...забыл уточнить. Вход надо тоже определить |
|
|
Zireael |
Отправлено: 26 Марта, 2023 - 23:46:24
|
Эксперт
Покинул форум
Сообщений всего: 4468
Дата рег-ции: Нояб. 2017
Репутация: 585
|
Цитата: Если не заморачиваясь
Тогда и не работает как надо. Если будет несколько вариантов куда можно двигаться, то проверит только 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("Путь не найден");
Код длл (Отобразить)CODE:#include "pch.h"
#include <format>
#include <regex>
using namespace std;
const int X = 7;
const int Y = 4;
const int N_MAX = 50;
auto lab = new int[X][Y];
string result[N_MAX];
int CountHod;
bool exit_found;
void CopyArray(int lab[X][Y], int lab2[X][Y])
{
for (int i = 0; i < X; i++)
for (int j = 0; j < Y; j++) lab2[i][j] = lab[i][j];
}
void FindPathFunc(int N, int x, int y, int lab[X][Y])
{
if (N + 1 >= N_MAX) return;
auto labCopy = new int[X][Y];
CopyArray(lab, labCopy);
labCopy[x][y] = 3;
int CurrentKey = (N + 1) % 3;
if (x + 1 == X) // дошли до нижней границы
{
exit_found = true;
CountHod = N;
return;
}
if (!exit_found && x > 0 && labCopy[x - 1][y] == CurrentKey) // вверх
{
result[++N] = std::format("Up {}, {}", --x, y);
FindPathFunc(N--, x++, y, labCopy);
}
if (!exit_found && x + 1 < X && labCopy[x + 1][y] == CurrentKey) // вниз
{
result[++N] = std::format("Down {}, {}", ++x, y);
FindPathFunc(N--, x--, y, labCopy);
}
if (!exit_found && y > 0 && labCopy[x][y - 1] == CurrentKey) // влево
{
result[++N] = std::format("Left {}, {}", x, --y);
FindPathFunc(N--, x, y++, labCopy);
}
if (!exit_found && y + 1 < Y && labCopy[x][y + 1] == CurrentKey) // вправо
{
result[++N] = std::format("Right {}, {}", x, ++y);
FindPathFunc(N--, x, y--, labCopy);
}
delete[] labCopy;
return;
}
extern "C" __declspec(dllexport)int FindPath(int* arr, char* result_str)
{
string EndX = "", EndY = "";
const regex r("(\\d+).+?(\\d+)");
smatch m;
for (int i = 0; i < X; i++)
for (int j = 0; j < Y; j++)
lab[i][j] = arr[j + i * Y];
CountHod = 0;
exit_found = false;
for (int i = 0; i < 4; i++)
{
if (exit_found) break;
if (lab[0][i] != 0) continue;
result[0] = std::format("Start 0, {}", i);
FindPathFunc(0, 0, i, lab);
}
if (!exit_found) return 0;
if (regex_search(result[CountHod++], m, r))
{
EndX = m[1].str();
EndY = m[2].str();
}
result[CountHod] = std::format("Down {}, {}", EndX, EndY);
string resultS = "";
for (int i = 0; i < CountHod; i++) resultS += result[i] + "\r\n";
strcpy(result_str, resultS.c_str());
return CountHod;
} |
|
|
Zireael |
Отправлено: 28 Марта, 2023 - 15:27:44
|
Эксперт
Покинул форум
Сообщений всего: 4468
Дата рег-ции: Нояб. 2017
Репутация: 585
|
Цитата: через 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); |
|
|
|