Меню сайта
Форма входа

Категории раздела
Уроки по созданию игр [38]
Программирование игр разной сложности
Игровые алгоритмы [24]
Алгоритмы, которые уже реализованы для разных жанров игр
Графика [5]
Учимся работать с графикой в Делфи
Мультимедиа [3]
Работа с мультимедийными возможностями Делфи
Другие статьи [18]
Статьи не вошедшие не в один из разделов
Ошибки [4]
Всевозможные ошибки и пути их решения
Среда, 15.05.2024, 13:43
Приветствую Вас Гость

Статьи по программированию

Главная » Статьи » Игровые алгоритмы

Искуственный интеллект для игры в шашки

Искуственный интеллект для игры в шашки

 

Всем доброго времени суток! Недавно поступил вопрос о том, как создать искусственный интеллект (ИИ) для шашек. Конечно, его сложность, надежность, скорость работы и другие характеристики зависят напрямую от поставленой задачи, ее требований. В интернете каждый желающий сможет найти целую кучу готовых исходников данной игры с ИИ, а также обьяснений на эту тему. Но специально для посетителей моего сайта я постараюсь обьяснить как же реализовать простой ИИ в среде Delphi, который Вы с легкостью сможете усложнить и доработать в любое время.

 

Во первых, текст исходного кода будет напрямую зависеть от структуры Вашей программы (в данном случае игры) и имен Ваших переменных. Поэтому нам прийдется или использовать абстрактные переменные (с выдуманными именами или идентификаторами) или же попытаться реализовать что-то более-менее универсальное. Я думаю второй вариант, нам пподходит больше. А значит мы займемся созданием процедуры, которая и будет отвечать за ИИ в нашей игре. Нам нужно будет только определить входные данные для этой процендуры.

 

Давайте для начала назовем нашу процедуру. Например, AI (как принято сокращенно называть ИИ на английском). Также для входных данных нам понадобится:

 

  • Координаты активной шашки
  • Активный игрок (например, его номер)
  • Игровое поле (расстановку всех шашек, в томч исле и своих, например, в виде координат или массива)

 

Итак, подготовим пока пустую процедуру:

 

Procedure AI;

Begin

End;

 

И не забываем обьявить нашу процедуру в разделе Var иначе программа не будет знать о существовании нашей процедуры, при ее вызове.

 

Var

Procedure AI;

 

Теперь поговорим о самом алгоритме искусственного алгоритма. Для начала условимся что у нас есть некий массив.

 

map:array[0..7,0..7] of integer;

 

Этот массив хранит расположение шашек на нем. Например, белые шашки в этом массиве будут обозначены единицей, а белые дамки – двойкой, черные шашки – тройкой, черные дамки – четверкой. Остальные клетки заполняем нулями. При клике по своей шашке – эта шашка становится активной, то есть мы запоминаем ее координаты. После этого должна вызваться наша процедура.  Вызывается она с помощью ее имени:

 

AI;

 

А внутри процедуры сделаем проверку на наличие шашек противника рядом. И если такая шашка будет найдена, то проверяем свободное место за ней, чтобы можно было ее ударить. Если такую шашку можно ударить, то нам нужно отметить место, на которое мы станем или сразу автоматически будет биться шашка. Поскольку ИИ пишется для компьютерного игрока, то нам подходит второй вариант. Если рядом с активной шашкой нет врагов, то данная шашка просто ходит.

 

Условимся, что компьютер будет управлять, к примеру, черными шашками. И так, сначала компьютер случайно выбирает любую свою шашку на поле:

 

Procedure AI;

Var I,j:integer;

N:boolean;

Begin

Randomize;

N:=false;

  While (n=false) do

  Begin

  I:=random(8);

  J:=random(8);

  If (map[I,j]=3) or (map[I,j]=4) then n:=true;

  End;

End;

 

Далее проверяем впереди шашек наличие пустых клеток, чтобы походить. Если свободное место будет, то шашка походит, в противном случае нужно будет сново вызывать нашу процедуру для поиска новой активной шашки. Условимся, что белые шашки идут вверх, а черные вниз. Координаты активной шашки обозначим через activ.x, activ.y:

 

Procedure AI;

Var I,j:integer;

N:boolean;

Begin

Randomize;

N:=false;

  While (n=false) do

  Begin

  I:=random(8);

  J:=random(8);

  If (map[I,j]=3) or (map[I,j]=4) then n:=true;

  End;

 

  N:=false;

  If (n=false) and (activ.x+1<=7) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x+1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x-1>=0) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x-1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

 

End;

 

Мы также предусматриваем, чтобы не при проверке не выходили за пределы созданного нами массива игрового поля. Теперь нам останется только сделать проверку на наличие вражеских шашек рядом, чтобы можно было их бить. И если при ходьбе мы проверяли только клетки под нами, то для битья нужно проверять и клетки, которые выше нашей активной клетки. Проверку на возможность бить нужно реализовать перед ходьбой. Так как битье шашек более приоритетное дело.

 

