squadbrodyaga
@squadbrodyaga
帆は風を変えた

Как сделать алгоритм победы в больших крестиках-ноликах?

Решил сделать игру крестики-нолики, но не обычные 3 на 3, а большие.
В таких крестиках нет ограничений по полям, а чтобы победить нужно поставить 5 крестиков или ноликов в ряд по диагонали, вертикали или горизонтали.

Я смотрел видео как делать обычные крестики-нолики, там 8 победных вариантов заносили в массив, но ведь у меня такая фигня не сработает, потому что у меня этих вариантов может быть тысячи.

В общем, как можно сделать алгоритм победы, который будет проверять, что нужное количество ноликов или крестиков построено по диагонали или по вертикали?

Сейчас я просто сделал разметку игрового поля, по которому можно тыкать, но ни какой логики победы нету: https://codepen.io/squadcoder/pen/bGwwBLp?editors=0010
  • Вопрос задан
  • 353 просмотра
Решения вопроса 2
@ksnk
Берем 4 направления - [0,-1],[1,-1],[1,0],[1,1], к примеру - [0,-1] - это вверх. Инвертируем все цифры - получаем противоположное [0,1] - вниз.
Поставили, к примеру крестик.
Изменяем стартовые координаты на "направление". если там тоже крестик - идем дальше. Если нет - прекращаем.
Переключаемся на противоположное направление, считаем крестики. Если досчитали до 4-х - победа крестиков.
Если прошли все направления - отдаем ход. Ну и координатную сетку как-то надо вбить в разметку, например как-то так
// Создаю клетки 49 клеток с классом "cell"
    for(let i = 1; i <= 49; i++) {
        var x=Math.floor((i-1)/7)+1,y=((i-1)%7)+1;
        area.innerHTML += `<div class='cell' id='id-`+x+`-`+y+`'></div>`
    }

    // Отслеживаю клик по клетке и выполняю функцию cellClick()
    const cells = document.querySelectorAll('.cell')

    cells.forEach(cell => {
        cell.addEventListener('click', cellClick, false)
    })

    // Первый игрок - X
    let player = 'x'

    // В функции cellClick() я проверяю занята ли клетка, и если нет, то
    // вставляю в неё текущего игрока.
    function cellClick() {

        /**
         * проверяем, что по координатам x,y стоит нужный знак
         *
         * @param x
         * @param y - координаты
         * @param player - крестик
         * @returns {boolean} true - стоит
         */
        function check(x,y,player){
            return document.getElementById('id-'+x+'-'+y).innerHTML==player;
        }

        /**
         * считаем количество крестиков(player) от координаты x,y в "направлении" dx,dy
         * @param dx
         * @param dy
         * @param x
         * @param y
         * @param player
         * @returns {number}
         */
        function countit(dx,dy,x,y, player){
            var total=0;
            x+=dx; y+=dy;
            while (x>0 && x<=7 && y>0 && y<=7 ){
                if(check(x,y,player))
                    total++;
                else
                    break;
                x+=dx; y+=dy;
            }
            return total;
        }

        if (!this.innerHTML) {
            this.innerHTML = player;
            // so checkit
            var dirs=[[0,1],[-1,1],[-1,0],[-1,-1]],
                // вычисляем текущие координаты клика
                m=this.getAttribute('id').match(/id-(\d+)-(\d+)/),
                // вот они - координаты. Умножение для преобразования строк в числа
                x=1*m[1], y=1*m[2];
            for(var d=0;d<dirs.length;d++){
                if(5>1+ // 1 - мы поставили крестик
                    // число крестиков в направлении
                    countit(dirs[d][0],dirs[d][1], x, y, player) +
                    // и инвертированном направлении
                    countit([-dirs[d][0],-dirs[d][1]],x ,y , player)
                ){
                    // если меньше чем надо для победы - считаем дальше
                    continue;
                }
                // если нашли больше 5 крестиков в ряд - победа.
                alert('Победа '+player);
                break;
            }
        }

        // Меняю игрока, если текущий игрок сходил.
        player = player == "x" ? "o" : "x"
    }
Ответ написан
squadbrodyaga
@squadbrodyaga Автор вопроса
帆は風を変えた
Поскольку я тугодум, то мне пришлось долго разбираться в коде ksnk, но в конечном итоге я решил попробовать полностью переписать код алгоритма победы и у меня получилось, сейчас я вроде знаю как он работает.
Всем спасибо!

Код: https://codepen.io/squadcoder/pen/bGwwBLp?editors=0010 (очень сильно закомментировал)
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@foul11
Можешь попробовать сделать так:

У тебя есть функция, которая принимает 3мя аргумента позиция, крестик или нолик, сторона света, при каждом клике по полю запускай 8 раз функцию с координатами тыка, и восьмью сторонами света например от 0-7 (0 верхняя клеточка, 7 правая верхняя клеточка), если у тебя удачно найден ну например крестик в ту сторону куда запустил, запускай рекурсивно в ту же сторону, но с координатами найденого крестика, если дошел до конца и нечего нет, верни 1, подсчитай общее кол-во совпадений, тоесть сколько раз входил в рекурсию + 1 и возвращаешь результат пусть будет 5, а в том for который запускал в начале делай проверку сколько подряд должно быть, ну например для выигрыша как раз 5 и надо, значит я выиграл
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы