Крестики нолики на php
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Крестики нолики на Php
Здраствуйте)) Задали курсавой по Php нужно зделать игру крестики нолики на Php, я в этом 0.
Создание игры «Крестики нолики» на php
Народ помогите создать на обычной веб странице игру «Крестики нолики», но нужно создать так чтобы.
PHP + MYSQL Крестики нолики
Всем привет. Пытаюсь определить победителя в крестики-нолики. Ничего не получается. Данные.
Вложения
krest.zip (5.5 Кб, 638 просмотров) |
Вложения
test.rar (5.8 Кб, 813 просмотров) |
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Крестики-нолики
Как сделать так, чтобы программа могла определять 3 в ряд в крестиках-ноликах?) Спасибо большое
Крестики Нолики
Прошу помочь, я написал игру крестики нолики, но при вводе. Выводится только крестик. ПОмогите. Не.
Крестики-Нолики
Привет. Столкнулся с проблемой в скрипте. Не могу правильно присвоить каждой кнопки значение «x».
Игра крестики нолики через js видео
Мы сделаем два варианта крестиков ноликов 1,Js + html + css и 2.Js + php + html + css.
В интернете вы сможете найти массу вариантов решения данной задачки, ну и мне захотелось побаловаться на эту тему…Тем более это будет полезным в изучение выше указанных языков.
Живой пример крестики нолики javascript
Поле для крестиков ноликов на javascript
Скрипт для игры крестики нолики:
Объявим несколько переменных(var),
Получим, что есть у нас в ид =rezult и присвоим одноименной переменной это же значение.
В «button» получим что есть внутри, и далее условие, если не пустота и внутри же условие если в «rezult» крестик, то в «permennaya» либо ноль либо крестик
Вставим функцию «winner();».
Кроме объявления ременных это надо повторить еще 8 раз.
button =document.getElementById(«id_1»).innerHTML; //alert(button);
Проверка на нолик и крестики
Это надо повторить: 1) 3 горизонтальные строки 2) 3 вертикальные, и 3) 2 по диагонали.
Всё тоже самое только с ноликом повторим.
Открываем страницу и нажимаем «ctrl + U»
Итоговый листинг: внизу страницы ищем слово скачать
Использование php в формировании поля
Логику предыдущего пункта мы не будем повторять, потому, что она такая же!
Единственно отличие в написании. добавим php и сократим код.
Внесенные изменения, убрали проверку:
Добавили проверку на последний ход:
И в проверке добавили в каждую строку:
Сообщение системы комментирования :
Форма пока доступна только админу. скоро все заработает. надеюсь.
Крестики нолики «Без границ»
Крестики-нолики… в них играли все, я уверен. Игра притягательна своей простотой, особенно когда ты тянешь часы где-нибудь на уроке, паре, а под рукой нет ничего, кроме тетрадного листа и простого карандаша. Уж не знаю, кто первым когда-то догадался рисовать кресты и кружки в 9 квадратах, но с тех пор игра нисколько не потеряла в востребованности, тем более, что народ придумал огромное множество её вариаций.
Эта статья про процесс разработки ИИ на javascript для игры в одну из таких вариаций крестиков-ноликов: получилось довольно много материала, но я разбавил его анимацией и картинками. В любом случае, хотя бы стоит попробовать поиграть в это.
Отличия этого варианта игры от оригинала в следующем:
Перед тем, как начнем
Вынужден извиниться заранее за объем статьи и местами не совсем доходчивое изложение мысли, однако у меня не получилось сжать стаю без потери в содержании и качестве.
Рекомендую сначала ознакомиться с результатом. Код
Горячие клавиши и команды:
Начнем
Начать нужно с реализации самой игры, т.е. написать приложение для двух игроков, пока без бота. Для своих целей я решил использовать javascript + jquery + bootstrap4, хотя он там практически не используется, но его лучше оставить – или таблица поплывет. Тут рассказывать особо нечего, материала по js, jquery и bootstrap на хабре полно. Скажу лишь, что использовал MVC. Да и вообще, объяснять абсолютно весь код я не буду – материала и без того получилось много.
Итак, игровое поле было готово. Можно устанавливать фигуры в клетки. Но победа кого-либо из игроков никак не фиксировалась.
Сканирование «конца игры»
Игра заканчивается, когда один из игроков поставит 5 фигур в ряд. «Все просто!» — подумал я. И начал сканировать абсолютно все клетки поля: сначала все горизонтали, потом вертикали и, наконец, диагонали.
Это тупой способ, но он работал. Однако, его можно было значительно улучшить, что я и сделал: Большая часть клеток будет оставаться пустой на протяжении всей игры – игровое поле слишком большое, чтоб его можно было заполнить целиком. Поскольку сканировать его нужно было каждый ход, а за один ход ставится только одна фигура — то можно сосредоточиться только на этой фигуре (клетке): просканировать только одну горизонталь, вертикаль и две диагонали клетки, которым принадлежит та самая клетка.
Плюс ко всему, не нужно сканировать все клетки линий. Поскольку конец игры – это 5 фигур в ряд, то фигуры, удаленные друг от друга на 6 клеток нас не интересуют. Достаточно сканировать по пять клеток в каждую из сторон. Не понятно? Смотри анимацию ниже.
Приступим к самому боту
Итак, мы уже написали страницу с крестиками-ноликами. Переходим к основной задаче – ИИ.
Нельзя просто так взять и написать код, если ты не знаешь как: нужно продумать логику бота.
Суть заключается в анализе игрового поля, хотя бы его части, и просчета цены (веса) каждой клетки на поле. Клетка с наибольшим весом – самая перспективная – туда бот и поставит фигуру. Основная сложность именно в просчете веса одной клетки.
Терминология
Крестики и нолики – это фигуры.
Атакой будем называть несколько одинаковых фигур, стоящих рядом, на одной линии. По сути, это множество. Количество фигур в атаке – её мощность. Одна отдельная фигура – тоже атака (мощностью 1).
На соседних клетках атаки (на концах) могут быть пустые клетки или фигуры противника. Логично думать, что атаку с двумя пустыми клетками на «концах», мы можем развивать в двух направлениях, что делает ее более перспективной. Количество пустых клеток на «концах» атаки будем называть её потенциалом. Потенциал может принимать значения 0, 1 или 2.
Атаки обозначаем так: [ мощность атаки, потенциал ]. Например, атака [4:1].
Рис 1. Атака [4:1]
В ходе анализа мы будем оценивать все клетки, которые входят в определенную область. У каждой клетки будет просчитываться её вес. Он вычисляется на основе весов всех атак, на которые влияет данная клетка.
Суть анализа
Представим, что на игровом поле уже есть несколько атак одного и второго игрока. Кто-то из игроков делает ход (пускай крестики). Естественно ход он делает в пустую клетку – и тем самым он может:
Суть анализа в следующем:
По сути, таким алгоритмом мы проверяем, что будет, если мы пойдем так… а что будет если так пойдет оппонент. Мы смотрим на один ход вперед и выбираем наиболее подходящую клетку – с наибольшим весом.
Если какая-то клетка имеет больший вес, нежели другая, значит она приводит к созданию более опасных атак, либо к блокировке сильных атак противника. Все логично… мне кажется.
Если зайти на страницу и написать в консоли SHOW_WEIGHTS = true, можно визуально прочувствовать работу алгоритма (Будут показаны веса клеток).
Веса атак
Пораскинул я мозгами и привел такое соответствие атак и весов:
Подобрано эмпирически – возможно это не оптимальный вариант.
Я добавил в массив атаки мощностью 5 с запредельно большим весом. Объяснить это можно тем, что бот анализирует игру, смотря на шаг вперед (подставляя фигуру в клетку). Пропуск такой атаки есть ни что иное, как поражение. Ну или победа… смотря для кого.
Атаки с большим потенциалом ценятся выше.
Атака [4:2] в большинстве случаев решает исход игры. Если игроку удалось создать такую атаку, то оппонент уже не сможет ее заблокировать. Однако это еще не победа. Противник может быстрее завершить игру, даже при наличие у нас на поле атаки [4:2], поэтому ее вес ниже, чем у атак мощностью 5. Смотри пример ниже.
Рис 2. Атака [4:2]
«Рваные» атаки
В этом абзаце код не представлен. Здесь мы вводим понятие делителя атаки и объясняем суть «рваных атак».
Рассмотрим такую ситуацию: при подстановке фигуры на удалении нескольких пустых клеток, но не более 5-и, расположена еще одна.
И вроде бы, две одинаковые фигуры, на одной линии… визуально это похоже на атаку, а по факту нет. Не порядок, так как такие «рваные» атаки также несут в себе потенциальную угрозу.
Специально для таких случаев, для каждой атаки будем просчитывать делитель. Изначально его значение равно 1.
Таким образом, «рваные» атаки так же будут учитываться ИИ. На самом деле, это будут обычные атаки, но чем они дальше находятся от сканируемой клетки, тем меньшее влияние на нее оказывают и, соответственно, имеют меньший вес (благодаря делителю).
Алгоритм поиска атак
Во-первых, создадим класс атаки. У атаки будет 3 атрибута, о которых я писал ранее:
И один метод, который будет возвращать вес данной атаки:
Далее. Поиск всех атак для одной клетки мы разделим на:
Однако, нам не нужно проверять всю линию целиком. Максимальная мощность атаки, которая нас интересует – 5. Безусловно, создать атаку мощностью, скажем, 6 – возможно. Но для ИИ, который анализирует игровую ситуацию следующего хода, все равно, что 6, что 5. Перспектива получить одну из этих атак говорит о конце игры на следующем ходу. Соответственно, вес анализируемой клетки будет в обоих случаях будет одинаковым.
Здесь надо остановиться, так как может возникнуть вопрос: зачем проверять 6-ую клетку, если максимальная мощность атаки – 5. Ответ – это нужно для определения потенциала удаленной от центра атаки.
Вот пример: атака мощностью 1 на картинке находится на границе сканируемой области. Чтобы узнать потенциал этой атаки нужно «заглянуть за границу».
Рис. 3. Сканирование 6-ых клеток. Если не просканировать 6-ую клетку, можно неправильно определить потенциал атаки.
Для завершения некоторых атак может просто не хватать места. Посчитав attackplace мы заранее можем понять, какие из атак бесперспективны.
Рис. 4. Место для атаки
1) Начнем с центральной клетки. Она должна быть пустой (мы ведь собираемся сделать в нее ход, не так ли? Однако мы не забываем, что наш ИИ должен подставлять фигуры в данную клетку для анализа следующего хода. Фигура, которую мы подставляем – this.subfig – по умолчанию крестик. Поскольку центральная клетка изначально будет содержать в себе какую-либо фигуру после подстановки, то она будет принадлежать какой-то атаке this.curAttack:
Все эти пункты мы отобразили в значениях конструктора по умолчанию – смотри код выше.
2) Далее, уменьшая итератор, перебираем 5 клеток с одной стороны от сканируемой. За это отвечает функция getAttacks( cellX, cellY, subFig, dx, dy ), где:
cellX, cellY – координаты проверяемой клетки
subFig – фигура, которую мы подставляем в проверяемую клетку
dx, dy – изменения координат x и y в циклах – так мы задаем направление поиска:
Обратите внимание, что если checkCell() что-то вернет, то выполнение цикла прекращается.
3) Проверяем фигуры данных клеток.
За это отвечает функция checkCell( x, y ):
Для начала запишем фигуру в переменную fig:
Model.Field – наше игровое поле.
fig может быть ‘x’, ‘o’, ‘b’ (граница), 0 (пустая клетка).
4) Если на 5-ой клетке фигура совпадает с центральной клеткой, значит атака «уперлась» в границу и для определения потенциала атаки придется «проверить границу» ( this.checkEdge = true).
Функция checkCell – готова. Однако продолжаем работать над классом checkLine.
5) После выполнения первого цикла, надо «развернуться». Переводим итератор в центр и центральную атаку, с индексом 0, убираем из массива атак и устанавливаем как текущую.
6) Далее идем в другую сторону от текущей клетки, увеличивая итератор.
Абсолютно такая же проверка фигур. (Код уже написан – функция getAttacks)
7) Все, мы собрали все атаки, что были на линии в один массив.
На этом с классом checkLine всё… закончили.
Ну а дальше все просто – создаем объект checkLine для каждой из линий (2 диагонали, горизонталь и вертикаль) и вызываем функцию getAttacks. То есть, для каждой линии — свой объект checkLine и, соответственно, свой набор атак.
Пусть за все это отвечает функция getAllAttacks() – уже отдельно от описанных выше классов;
На выходе имеем объект со всеми атаками для проверяемой клетки
Однако вы, возможно, заметили некую функцию-фильтр. Ее задача – отсеивать «бесперспективные» атаки:
Да соберем, наконец, все воедино
Итак, основной ад позади — описан выше. Пора слепить из него что-то рабочее. Функция countWeight( x, y ) — принимает на вход координаты клетки, а возвращает ее вес. Что же у нее под капотом?
Во-первых, получим массив всех атак, которым клетка принадлежит. ( getAllAttacks( x, y ) ). Перебирая все линии, мы считаем количество брейкпоинтов. Если 2 брейкпоинта – вспоминаем, что такая ситуация может решить исход игры, и увеличиваем вес клетки на 100.
Однако все брейкпоинты должны принадлежать одному игроку, поэтому пришлось реализовать проверку в 2 шага: сначала крестики, потом нолики.
Поскольку в массиве весов атак ( ATTACK_WEIGHTS[] ) я не предусмотрел атаки мощностью 6 и больше, мне пришлось заменить их на атаки мощностью 5. Разницы никакой – все они приводят к концу игры.
Ну и суммируем веса атак – к этому все и шло.
Еще небольшой момент: чтобы бот в конце игры не тупил, когда он уже построил атаку мощностью 4 и думает над текущем ходом, необходимо значительно увеличить вес клетки для завершения такой атаки. Без этого, ИИ, просто на просто, может начать защищаться от «опасных» атак оппонента, хотя игра, казалось бы выиграна. Последний ход важен.
Теперь при вызове этой функции для конкретной клетки мы получим ее вес. Проводим эту операцию для всех клеток и выбираем наилучшую (с наибольшим весом). Туда и ходим)
Остальной код вы сможете найти на github. Материала уже предостаточно, и его изложение, как я не пытался, оставляет желать лучшего. Но если ты смог дочитать до этого момента, дорогой читатель, то я тебе благодарен.
Мое мнение о полученном результате
Сойдет! Да, его можно обыграть, однако сделать это немножко проблематично лично для меня. Возможно я просто недостаточно внимателен. Попробуйте и вы свои силы.
Знаю, что можно проще, но не знаю как. Хотелось бы выслушать людей знающих или посмотреть на иные реализации такого бота.
Знаю, что можно лучше. Да… можно воспользоваться известными алгоритмами, вроде минимакса, но для этого нужно обладать некоторой базой знаний в области теории игр, чем похвастать увы не могу.
В будущем планирую добавить анализ брейкпоитов на несколько шагов вперед, что сделает бота еще более серьезным соперником. Однако сейчас не имею четкого представления о реализации сего; лишь имею предстоящую сессию и недописанный диплом – что меня огорчает.
H Игра на чистом PHP — миф или реальность? в черновиках
Какую же игру выбрать для реализации? Воображение сразу же подсунуло целую кучу срелялок-леталок (спасибо 8 битному детству), но разум подсказывал — начни с простого. Поэтому я выбрал старые добрые крестики-нолики.
Для себя решил, что игра должна быть обязательно консольной (PHP игра, которая исполняется в браузере — слишком простая задача, а я не ищу легких путей). Все готово, пора начинать наш квест.
Шаг 1: игровое поле
Поскольку наша игра будет консольной, то прорисовывать изображения и надписи на экране мы будем с помощью символов.
Шаг 2: ход игрока
Пользователь имеет возможность выбирать номер ячейки, куда будет поставлен крестик. Компьютер же играет ноликами. Каждый раз после того, как выбор сделан, игровое поле обновляется и выводится на экран.
При этом не забываем контролировать и проверять выбор игрока.
Шаг 3: ход компьютера
Самый простой вариант — что называется «пальцем в небо», простая случайная выборка.
Но давайте добавим нашем сопернику немного интеллекта.
Шаг 4: кто же выиграл
После каждого сделанного шага (как игрока так и компьютера) следует проверять не появился ли победитель.
Шаг 5: интерактивность
Перед тем, как рисовать обновленное игровое поле, надо стереть старое. Казалось бы, что может быть проще — просто очищаем весь экран.
Но тут меня ждал неприятный сюрприз. Конструкция
не работает, если консоль запущена из-под Windows. Панику в сторону. Подход «гугл в помощь» в конце концов принес таки долгожданный результат.
Шаг 6: идем дальше
Объединяем все кусочки пазла в один класс — и вот, желаемая вершина достигнута GitHub. Однако оглянувшись я увидел, что это вершина не горы, а только маленького бугорка, а глаза уже смотрят туда, где вдалеке маячат консольные PHP экшены и игры на чистом sql.
Создание игры «Крестики нолики» на php
Помощь в написании контрольных, курсовых и дипломных работ здесь.
Крестики нолики на Php
Здраствуйте)) Задали курсавой по Php нужно зделать игру крестики нолики на Php, я в этом 0.
PHP + MYSQL Крестики нолики
Всем привет. Пытаюсь определить победителя в крестики-нолики. Ничего не получается. Данные.
вы же писали что это вы написали код JS
Вы не знаете где у вас проверка кто победил?)
Просто скопировать не получится, всё равно немного надо менять.
Добавлено через 35 секунд
ТС что значит bool и какие возможные значения такого типа? (вопрос для проверки)
Только без гугла
Loki1993, вы меня игнорируете? мне кажется здесь всё понятно, никакой джава код ТС не писал. Мне ООООчень не нравится когда люди НАГЛО врут. думаю никому не нравится!
Под переписать имелось ввиду взять код, и по аналогии написать на php, но с учётом его синтаксиса.
То есть Переписать с JS на PHP. Но не скопипастить!
И так далее, все горизонтальные, потом вертикальные, потом по диагонали, и всё. тут работы на 1 минуту.
Добавлено через 2 минуты
Вспомнил фразу, которую часто говорил преподаватель по геометрии: «Ученье свет, а за свет нужно платить!»
Ну наймите фрилансера что бы совсем всё готовое получить А то вы совсем получается думать не хотите
Loki1993, вы меня игнорируете? мне кажется здесь всё понятно, никакой джава код ТС не писал. Мне ООООчень не нравится когда люди НАГЛО врут. думаю никому не нравится!
Добавлено через 1 минуту
http://php.net/manual/ru/langu. oolean.php первое предложение. Вы не находите схожесть.
Под переписать имелось ввиду взять код, и по аналогии написать на php, но с учётом его синтаксиса.
То есть Переписать с JS на PHP. Но не скопипастить!
И так далее, все горизонтальные, потом вертикальные, потом по диагонали, и всё. тут работы на 1 минуту.
Добавлено через 2 минуты
Вспомнил фразу, которую часто говорил преподаватель по геометрии: «Ученье свет, а за свет нужно платить!»
Ну наймите фрилансера что бы совсем всё готовое получить А то вы совсем получается думать не хотите
вот теперь я понял что мне делать надо спасибо.