Procedure AI;

Var I,j:integer;

N:boolean;

Begin

Randomize;

N:=false;

  While (n=false) do

  Begin

  I:=random(8);

  J:=random(8);

  If (map[I,j]=3) or (map[I,j]=4) then n:=true;

  End;

 

  N:=false;

 

  If (n=false) and (activ.x+2<=7) and (activ.y+2<=7)

  and (map[activ.x+1,activ.y+1]>0)

  and (map[activ.x+1,activ.y+1]<3)

  and (map[activ.x+2,activ.y+2]=0) then

  Begin

  Map[activ.x+2,activ.y+2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x+1,activ.y+1]:=0;

  N:=true;

  End;

 

   If (n=false) and (activ.x-2>=0) and (activ.y-2>=0)

  and (map[activ.x-1,activ.y-1]>0)

  and (map[activ.x-1,activ.y-1]<3)

  and (map[activ.x+2,activ.y+2]=0) then

  Begin

  Map[activ.x-2,activ.y-2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x-1,activ.y-1]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x+2<=7) and (activ.y-2>=0)

  and (map[activ.x+1,activ.y-1]>0)

  and (map[activ.x+1,activ.y-1]<3)

  and (map[activ.x+2,activ.y-2]=0) then

  Begin

  Map[activ.x+2,activ.y-2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x+1,activ.y-1]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x-2>=0) and (activ.y+2<=7)

  and (map[activ.x-1,activ.y+1]>0)

  and (map[activ.x-1,activ.y+1]<3)

  and (map[activ.x-2,activ.y+2]=0) then

  Begin

  Map[activ.x-2,activ.y+2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x-1,activ.y+1]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x+1<=7) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x+1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x-1>=0) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x-1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

End;

 

Теперь компьютер может не только ходить, но и бить шашки противника. Но пока он умеет бить только по одной шашке. Дабы он мог бить более одной шашки – нужно после биться делать проверку на возможность ударить еще раз.

 

Procedure AI;

Var I,j:integer;

N:boolean;

Begin

Randomize;

N:=false;

  While (n=false) do

  Begin

  I:=random(8);

  J:=random(8);

  If (map[I,j]=3) or (map[I,j]=4) then n:=true;

  End;

 

  N:=false;

 

 While (n=false) do

 Begin

 

  If (n=false) and (activ.x+2<=7) and (activ.y+2<=7)

  and (map[activ.x+1,activ.y+1]>0)

  and (map[activ.x+1,activ.y+1]<3)

  and (map[activ.x+2,activ.y+2]=0) then

  Begin

  Map[activ.x+2,activ.y+2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x+1,activ.y+1]:=0;

  N:=true;

  End;

 

   If (n=false) and (activ.x-2>=0) and (activ.y-2>=0)

  and (map[activ.x-1,activ.y-1]>0)

  and (map[activ.x-1,activ.y-1]<3)

  and (map[activ.x+2,activ.y+2]=0) then

  Begin

  Map[activ.x-2,activ.y-2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x-1,activ.y-1]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x+2<=7) and (activ.y-2>=0)

  and (map[activ.x+1,activ.y-1]>0)

  and (map[activ.x+1,activ.y-1]<3)

  and (map[activ.x+2,activ.y-2]=0) then

  Begin

  Map[activ.x+2,activ.y-2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x+1,activ.y-1]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x-2>=0) and (activ.y+2<=7)

  and (map[activ.x-1,activ.y+1]>0)

  and (map[activ.x-1,activ.y+1]<3)

  and (map[activ.x-2,activ.y+2]=0) then

  Begin

  Map[activ.x-2,activ.y+2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x-1,activ.y+1]:=0;

  N:=true;

  End;

 

  If ( (activ.x-2>=0) and (activ.y+2<=7) and (map[activ.x-2,activ.y+2]=0)

  (map[activ.x-1,activ.y+1]>0) and (map[activ.x-1,activ.y+1]<3) )

  or ( (activ.x+2<=7) and (activ.y+2<=7) and (map[activ.x+2,activ.y+2]=0)

  (map[activ.x+1,activ.y+1]>0) and (map[activ.x-1,activ.y+1]<3) )

  or ( (activ.x+2<=7) and (activ.y-2>=0) and (map[activ.x+2,activ.y-2]=0)

  (map[activ.x+1,activ.y-1]>0) and (map[activ.x-1,activ.y+1]<3) )

  or ( (activ.x-2>=0) and (activ.y-2>=0) and (map[activ.x-2,activ.y-2]=0)

  (map[activ.x-1,activ.y-1]>0) and (map[activ.x-1,activ.y+1]<3) )  then

  N:=false;

 

 End;

 

  If (n=false) and (activ.x+1<=7) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x+1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x-1>=0) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x-1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

