Android Статьи Браузерные игры Программы О сайте
 

Крестики-нолики - разработка игры: как создать игру

Небольшое вступление

Вместо того, чтобы долго изучать программирование по статьям и лекциям, которые скучно описывают какие-то непонятные действия с числами и строками, лучше изучать программирование на красочных примерах, таких, как создание игр!

Естественно, вам потребуется хотя бы теоретическое знание о том, что такое: язык программирования, переменная, цикл, массив... Так же, для чтения этой статьи и изучения программы, желательно иметь представление о: JavaScript, HTML, и CSS (CSS не обязательно - требуется только для украшения).

Структура игры

Эта игра состоит из нескольких частей, которые написаны на HTML, CSS и JavaScript.

Общий принцип такой: на веб-страничке (HTML) делаются ссылки на файл с JavaScript-ом и CSS файл со стилями. Так же, в HTML размечаются те места, где будут элементы игры отображаться. А так же вставлена одна функция на JavaScript, которая запускается сразу после загрузки страницы, и задаёт параметры языка для игры, и даёт команду на создание нового игрового поля.

В CSS файле содержатся стили элементов игры, такие, как обводка клеток, и тип курсора мыши, при наведении на клетку.

В JS файле содержится основной код, который и управляет игрой.

Раз мы изучаем на примере, то практически каждая строчка будет содержать комментарий – подробное описание того, чего делает данная команда.

Исходный код CSS файла

CSS (каскадные таблицы стилей) – описывает стиль для отображения игрового поля на HTML страницы. Исходный код CSS приведу без подробных объяснений, только с комментариями, которые начинаются символами /* и заканчиваются символами */.

#gameinfo { font-size: 110%; } /* размер шрифта в текстовом поле, с ID=gameinfo */
#game table{ /* описывает стиль таблицы с крестиками и ноликами */
 border:3px groove blue; /* окаёмка таблицы */
 background-image:url("fon.jpg"); /* фоновая картинка для игры */ }
#game table tr td{ /* стиль для одной ячейки в таблице – где будет располагаться крестик, либо нолик, или просто будет пустовать */
 border:1px dotted #eeb; /* опишем обводку клетки */
 cursor:pointer; /* установим вид курсора мыши, чтобы показать, что можно кликать на клетку */ }
#game table tr td:hover{ border:1px solid #ffa; } /* подсвечивание клетки, при наведении на неё курсора мыши */

Код на HTML странице

HTML. Следующий код необходимо вставить на веб-страницу. Каждый фрагмент кода подписан.

внутрь тега HEAD:

<link rel="stylesheet" type="text/css" href="gamestyle.css" /> <!-- использование стиля из файла -->
<script type="text/javascript" src="gamescript.js"></script> <!-- загрузка скрипта игры -->
<script type="text/javascript"> <!-- инициализирующий игру скрипт и обработка событий -->
function clkGameButton(){ // событие начала новой игры
 if (isNaN(frnG.nCells.value)) { // проверка правильности ввода
  alert("Введите число клеток.");
  return;
 }
 var n=parseInt(frnG.nCells.value);
 createField(n,n);
 gameinfo.innerText="Начало игры. Всего точек "+nMaxPoint+"\nМинимальная вероятность победы:"+Math.round(nMaxPoint/(n*n)*100)+"%";
}
function initGame(){ // инициализация игры
 gTexts['win1']='Победил "'; gTexts['win2']='" !'; // настроцка текста
 gTexts['playing']='игра продолжается...'
 gTexts['start']='Начало игры. Ваш ход.'
 createField(3,3); // создание игрового поля
}
</script>

Так же, нужно прописать параметр onload="initGame();" в тег BODY.

внутрь BODY – туда, где будет управление игрой:

<table width="100%"><tr>
 <td width="50%">
  <span id="gameinfo">Кликните по клетке, чтобы открыть её</span> <!-- сообщения игры -->
  </td><td width="50%">
  <form name="frnG" action="javascript:clkGameButton();">
  Размер поля: <input type="text" name="nCells" value="8" title="Число клеток" size="3"> <!-- текстовое поле -->
  <input type="button" value="Начать игру" onclick="clkGameButton();"> <!-- кнопка начала игры -->
 </form></td>
