IPB
ЛогинПароль:

 
 Ответить  Открыть новую тему 
> ПРОСЬБА-ОБРАЩЕНИЕ, злополучные крестики-нолики
сообщение
Сообщение #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 маленьких вопроса:
Что за массивы заполняются в начале программы?
Зачем так много процедур в модуле?(зачем они вообще)

Если чем поможете можем и отблагодарить. Заранее не могу, т.к уже нет времени. Просто физически не смогу.

Заранее благодарен.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Бывалый
***

Группа: Пользователи
Сообщений: 178
Пол: Мужской

Репутация: -  0  +


Забыл добавить сами файлы


Прикрепленные файлы
Прикрепленный файл  INPUT.TXT ( 8.5 килобайт ) Кол-во скачиваний: 371
Прикрепленный файл  PROGRAM.TXT ( 15.74 килобайт ) Кол-во скачиваний: 350
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Бывалый
***

Группа: Пользователи
Сообщений: 178
Пол: Мужской

Репутация: -  0  +


Ну хоть что-то ответить можно?
Если не вы, то кто поможет разобраться с программой?

Скажите хотя бы принцип игры компа. (От чего "плясать")
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






Цитата
Если не вы, то кто поможет разобраться с программой?
Тот, кто написал этот бред... Обращайся к автору...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Бывалый
***

Группа: Пользователи
Сообщений: 178
Пол: Мужской

Репутация: -  0  +


Что вообще бредовая прога?
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Профи
****

Группа: Пользователи
Сообщений: 618
Пол: Мужской

Репутация: -  24  +


Брррр... Автор кода явно не утруждал себя коментариями. Но так как все мы стараемся быть немного телепатами, я попробую это расшифровать. Не гарантирую, что объясню весь код за один присест, но уж на что терпения хватит smile.gif

Сперва опишу пару массивов:
field : array[-2..n+3,-2..n+3] of integer;
history : array[0..max_ply,-2..n+3,-2..n+3] of shortint;

Первый - это игровой поле, оно задано явно больше чем нужно, то есть реально используется только диапазон [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;
if field[x,y-1]>0 then field[x,y-1]:=rad1;
if field[x+1,y-1]>0 then field[x+1,y-1]:=rad1;
if field[x-1,y]>0 then field[x-1,y]:=rad1;
...

procedure unmakemove(ply:integer);
восстанавливает игровое поле из хистори, то есть это, по сути, отмена хода.

Уф... Пока все... Потом продолжу.

PS cooler, ты угадал, функция evaluate осуществляет проверку на 5 в ряд, а поиск хода для AI осуществляет функция search1

Сообщение отредактировано: Archon -


--------------------
Close the World...txeN eht nepO
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Бывалый
***

Группа: Пользователи
Сообщений: 178
Пол: Мужской

Репутация: -  0  +


Если можно побыстрее.
Время..
Спасибо Огромное.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #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 -


--------------------
Close the World...txeN eht nepO
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Бывалый
***

Группа: Пользователи
Сообщений: 178
Пол: Мужской

Репутация: -  0  +


Спасибо, Archon, Тверь вас не забудет.


Можно удалять тему

Сообщение отредактировано: cooler -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 24.10.2021 5:44
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name