Zireael |
Отправлено: 30 Сентября, 2018 - 12:57:05
|
Эксперт
Покинул форум
Сообщений всего: 4464
Дата рег-ции: Нояб. 2017
Репутация: 585
|
Цитата: Тоже самое в 1.5 раза быстрее
Исправил небольшой баг. Строку temp не очистил при сборке в строку массива по вертикали.
function proverka (Отобразить)CODE:function proverka(int X, int Y)//Оценивает после замены ситуацию. Находит все совпавшие линии ровные присваивая им оценку равную кол фишек.
{
int tOcenka=-1;
int x, y;
string R="(\d)\1{7}|(\d)\2{6}|(\d)\3{5}|(\d)\4{4}|(\d)\5{3}|(\d)\6{2}"; // подряд идущие числа от 8 до 3, например 55555 или 3333333
string temp="";
for (y=0; y<Y; y++){for (x=0; x<X; x++)temp=temp+format(mas_pole[x][y]);temp=temp+" ";} // массив в 1 строку
if(regexsearch(1, #temp, temp, R)>0){if (size(temp)>tOcenka)tOcenka=size(temp);} // поиск подряд идущих чисел от 8 до 3
temp="";
for (x=0; x<X; x++){for (y=0; y<Y; y++)temp=temp+format(mas_pole[x][y]);temp=temp+" ";} // массив в 1 строку
if(regexsearch(1, #temp, temp, R)>0){if (size(temp)>tOcenka)tOcenka=size(temp);} // поиск подряд идущих чисел от 8 до 3
return tOcenka;
}
Цитата: function perebor(int X, int Y, int #kx1, int #ky1, int #kx2, int #ky2)//Перебирает все возможные комбинации меняя соседнте фишки
Нет смысла проверять x+1, т. к. на следующей итерации x-1 сделает этот же ход. Тоже самое с Y.
function perebor (Отобразить)CODE:function perebor(int X, int Y, int #kx1, int #ky1, int #kx2, int #ky2)//Перебирает все возможные комбинации меняя соседнте фишки
{
int tp;
int Max=-1;
int tMax=-1;
int x, y;
for (y=1; y<Y; y++) // вместо Y-1 Y
{
for (x=1; x<X; x++) // вместо X-1 X
{
//Делаем ход меняя x на x-1
tp=mas_pole[x][y];
mas_pole[x][y]=mas_pole[x-1][y];
mas_pole[x-1][y]=tp;
Max=proverka(X, Y);//Оцениваем полученную ситуацию
if (Max>=tMax){tMax=Max; kx1=x; ky1=y; kx2=x-1; ky2=y;}//Если оценка больше предыдущей, записываем координаты и оценку сохраняем.
//Меняем назад на исходную.
tp=mas_pole[x][y];
mas_pole[x][y]=mas_pole[x-1][y];
mas_pole[x-1][y]=tp;
tp=mas_pole[x][y];
mas_pole[x][y]=mas_pole[x][y-1];
mas_pole[x][y-1]=tp;
Max=proverka(X, Y);
if (Max>=tMax){tMax=Max; kx1=x; ky1=y; kx2=x; ky2=y-1;}
tp=mas_pole[x][y];
mas_pole[x][y]=mas_pole[x][y-1];
mas_pole[x][y-1]=tp;
}
}
return tMax;
} |
|
|
Zireael |
Отправлено: 01 Октября, 2018 - 00:02:58
|
Эксперт
Покинул форум
Сообщений всего: 4464
Дата рег-ции: Нояб. 2017
Репутация: 585
|
Цитата: Надо немного доработать perebor
Слегка доработал. Ищет ходы в том числе и по периметру. Работает раз в 5 быстрее.
Сохранить в файл, например: Лучший_ход.txt (Отобразить)CODE:function perebor(int #m, int X, int Y, int #kx1, int #ky1, int #kx2, int #ky2)//Перебирает все возможные комбинации меняя соседние фишки
{
int Max=-1, tMax=-1, i, x, y;
string T, R, M=" ";
char tmp;
int size_filed=X*Y;
new char c[size_filed+1];
T="";
for (x=0; x<X; x++){for (y=0; y<Y; y++)T=T+format(m[x][y]);} // массив в одну строку
strcpy(#c[0], T);
R="(?<=\s*\d{"+format(Y)+"}\B)))"; // разделит строку пробелами по количеству строк в массиве
// ходы по горизонтали в соседних строках, такие ходы образуют больше 3 в ряд
for(i=0; i<size_filed-Y; i++)
{
tmp=c[i]; c[i]=c[i+Y]; c[i+Y]=tmp; // поменять местами элементы
T=format(#c[0]); // для regex, т. к. не работает с char
while(regexreplace(1, #T, T, R, M)>0){} // разделить строку пробелами
Max=proverka(T);//Оцениваем полученную ситуацию
if (Max>=tMax){tMax=Max; kx1=i/Y; ky1=mod(i, Y); kx2=(i+Y)/Y; ky2=mod(i, Y);}
tmp=c[i]; c[i]=c[i+Y]; c[i+Y]=tmp; // вернуть на место элементы
T=format(#c[0]);
}
// ходы по горизонтали в пределах одной строки, 3 в ряд
for(i=0; i<size_filed-1; i++)
{
if(mod(i+1, Y)==0)continue;
tmp=c[i]; c[i]=c[i+1]; c[i+1]=tmp; T=format(#c[0]);
while(regexreplace(1, #T, T, R, M)>0){}
Max=proverka(T);
if (Max>=tMax){tMax=Max; kx1=i/Y; ky1=mod(i, Y); kx2=i/Y; ky2=mod(i+1, Y);}
tmp=c[i]; c[i]=c[i+1]; c[i+1]=tmp; T=format(#c[0]);
}
// ходы по вертикали в соседних столбцах, такие ходы образуют больше 3 в ряд
T="";
for (y=0; y<Y; y++){for (x=0; x<X; x++)T=T+format(m[x][y]);}
strcpy(#c[0], T);
R="(?<=\s*\d{"+format(X)+"}\B)))";
for(i=0; i<size_filed-X; i++)
{
tmp=c[i]; c[i]=c[i+X]; c[i+X]=tmp; T=format(#c[0]);
while(regexreplace(1, #T, T, R, M)>0){}
Max=proverka(T);
if (Max>=tMax){tMax=Max; kx1=mod(i, X); ky1=i/X; kx2=mod(i, X); ky2=(i+X)/X;}
tmp=c[i]; c[i]=c[i+X]; c[i+X]=tmp; T=format(#c[0]);
}
// ходы по вертикали в одном столбце, 3 в ряд
for(i=0; i<size_filed-1; i++)
{
if(mod(i+1, X)==0)continue;
tmp=c[i]; c[i]=c[i+1]; c[i+1]=tmp; T=format(#c[0]);
while(regexreplace(1, #T, T, R, M)>0){}
Max=proverka(T);
if (Max>=tMax){tMax=Max; kx1=mod(i, X); ky1=i/X; kx2=mod(i+1, X); ky2=i/X;}
tmp=c[i]; c[i]=c[i+1]; c[i+1]=tmp; T=format(#c[0]);
}
delete c;
return tMax;
}
function proverka(string temp)
{
int tOcenka=-1;
string R="(\d)\1{7}|(\d)\2{6}|(\d)\3{5}|(\d)\4{4}|(\d)\5{3}|(\d)\6{2}"; // подряд идущие числа от 8 до 3, например 55555 или 3333333
if(regexsearch(1, #temp, temp, R)>0){if (size(temp)>tOcenka)tOcenka=size(temp);} // поиск подряд идущих чисел от 8 до 3
return tOcenka;
}
function mod(int a, int b){return a-(a/b)*b;}
Пример использования (Отобразить)CODE:#include "C:\Лучший_ход.txt"//В начале скрипта
int X=7, Y=8;//Размерность поля
/*
Массив с типами фигур. Заполнить любыми числами по типу и любым способом
Координаты фишек надо хранить так же в двухмерных массивах. Пример:
new int fX[X][Y];//Координаты X фишек
new int fY[X][Y];//Координаты Y фишек
*/
new int mas[X][Y];
/*
Индексы заменяемых массивов. kx1 ky1 меняется на kx2 ky2
то есть фишки с координатами fX[kx1][ky1] fY[kx1][ky1] и fX[kx2][ky2] fY[kx2][ky2] поменяются местами
*/
int kx1, ky1, kx2, ky2;
/*
//Использование
if (perebor(#mas[0][0], X, Y, #kx1, #ky1, #kx2, #ky2)>2)//Есть замена
{
//Тут поменять местами фишки.
messagebox ("Есть замена "+format(kx1)+" " +format(ky1)+" -" +format(mas[kx1][ky1])+" на "+format(kx2)+" " +format(ky2)+" -" +format(mas[kx2][ky2]));
}
*/
//Тест с файла (убрать после весь ниже код)
if (fopen ("c:\Исходник.txt", "r")!=0)//В этом файле массив 7 на 8 заполнен цифрами которые соответствуют фишкам
{
for(int n1=0; n1<Y; n1++)
{
for(int n=0; n<X; n++)
{ fread(mas[n][n1]);
}
}
fclose();//закрываем файл
}
int L=perebor(#mas[0][0], X, Y, #kx1, #ky1, #kx2, #ky2);
//Покажет лучший результат замены
messagebox ("Лучший ход на "+format(L)+" Заменить "+format(kx1)+" " +format(ky1)+" -" +format(mas[kx1][ky1])+" на "+format(kx2)+" " +format(ky2)+" -" +format(mas[kx2][ky2]));
Содержимое файла для теста (Отобразить) Цитата: 0 1 2 3 4 5 2
2 3 1 1 2 5 3
1 5 1 7 5 9 2
5 5 2 1 5 5 2
4 3 2 5 2 0 5
0 6 1 4 5 6 1
5 5 5 2 5 5 5
0 5 4 5 5 1 5 |
|
|
konctantin777 |
Отправлено: 20 Октября, 2018 - 09:03:13
|
Эксперт
Покинул форум
Сообщений всего: 1152
Дата рег-ции: Окт. 2017
Откуда: Архангельск
Репутация: 6
|
Zireael пишет: Цитата: Надо немного доработать perebor
Слегка доработал. Ищет ходы в том числе и по периметру. Работает раз в 5 быстрее.
Почему- то бот просто выключается через несколько часов... Просто сам закрывается. Предыдущие версии "перебора" долго не гонял, но с глобальной переменной может работать сутками... |
|
|
Zireael |
Отправлено: 21 Октября, 2018 - 05:06:29
|
Эксперт
Покинул форум
Сообщений всего: 4464
Дата рег-ции: Нояб. 2017
Репутация: 585
|
https://drive.google.com/open?id...3QCVG_D-4bXkIQ3N
В архиве доработанный скрипт и видео как он работает.
В настройках игры поставить скорость анимации 4x и отключить подсказку ходов.
Поиск хода занимает в среднем от 50 до 500 мсек. Время зависит от количества возможных ходов и процессора.
Добавлена стоимость фишек. Может быть как положительной, так и отрицательной (если какие-то фишки нежелательно убирать с поля).
Теперь учитывается как переместятся фишки после хода (функция offset). Стоимость рассчитывается с учётом какие ещё ряды будут собраны после хода.
Например, есть ход чтобы собрать 3 в ряд, после которого будет собран ряд из 4 или 5 фишек, это будет учтено, т. к. при этом будет дополнительный ход.
Добавлен приоритет для ходов (переменная priority):
0 - приоритет 5 в ряд, если нет такого хода, будет сделан ход максимальный по стоимости.
1 - приоритет 5 или 4 в ряд, если нет таких ходов, будет сделан ход максимальный по стоимости.
2 - приоритет максимальная стоимость хода.
3 - если нет ходов 4 или 5, то приоритет 3 в ряд, которые находятся в самом низу поля. |
|
|
|