</tr></table>

внутрь BODY – туда, где будет игровое поле: <div id="game"></div>

Код JavaScript игры

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

Первые строки - переменные отвечают за общие переменные:

  • gameImgDir - содержит сведения об расположении относительного адреса графических изображений.
  • gTexts - содержит текстовые строки, полезны для поддержки многоязычности.
  • gField - двумерный массив - содержит информацию о клетках.

Далее идут функции, которые вызываются со страницы. Посредством этих вызовов в игру передаются команды о выборе пользователя, и ответные реакции игры - сообщение о конце игры, расстановка крестиков и ноликов, расчёт хода компьютерного противника. Вот, что каждая из них делает:

  • createField(w,h) - создание нового поля, с размером w на h.
  • setCell(x,y,t) - ставит в клетку с координатами [x,y] значение t (крестик, или нолик). А так же заменяет картинки на поле.
  • isWin() - проверяет, кто победил.
  • CompGame() - вызывает компьютерного игрока, который сначало методом перебора проверяет все варианты, запуская isWin(), а затем делает ход, вызывая setCell(x,y,t).
  • onCellClk(x,y) - вызывается по клику, передаются координаты клетки. Вызывает isWin(), setCell(x,y,t) и CompGame(). Сообщает информацию о победе.

После того, как мы изучили основные принципы игры, теперь можно смотреть весь исходный код файла gamescript.js. Все основные моменты кода даны с комментариями (комментарии в JS идут после двойного слеша //).

// (C) www.AlexeyK.com, 2012.

 var gameImgDir="data/";
 var gTexts=[]; // Для многоязычности.
 gTexts['win1']='Win '; gTexts['win2']='!';
 gTexts['playing']='...'
 gTexts['start']='Begin game!'

 var gField=[]; // игровое поле

 function createField(w,h){ // Задаёт размер игрового поля.
  gField=new Array(w); // создание нового массива.
  for (i=0;i<w;i++) gField[i]=new Array(h); // теперь переделаем массив в матрицу.

  var hT="<table cellpadding='0' cellspacing='0'>"; // заголовок тега таблицы.
  for (j=0;j<h;j++) {
   hT+="<tr>"; // создание новой линии
   for (i=0;i<w;i++) { // вставка ячеек в линию
    hT+="<td>";
    hT+="<img id='c"+i+"_"+j+"' src='"+gameImgDir+"c_null.gif' alt=' ' onclick='onCellClk("+i+","+j+")'>";
    hT+="</td>";
   }
   hT+="</tr>"; // конец линии
  }
  document.getElementById('game').innerHTML = hT+"</table>"; // вставка таблицы на страницу.
  document.getElementById('gameinfo').innerText=gTexts['start']; // отобразить сообщение
 }
 function setCell(x,y,t) { // Поставить крестик или нолик
  gField[x][y]=t; // Запомнить t в массиве
  var imgsrc=gameImgDir+'c_null.gif'; // изображение по умолчанию
  if (t=='x') imgsrc=gameImgDir+'c_x.gif'; // картинка для крестика
  if (t=='o') imgsrc=gameImgDir+'c_o.gif'; // картинка для нолика
  var oName="c"+x+"_"+y; // составление имени картинки
  document.getElementById(oName).src = imgsrc; // замена изображения
  if (t!=null) document.getElementById(oName).alt = t; // если картинки выключены, то игра будет в текстовом режиме :)
 }

 function isWin(){ // Проверка победы.
  // проверка зон 3 на 3...
  for ( stX=0 ; stX<=gField.length-3 ; stX++) for ( stY=0 ; stY<=gField[0].length-3 ; stY++) // Если размер поля больше трёх.
  {
  var lC=gField[stX][stY]; // проверка линии
  if (lC!=null) for ( i=0 ; i<3 ; i++ ) if ( gField[i+stX][i+stY] != lC ) lC=null; // если проверяемая клетка не содержит lC, то сбросить значение lC
  if (lC!=null) return lC; // если победа обнаружена.
  lC=gField[2+stX][stY];
  if (lC!=null) for ( i=0 ; i<3 ; i++ ) if ( gField[2-i+stX][i+stY] != lC ) lC=null;
  if (lC!=null) return lC;

  for ( i=0 ; i<3 ; i++ ) { // проверка по вертикали
   lC=gField[stX+i][stY];
   if (lC!=null) for ( j=0 ; j<3 ; j++ ) if ( gField[i+stX][j+stY] != lC ) lC=null;
   if (lC!=null) return lC;
  }
  for ( j=0 ; j<3 ; j++ ) { // проверка по горизонтали
   lC=gField[stX][stY+j];
   if (lC!=null) for ( i=0 ; i<3 ; i++ ) if ( gField[i+stX][j+stY] != lC ) lC=null;
   if (lC!=null) return lC;
  }
  }
// TO DO - если все клетки заняты, но никто не победил, то ничья, но пока это условие не сделано. Попробуйте сами доделать эту проверку ;)
  return false; // если никто не победил
 }

 function CompGame(){ // Так сказать ИИ :)
  var tx=null,ty=null,tp=0; // tp - приоритет выбранной целевой клетки.
  var stX=0,stY=0;
  for ( stX=0 ; stX<gField.length ; stX++) for ( stY=0 ; stY<gField[0].length ; stY++) // для каждой клетки
 {
  var lC=gField[stX][stY];
  if ( (lC!='x')&&(lC!='o')) { // только для пустых клеток
   gField[stX][stY]='x';
   if ( isWin()=='x' ) { // пробуем победить
    tx=stX;ty=stY;
    tp=3;
   } else if (tp<3) {
    gField[stX][stY]='o';
    if ( isWin()=='o' ) { // или помешать победить игроку.
     tx=stX;ty=stY;
     tp=2;
    }else if (tp<2){ // или...
     var mini=-1,maxi=1,minj=-1,maxj=1;
     if (stX>=gField.length-1) maxi=0; if (stY>=gField[0].length-1) maxj=0;
     if (stX<1) mini=0; if (stY<1) minj=0;
     // найти ближайший нолик...
     for (i=mini;i<=maxi;i++) for (j=minj;j<=maxj;j++) if ( (i!=0) && (j!=0) ) { // если есть рядом своя занятая клетка - поближе к своим
      if (gField[stX+i][stY+j]=='o') {
       tx=stX;ty=stY;
       tp=1;
      }
     }
     if (tp<1) { // или хотя бы на свободную клетку поставить.
      tx=stX;ty=stY;
     }
    }
   }
   gField[stX][stY]=lC;
  }
  }
  if ( (tx!=null)&&(ty!=null) ) { // если целевая клетка выбранна
   setCell(tx,ty, 'o'); // поставим нолик в клетку.
  }
 }

 function onCellClk(x,y) { // Действия при клике по клетке
  if (gField[x][y]==null) { // если клетка пустая
   var win = isWin(); // проверка на победу.
   if ( !win ) setCell(x,y, 'x');
   win = isWin(); // проверка на победу
   if ( !win ) {
    CompGame(); // запуск компьютерного игрока
    win = isWin(); // проверка на победу
   }
   if (!win) {
    gameinfo.innerText = gTexts['playing'] // отображение сообщения
   } else {
    var mes=gTexts['win1'] + win + gTexts['win2'];
    alert(mes); // отображение сообщения о победе
    gameinfo.innerText = mes;
   }
  }
 }

Прочие файлы

Так же, для игры требуются графические файлы:

  • c_null.gif - изображение пустой ячейки
  • c_x.gif - изображение ячейки с x
  • c_o.gif - изображение ячейки с o
  • fon.jpg - фоновое изображение
Если использовать GIF анимацию, то она тоже работает, но в разных браузерах начало анимации отображается слегка по разному.

Вот и всё. Попробуйте попрактиковаться в создании html-страничек, и попробуйте запустить эту игру, собрав её самостоятельно. Если получилось, то я специально недоделал сообщение о нечьей. Попробуйте самостоятельно сделать проверку на нечью, и добавить её в игру.

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

 
© www.AlexeyK.com, 2012