End;

 

И в конце необходимо реализовать переход хода первому игроку и сделать все шашки неактивными.

 

Procedure AI;

Var I,j:integer;

N:boolean;

Begin

Randomize;

N:=false;

  While (n=false) do

  Begin

  I:=random(8);

  J:=random(8);

  If (map[I,j]=3) or (map[I,j]=4) then n:=true;

  End;

 

  N:=false;

 

 While (n=false) do

 Begin

 

  If (n=false) and (activ.x+2<=7) and (activ.y+2<=7)

  and (map[activ.x+1,activ.y+1]>0)

  and (map[activ.x+1,activ.y+1]<3)

  and (map[activ.x+2,activ.y+2]=0) then

  Begin

  Map[activ.x+2,activ.y+2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x+1,activ.y+1]:=0;

  N:=true;

  End;

 

   If (n=false) and (activ.x-2>=0) and (activ.y-2>=0)

  and (map[activ.x-1,activ.y-1]>0)

  and (map[activ.x-1,activ.y-1]<3)

  and (map[activ.x+2,activ.y+2]=0) then

  Begin

  Map[activ.x-2,activ.y-2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x-1,activ.y-1]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x+2<=7) and (activ.y-2>=0)

  and (map[activ.x+1,activ.y-1]>0)

  and (map[activ.x+1,activ.y-1]<3)

  and (map[activ.x+2,activ.y-2]=0) then

  Begin

  Map[activ.x+2,activ.y-2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x+1,activ.y-1]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x-2>=0) and (activ.y+2<=7)

  and (map[activ.x-1,activ.y+1]>0)

  and (map[activ.x-1,activ.y+1]<3)

  and (map[activ.x-2,activ.y+2]=0) then

  Begin

  Map[activ.x-2,activ.y+2]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  Map[activ.x-1,activ.y+1]:=0;

  N:=true;

  End;

 

  If ( (activ.x-2>=0) and (activ.y+2<=7) and (map[activ.x-2,activ.y+2]=0)

  (map[activ.x-1,activ.y+1]>0) and (map[activ.x-1,activ.y+1]<3) )

  or ( (activ.x+2<=7) and (activ.y+2<=7) and (map[activ.x+2,activ.y+2]=0)

  (map[activ.x+1,activ.y+1]>0) and (map[activ.x-1,activ.y+1]<3) )

  or ( (activ.x+2<=7) and (activ.y-2>=0) and (map[activ.x+2,activ.y-2]=0)

  (map[activ.x+1,activ.y-1]>0) and (map[activ.x-1,activ.y+1]<3) )

  or ( (activ.x-2>=0) and (activ.y-2>=0) and (map[activ.x-2,activ.y-2]=0)

  (map[activ.x-1,activ.y-1]>0) and (map[activ.x-1,activ.y+1]<3) )  then

  N:=false;

 

 End;

 

  If (n=false) and (activ.x+1<=7) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x+1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

 

  If (n=false) and (activ.x-1>=0) and (activ.y+1<=7) and (map[activ.x+1,activ.y+1]=0) then

  Begin

  Map[activ.x-1,activ.y+1]:=map[activ.x,activ.y];

  Map[activ.x,activ.y]:=0;

  N:=true;

  End;

 

  If n=true then

  Begin

  Current:=1;

  Activ.x:=-1;

  Activ.y:=-1;

  End;

 

End;

 

Переменная Current показывает какой игрок является активным. То есть, ходит в данный момент.  Ну вот, в принципе, и все. Простенький Искуственный интеллект у нас готов. Далее его можно доработать на свое усмотрение. Вызывать нашк процедуру можно в таймере с проверкой (когда ходит игрок номер 2 «черные шашки»):

 

If Current=2 then AI;

 

А у меня на этом все. Надеюсь я доступно смог обьяснить Вам реализовать ИИ для игры в шашки. Свои вопроссы и пожелания оставляйте в нашей группе в Вконтакте, на форуме данного сайта и в чате, тоже на этом же сайте. Всем пока и до новых встречь! Удачи в Ваших начинаниях по созданию игр в среде программирования Delphi.

 

Автор: Соколов Виталий

Источник: delgame.at.ua

Категория: Игровые алгоритмы | Добавил: Armageddets (11.01.2015) | Автор: Искуственный интеллект для шашек
Просмотров: 3857 | Теги: gamedev, делфи, шашки, урок по созданию игр, Delphi | Рейтинг: 0.0/0
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Наш опрос
Какие уроки по созданию игр Вам удобнее?
Всего ответов: 141
Мини-чат
Друзья сайта
  • Официальный блог
  • Сообщество uCoz
  • FAQ по системе
  • Инструкции для uCoz
  • Статистика

    Онлайн всего: 1
    Гостей: 1
    Пользователей: 0