Крестики нолики на javascript

Приветствую вас дорогие друзья! В этом уроке я покажу, как можно сделать браузерную игру – крестики нолики, на javascript!

Крестики нолики на javascript

Все вы знаете, что это за игра и как в нее играть, но еще раз напомню:

 

Крестики-нолики — это логическая игра между двумя игроками на квадратном поле 3 на 3 клетки (возможно и бо́льшего размера). Один играет «крестиками», а второй — «ноликами».

 

P.S. как и во всех подобных уроках по javascript, в конце статьи вы можете скачать исходный файл, а также посмотреть результат работы на demo примере!

Описание создаваемой игры

Давайте рассмотрим особенности игры:

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

 

Логика

Я не стал придумывать сложных (универсальных) алгоритмов для игрового поля 3 на 3 клетки, я пошел другим путем – перебором! (об этом чуть позже).

Я выделил три основных последовательных этапа, на которых и держится вся логика:

 

1 этап: проверяем – победил ли игрок?

На этом этапе мы проверяем, имеются ли 3 клетки (на одной линии), заполненные одинаковыми символами играющего (крестиками или нолями).

Т.е. не смотря на то, какой этой ход (пусть даже первый) мы всегда сначала проверяем – выиграл ли играющий.

Вот так выглядит победа:

Победа игрока

 

2 этап: проверяем – может ли компьютер победить следующим ходом?

На этом этапе мы ищем линию, где были бы 2 клетки заполненные компьютером и одна пустая клетка – то есть пытаемся выиграть за счет невнимательности игрока.

Вот так выглядит поражение (т.е. победа компьютера):

Поражение

 

3 этап: не даем выиграть!

Здесь мы ищем такую же линию, как и на втором этапе, только 2 клетки должны быть заполнены игровыми знаками игрока, то есть на этом этапе не даем проиграть компьютеру, поставив знак в пустую клетку.

Каждый из этапов представляем собой самостоятельную функцию – это вы можете увидеть в js коде ниже.

 

Реализация

Разметка игрового поля очень простая – в основном блоке размещена строка информации (класс – result) и 9 блоков, представляющих собой клетки (класс – block)

HTML разметка клеток:

        <div class="krestiki_noliki">
                <p class="result">Ваш ход!</p>    
                <div class="block cell1"></div>
                <div class="block cell2"></div>
                <div class="block cell3"></div>
                <div class="block cell4"></div>
                <div class="block cell5"></div>
                <div class="block cell6"></div>
                <div class="block cell7"></div>
                <div class="block cell8"></div>
                <div class="block cell9"></div>   
        </div>

 

Вспомогательный класс cell[1..9] необходим для того, чтобы точно идентифицировать нужную клетку на игровом поле.

 

CSS стили для игрового поля:

.krestiki_noliki{
    width: 306px;
    margin: 0 auto;
}
.krestiki_noliki .block{
    width: 100px;
    height: 100px;
    border: 1px solid #ccc;
    cursor: pointer;
    float: left;
    text-align: center;
    font-size: 100px;
    line-height: 94px;
}

 

Теперь давайте рассмотрим весь JS код, после чего я расскажу об основных моментах:

$(document).ready(function(){
        
        var znak_user = 'O';
        var znak_comp = 'X';
        
        var rand_num = Math.round((Math.random() * (9 - 1) + 1));
        
        if( rand_num > 3 ){
                var znak_comp = 'O';
                var znak_user = 'X';
                $('.cell'+rand_num).text(znak_comp);
        }
        
        var exit_flag = false;
        var win_user_array = ['123','456','789','147','258','369','159','357'];
                
        //Определяем победу игрока
        function check_3_user(znak){
                for (var i = 0; i < 8; i++) {
                
                        var first = 'cell' + win_user_array[i].substr(0,1);
                        var second = 'cell' + win_user_array[i].substr(1,1);
                        var third = 'cell' + win_user_array[i].substr(2,1);
                        
                        if( $('.'+first).text() == znak && $('.'+second).text() == znak && $('.'+third).text() == znak ){
                                $('.'+first+',.'+second+',.'+third).css("background-color", "#83e2c3");
                                $('.result').text('Вы выиграли!');
                                $('.krestiki_noliki .block').unbind('click');
                                exit_flag = true;
                        }       
                }
        }
        
        //Определяем возможность победы компьютера
        function check_2_comp(znak){
                for (var i = 0; i < 8; i++) {
                
                        var first = 'cell' + win_user_array[i].substr(0,1);
                        var second = 'cell' + win_user_array[i].substr(1,1);
                        var third = 'cell' + win_user_array[i].substr(2,1);
                        
                        if( $('.'+first).text() == znak && $('.'+second).text() == znak && $('.'+third).text() == '' && exit_flag == false ){
                                $('.'+third).text(znak);
                                $('.'+first+',.'+second+',.'+third).css("background-color", "#EF7C7C");
                                $('.result').text('Вы проиграли!');
                                $('.krestiki_noliki .block').unbind('click');
                                exit_flag = true;
                        }       
                        
                        if( $('.'+first).text() == znak && $('.'+second).text() == '' && $('.'+third).text() == znak && exit_flag == false ){
                                $('.'+second).text(znak);
                                $('.'+first+',.'+second+',.'+third).css("background-color", "#EF7C7C");
                                $('.result').text('Вы проиграли!');
                                $('.krestiki_noliki .block').unbind('click');
                                exit_flag = true;
                        }       
                        
                        if( $('.'+first).text() == '' && $('.'+second).text() == znak && $('.'+third).text() == znak && exit_flag == false ){
                                $('.'+first).text(znak);
                                $('.'+first+',.'+second+',.'+third).css("background-color", "#EF7C7C");
                                $('.result').text('Вы проиграли!');
                                $('.krestiki_noliki .block').unbind('click');
                                exit_flag = true;
                        }       
                }
        }
        
        //Определяем ход компьютера
        function check_2_user(znak){

                for (var i = 0; i < 8; i++) {
                
                        var first = 'cell' + win_user_array[i].substr(0,1);
                        var second = 'cell' + win_user_array[i].substr(1,1);
                        var third = 'cell' + win_user_array[i].substr(2,1);

                        
                        if( exit_flag == false ){
                                if( $('.'+first).text() == znak && $('.'+second).text() == znak && $('.'+third).text() == '' ){
                                        $('.'+third).text(znak_comp);
                                        exit_flag = true;
                                }
                        }
                                                
                        if( exit_flag == false ){
                                if( $('.'+first).text() == znak && $('.'+second).text() == '' && $('.'+third).text() == znak ){
                                        $('.'+second).text(znak_comp);
                                        exit_flag = true;
                                }       
                        }       
                        
                        if( $('.'+first).text() == '' && $('.'+second).text() == znak && $('.'+third).text() == znak ){
                                $('.'+first).text(znak_comp);
                                exit_flag = true;
                        }
                        
                        if(exit_flag) break;
                }
        }
        
        $('.krestiki_noliki .block').click(function(){

                //Если клетка пустая
                if( $(this).text() == '' ){
                        $(this).text(znak_user);        
                        check_3_user(znak_user);
                        check_2_comp(znak_comp);
                        check_2_user(znak_user);
                        
                        if( exit_flag == false ){
                                for (var i = 1; i < 10; i++) {       
                                        if( $('.cell'+i).text() == '' ){
                                                $('.cell'+i).text(znak_comp);
                                                break;
                                        }       
                                }
                        }else exit_flag = false;
                        

                }
        });
});

 

