ПРОСЬБА-ОБРАЩЕНИЕ, злополучные крестики-нолики |
ПРОСЬБА-ОБРАЩЕНИЕ, злополучные крестики-нолики |
cooler |
8.06.2007 19:46
Сообщение
#1
|
Бывалый Группа: Пользователи Сообщений: 178 Пол: Мужской Репутация: 0 |
Обращаюсь прежде всего к volvo и мисс_графити.
Прошу помочь 2м нуждающимся (мне и DRAKON'у). Есть у нас такая программа крестики-нолики. Я (не знаю как DRAKON) не прошу комментировать текст программы (сам бы на вашем месте не стал) прошу лишь показать и пояснить хотя бы 2 места в программе: проверка 5 символов в ряд и как компьютер определяет место для своего хода. Я думаю так, проверка 5 в ряд здесь: Код type tvert=array[1..20] of integer; const vert : tvert = (0,0,0,0,0, -1,-2,-3,-4,-5, 0,0,0,0,0, 1,2,3,4,5); hor : tvert = (-1,-2,-3,-4,-5, 0,0,0,0,0, 1,2,3,4,5, 0,0,0,0,0); diag1 : tvert = (-1,-2,-3,-4,-5, -1,-2,-3,-4,-5, 1,2,3,4,5, 1,2,3,4,5); diag2 : tvert = (1,2,3,4,5, -1,-2,-3,-4,-5, -1,-2,-3,-4,-5, 1,2,3,4,5); const ee=10; function evaluate(color:integer):longint; var ii,jj,i,j,k,l,pos,ev,pol : longint; fl,fl1,win,fl2 : boolean; procedure ev_(vert:tvert); var i : integer; begin pos:=1; pol:=1; fl:=false; fl1:=true; fl2:=false; for i:=1 to 4 do begin if field[ii+vert[i],jj+vert[i+5]]=color then begin if fl1 then pos:=pos+1; pol:=pol*ee; end else case field[ii+vert[i],jj+vert[i+5]] of null,rad1,rad2: begin if i<4 then if field[ii+vert[i+1],jj+vert[i+6]]=color then fl:=true else break else if field[ii+vert[i+1],jj+vert[i+6]]=color then begin pol:=pol*ee; fl2:=true; end; fl1:=false; end; else begin fl:=true; k:=i; break; end; end;{case} end; fl1:=true; for i:=11 to 14 do begin if field[ii+vert[i],jj+vert[i+5]]=color then begin if fl1 then pos:=pos+1; pol:=pol*ee; end else case field[ii+vert[i],jj+vert[i+5]] of null,rad1,rad2: begin if i<14 then if field[ii+vert[i+1]+0,jj+vert[i+6]]=color then fl2:=true else break else if field[ii+vert[i+1]+0,jj+vert[i+6]]=color then begin pol:=pol*ee; end; fl1:=false; end; else begin if fl and(k+i-10<5) then pol:=0; fl:=true; break; end; end;{case} end; if pol>10000000 then pol:=10000000; if fl or fl2 then ev:=ev+pol else ev:=ev+pol*ee; if pos>4 then win:=true; end; begin ev:=0; win:=false; for ii:=1 to n do begin for jj:=1 to n do begin if field[ii,jj]=color then begin ev_(vert); ev_(hor); ev_(diag1); ev_(diag2); end;{if} if win then break; end; if win then break; end; if win then ev:=inf; evaluate:=ev; end; function ev_step(color:integer;ii,jj:longint):longint; var i,j,k,l,pos,ev,pol : longint; fl,fl1,win,fl2 : boolean; procedure ev_(vert:tvert); var i : integer; begin pos:=1; pol:=1; fl:=false; fl1:=true; fl2:=false; for i:=1 to 4 do begin if field[ii+vert[i],jj+vert[i+5]]=color then begin if fl1 then pos:=pos+1; pol:=pol*ee; end else case field[ii+vert[i],jj+vert[i+5]] of null,rad1,rad2: begin if i<4 then if field[ii+vert[i+1],jj+vert[i+6]]=color then fl:=true else break else if field[ii+vert[i+1],jj+vert[i+6]]=color then begin pol:=pol*ee; fl2:=true; end; fl1:=false; end; else begin fl:=true; k:=i; break; end; end;{case} end; fl1:=true; for i:=11 to 14 do begin if field[ii+vert[i],jj+vert[i+5]]=color then begin if fl1 then pos:=pos+1; pol:=pol*ee; end else case field[ii+vert[i],jj+vert[i+5]] of null,rad1,rad2: begin if i<14 then if field[ii+vert[i+1]+0,jj+vert[i+6]]=color then fl2:=true else break else if field[ii+vert[i+1]+0,jj+vert[i+6]]=color then begin pol:=pol*ee; end; fl1:=false; end; else begin if fl and(k+i-10<5) then pol:=0; fl:=true; break; end; end;{case} end; if pol>10000000 then pol:=10000000; if fl or fl2 then ev:=ev+pol else ev:=ev+pol*ee; if pos>4 then win:=true; end; begin win:=false; if field[ii,jj]=color then begin ev_(vert); ev_(hor); ev_(diag1); ev_(diag2); end;{if} if win then ev:=inf; ev_step:=ev; end; Что здесь происходит? Помогите найти как компьютер ходит?(если можно поясните принцип) И ещё 2 маленьких вопроса: Что за массивы заполняются в начале программы? Зачем так много процедур в модуле?(зачем они вообще) Если чем поможете можем и отблагодарить. Заранее не могу, т.к уже нет времени. Просто физически не смогу. Заранее благодарен. |
cooler |
8.06.2007 21:12
Сообщение
#2
|
Бывалый Группа: Пользователи Сообщений: 178 Пол: Мужской Репутация: 0 |
Забыл добавить сами файлы
Прикрепленные файлы INPUT.TXT ( 8.5 килобайт ) Кол-во скачиваний: 270 PROGRAM.TXT ( 15.74 килобайт ) Кол-во скачиваний: 314 |
cooler |
9.06.2007 11:38
Сообщение
#3
|
Бывалый Группа: Пользователи Сообщений: 178 Пол: Мужской Репутация: 0 |
Ну хоть что-то ответить можно?
Если не вы, то кто поможет разобраться с программой? Скажите хотя бы принцип игры компа. (От чего "плясать") |
volvo |
9.06.2007 11:45
Сообщение
#4
|
Гость |
Цитата Если не вы, то кто поможет разобраться с программой? Тот, кто написал этот бред... Обращайся к автору... |
cooler |
9.06.2007 12:09
Сообщение
#5
|
Бывалый Группа: Пользователи Сообщений: 178 Пол: Мужской Репутация: 0 |
Что вообще бредовая прога?
|
Archon |
9.06.2007 12:25
Сообщение
#6
|
Профи Группа: Пользователи Сообщений: 618 Пол: Мужской Репутация: 24 |
Брррр... Автор кода явно не утруждал себя коментариями. Но так как все мы стараемся быть немного телепатами, я попробую это расшифровать. Не гарантирую, что объясню весь код за один присест, но уж на что терпения хватит
Сперва опишу пару массивов: field : array[-2..n+3,-2..n+3] of integer; Первый - это игровой поле, оно задано явно больше чем нужно, то есть реально используется только диапазон [1..n,1..n]. В первую очередь это сделано для того, чтобы не проверять каждый раз границы массива. Второй - это набор игровых полей. Сделано глупо, проще было написать "array[0..max_ply] of field;", тогда бы и сохранение/загрузка игрового поля в хистори было бы проще. Массив этот нужен, чтобы хранить в нем историю ходов (чтобы ходы отменять потом можно было). Далее процедуры и функции: procedure intro; Просто вывод заставки. Ничего особенного. procedure activate_field; Процедура заполняет игровое поле начальными значениями. Кстати, клетки на игровом поле могут принимать множество значений заданных константами, вот их описание: nol = -2 - нолик cross = -1 - крестик null = 4 - пустая клетка rad1 = 1 - Название от "радиус 1". Этим значением помечаются клетки, прилегающие вплотную к заполненным (то есть тем, в которых уже стоят крестик или нолик) rad2 = 2 - Аналогично. Только эти клетки отстоят от заполненных на 2. Чтобы лучше представить это, нарисуйте на листочке в клеточку несколько крестиков и ноликов, потом обведите то что получится по периметру единичками, а потом то что получится еще раз по периметру, только двойками. Зачем это нужно? Подозреваю, что для исскуственного интеллекта. out = -3 - клетка за пределами игрового поля. procedure makemove(move:tmove;ply:integer); Процедура делает ход. Сами параметры хода находятся в записи move. Сперва процедура сохраняет текущее игровое поле в хистори, потом собственно устанавливает крестик или нолик, а потом происходит установка тех самых rad1 и rad2, то есть просматриваются клетки, отстоящие на 1 клетку (туда устанавливается rad1), и клетки, отстоящие на 2 клетки (туда - rad2). Вот для этого и нужны массивы mr1 и mr2. В них хранятся смещения по координатам x и y, чтобы клетки мможно было проверить в цикле, а не набором условий вроде: if field[x-1,y-1]>0 then field[x-1,y-1]:=rad1; procedure unmakemove(ply:integer); восстанавливает игровое поле из хистори, то есть это, по сути, отмена хода. Уф... Пока все... Потом продолжу. PS cooler, ты угадал, функция evaluate осуществляет проверку на 5 в ряд, а поиск хода для AI осуществляет функция search1 Сообщение отредактировано: Archon - 9.06.2007 12:28 -------------------- Close the World...txeN eht nepO
|
cooler |
9.06.2007 20:16
Сообщение
#7
|
Бывалый Группа: Пользователи Сообщений: 178 Пол: Мужской Репутация: 0 |
Если можно побыстрее.
Время.. Спасибо Огромное. |
Archon |
10.06.2007 0:43
Сообщение
#8
|
Профи Группа: Пользователи Сообщений: 618 Пол: Мужской Репутация: 24 |
Ладно, объясняю принцип игры компа. Теперь собственно поиск хода:
Как видно, алгоритм ищет лучший ход перебирая только клетки, значение которых rad1 или rad2, думаю понятно почему именно их (нет смысла ходить далеко от уже поставленных х/о). Алгоритм представляет собой обычный рекурсивный перебор в глубину с оценкой. Глубина перебора задается константой ply_max1. Я говорил, что функция evaluate осуществляет проверку на 5 в ряд... Так вот, это не точно. На самом деле это оценочная функция, она определяет "качество" позиции для заданного игрока. То есть чем больше возвращаемое функцией значение, тем выгоднее эта позиция для указанного игрока. Константа inf задает условную бесконечность. То есть если функция evaluate вернула значение inf, значит игрок победил. Как происходит оценка позиции в функции evaluate? Предположим проверяется "качество" позиции для крестиков. Тогда для каждого найденного на поле крестика вызывается функция ev_, которая проверяет все клетки в заданном направлении. Направление задается массивами vert, hor, diag1, diag2. В каждом из этих массивов содержатся относительные смещения координат (как в случае с массивами mr1 и mr2). Функция ev_ рассматривает полоску длинной в 11 клеток в заданном направлении и с центром в заданной точке. Она вызывается для каждого из возможных направлений. Что она делает с этой полоской? Оценивает ее и результат прибавляет к общей оценке всей игровой позиции. Если в полоске есть 5 в ряд, ev_ устанавливает флаг win и заканчивает свое выполнение. Как функция ev_ оценивает полоску? У меня нет никакого желания разбираться. Слишком путано написано. Проще написать с нуля, тем более, что это не сложно. Нужно учитывать вот что: * Чем больше в ряд, тем лучше * Последовательность обесценивается если в ней собрать 5 невозможно в принципе (к примеру противник ограничил) * Если 3 или 4 в ряд и не ограничены противником с обоих сторон, то цена позиции - очень большая (это практически победа) Все! Если есть вопросы, задавайте. Сообщение отредактировано: Archon - 10.06.2007 0:46 -------------------- Close the World...txeN eht nepO
|
cooler |
10.06.2007 19:10
Сообщение
#9
|
Бывалый Группа: Пользователи Сообщений: 178 Пол: Мужской Репутация: 0 |
Спасибо, Archon, Тверь вас не забудет.
Можно удалять тему Сообщение отредактировано: cooler - 10.06.2007 19:10 |
Текстовая версия | 28.05.2024 17:03 |