Сначала мы объявляем переменные:

znak_user – в этой переменной мы храним знак, которым будет играть пользователь (по умолчанию там хранится нолик – это английская будка “О”).

znak_comp – в этой переменной мы храним знак, которым будет играть компьютер (по умолчанию там хранится крестик – это английская будка “икс”).

Далее мы генерируем случайное число (rand_num) от 1 до 9, оно необходимо нам для определения того, кто будет ходить первым, и какие будут использоваться знаки (крестик или нолик) у компьютера и игрока.

Логика такая: если случайное число больше 3, то компьютер играет ноликами, и он же (компьютер) делает первый ход.

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

exit_flag – этот флаг (переменная) отвечает за выход из функции, то есть, например, когда компьютер уже сделал свой ход, и нужно выйти из функции и передать ход игроку.

win_user_array – в этом массиве хранятся все победные варианты заполнения клеток.

Чтобы стало понятно, давайте взглянем вот на эту картинку:

Разметка игрового поля

Каждый элемент массива – это строка из трех цифр, которая является выигрышной комбинацией, то есть, например, если заполнить клетки под цифрами 1, 2 и 3, то наступит победа (или поражение).

Как видите, всего существует 8 победных вариантов, наша задача – перебрать все эти варианты.

Далее идут 3 функции:

  1. check_3_user();
  2. check_2_comp();
  3. check_2_user();

Назначение этих функций описано (в виде трех этапов) в разделе Логика (выше).

Эти функции вызываются по клику на любую из клеток поля.

В каждую из функций передается параметр (znak) – это знак игрока или компьютера (крестик или нолик), например, в функцию, определяющую победу игрока (check_3_user), мы передаем знак игрока, для того, чтобы найти 3 одинаковых знака на одной линии.

После трех функций (если компьютер еще не сделал ход), компьютер заполняем одну из свободных клеток.

Здесь, вы можете усложнить игровой процесс, например, сделав так, что если свободна центральная клетка (клетка под номером 5), то сначала ставить в нее, если она занята, то ставить в один из свободных углов (это клетки № 1, 3, 7 и 9) и так далее – в общем, здесь уже на ваше усмотрение.

Вот, в принципе и все, что требуется для создания подобной игры.

Теперь можете посмотреть игру на демо примере и скачать исходный файл (всего 1 файл).

08.06.2018 – спасибо за внимательность автору письма: Patvakan Baghdasaryan, исправлена ошибка, когда у компьютера было несколько возможных вариантов победы и закрашивались Все его победные ходы (от 4 до 6 клеток, вместо 3).

Demo пример

Скачать исходник

На этом у меня все, надеюсь, данный урок был полезен для вас, желаю вам удачи, пока!

Если вам нужна помощь в создании какого-либо функционала, сайта, сервиса, тестов или калькуляторов, то готов помочь, подробнее на странице услуг.

Крестики нолики на javascript: 5 комментариев

  1. Артавазд

    Спасибо большое

  2. Patvakan

    perviy raz, neponyatno kak eto sluchilos, no u computera vo vremya igri bil 5 vibranikh kletka a u menya vsevo li 3 i on viigral srazu dva ryadom. A vtaroy raz posle moy pobedushchiy shag on eshcko adin shag delal i pakazal mne zelyoniy moy ryad i krasniy evo ryad. Takie ashibki neskolko raz bil i ya reshil sfotografiroval, esli khatite magu atpravit

  3. Patvakan

    Dobrie vremya sutok. Ya neskolko raz igrayu kresik nolik iz vash sayta i 2 raza ne obichniy konec bil. Ya screenshot delal. Esli xatite ya magu atpravit tot kartinki. p. s. Izvinite za latinskiy alfavit.

    1. Виталий

      Спасибо за внимательность, ошибку исправил!

Обсуждение закрыто.