крестики нолики на питоне код
Новый блог GTK+ порадовал статьёй для начинающих и я решил попробовать что-то более простое, чем C++/C. Python оказался как нельзя кстати. Объём кода на Python для работы с GTK значительно меньше чем на C++, что не может не радовать.
PyGTK
PyGTK — биндинг библиотеки GTK для языка Python, PyGTK используется во многих открытых программах (например IM Gajim). Библиотека может быть очень интересна для Python программистов, поскольку проста в обращении и полностью скрывает реализацию GTK.
Под катом пример приложения.
Пример приложения
Для изучения PyGTK я решил написать простой пример — игру Крестики-Нолики.
Окно игры будет максимально простым — квадрат из кнопок 3×3.
Итак приступим к реализации. В программе есть пара классов: XO_Field и XO_Win, первый хранит информацию о поле, второй создаёт GUI для приложения и обрабатывает события.
Я использовал для примера модуль pygtk, установленный из пакетного менеджера в Ubuntu, на других системах стоит воспользоваться пакетами или python easy-install, а для Windows есть инсталлятор.
Используем модуль pygtk версии 2.0 или старше:
Создадим простое окно, по закрытию которого будем прерывать и цикл событий GTK. Функция destroy будет приведена чуть позже.
Для окна воспользуемся вертикальной компоновкой из трёх строк с горизонтальной.
Так кнопки будут расположены как раз в виде квадрата 3×3. Для каждой из кнопок добавляется обработчик события «clicked», синтаксис добавления очень похож на сигналы и слоты в Qt.
Функция, создающая кнопку:
Запуск основного цикла событий GTK и уничтожение окна:
По нажатию на кнопки происходит установка знака в указанную позицию и переход хода к следующему игроку, если ещё не определён победитель. Если игра завершена, результат выводится в заголовок окна.
Сама игра в Крестики-Нолики и её реализация довольно тривиальна, ссылка на исходный код приведена ниже. Больший интерес представляет сам цикл работы приложения Python в связке с GTK, так например сборщик мусора при сборке ссылок на объекты GTK также вызывает деструкторы для них, поскольку элементы UI содержат много ссылок на ресурсы.
Игра в игры с Python — Часть 1: крестики-нолики
Если вы случайно взглянули на мою самую первую статью о джиу-джитсу, я намекнул на тот факт, что у меня горько-сладкие отношения с видеоиграми. Они дают мне потрясающее повышение эго, когда я выигрываю, но время от времени я хочу пробить кулаком мой монитор, когда какой-то ребенок превосходит меня в Ракетной лиге. Прежде чем мы перейдем к скучным техническим вещам (которые составляют большую часть этой статьи), давайте отправимся в путешествие по моей памяти, чтобы объяснить мою мотивацию к этой статье:
Моя история с видеоиграми уходит корнями в далёкие времена, когда Nintendo пыталась спасти принцессу Пич в недавней ядовитой адской дыре киберспорта. Я окунул свои пальцы в каждый жанр — MMORPG, Shooters, Platformers, MOBA и т. Д. (Google эти термины, если вы маггл), но я продолжал возвращаться к MOBA и Shooters. Если кто-то может иметь отношение к наличию собачьего интернет-соединения, вы будете знать, что играть в онлайн-матчах — это определенно нет-нет. Поэтому я часто оказывался в игре «VS bots», где я мог отточить свои навыки, как гладиатор, полностью доминировать над ними, чувствовать себя в экстазе, выходить в интернет, чтобы сыграть в рейтинговом матче, полностью доминировать, наблюдать за моимиЭлоранжирование пойдет на ветер, плачь (именно в таком порядке). Мне не потребовалось много времени, чтобы понять, что так называемые AI-боты очень похожи на меня — будучи совершенно бесполезными. Таким образом, моя мотивация на создание лучших ИИ-ботов, чтобы я получал больше удовольствия от игр (да, это абсолютно эгоистичная причина).
Давайте теперь вернемся к обсуждаемой теме — «Крестики-нолики с кучей кода». Зритель может заметить, что я использовал фразу «связка кода» просто потому, что я не хотел сосредотачиваться только на методах обучения с подкреплением для решения игр, но также изучал другие, хотя и неэффективные, методы, такие как Tree Search, Genetic. Алгоритмы и т. Д. Я бы хотел пойти на более сложную игру, такую как Шахматы, но, будучи новичком в этой области, я решил убить свое эго и начать игру с одним из самых маленьких пространств состояний —Крестики-нолики,
Давайте посмотрим на нашего первого гладиатора:
Проекты Python для начинающих разработчиков
Проекты Python для начинающих разработчиков
Угадай число – компьютер выберет случайное число, а игроки должны будут по очереди угадывать число. При разработке используются: генератор случайных чисел, цикл while , условные конструкции if/else , переменные, целые числа и вывод на экран.
Камень, ножницы, бумага – мини-игра, в которую можно играть в одиночку с компьютером. При разработке потребуются знания генератора случайных чисел, вывод на экран, обработка ввода, цикл while и оператор if/else .
Генератор MadLibs – игра, в которой в пробелы нужно вставлять глупые слова, а после зачитывать. Для реализации понадобится понимание строк, переменных, конкатенация, ввод данных и вывод.
Генератор паролей – простое приложение, генерирующее случайный пароль. Из навыков потребуется генератор случайных чисел, работа со строками, числами, вывод на экран, последовательности.
Виселица – продвинутый вариант «угадай число». Игрок должен угадывать буквы в загаданном слове. Для упрощенной версии используйте только текст, без графики. Потребуется опыт работы со списками, генератор случайных чисел, работа со строками, обработка ввода, вывод, цикл while , операторы if/else . Для списка слов воспользуйтесь словарем Sowpods.
Симулятор игры в кости – понадобится генератор случайных чисел, который будет генерировать случайные числа от 1 до 6 , цикл while и вывод на экран для уточнения нужно ли сделать новый бросок, обработка ввода и цикл if/else для обработки введенного игроком значения.
Алгоритм двоичного поиска – структур данных, также известен как метод деления пополам. Возьмем список из 100 элементов, например, целые числа от 1 до 100 . Пользователю будет предложено ввести число, которое программа будет искать в данном списке и выводить соответствующий результат. Во время поиска берется среднее значение и сравнивается с искомым. Если значение найдено, то возвращается результат об успехе. Если значение меньше, то дальше будет аналогичным образом рассматривать левая часть, т. е. та, что меньше среднего значения. В противном случае, рассматривается правая часть. И так будет происходить до тех пор, пока значение не будет найдено или список не окажется пуст. Для реализации понадобится значение цикла, операторов if/else , ввод и вывод данных.
Текстовое приключение – простая игра квест, где игрок ходит по комнатам и получает описание комнат. Для реализации понадобится обработка ввода, вывод данных, операторы if/else , цикл while . При реализации понадобится следить за направлением движения, создавать стены, двери, ограничение на перемещение.
Пора поэкспериментировать
Мы рассмотрели основы работы с Kivy, но, я надеюсь, что вы увидели принцип построения приложений на Kivy. Мы строим приложения из отдельных виджетов, которые взаимодействуют друг с другом через изменение параметров или срабатывании событий. Мы также коротко коснулись языка kv и привели пример использования автоматического связывания свойств с событиями.
В архиве вы найдете полную копию программы для самопроверки. Мы также добавили дополнительный виджет, Interface , чтобы продемонстрировать как полностью построить структуру игры на языке kv, то есть мы показали еще один способ добавлять дочерние элементы. Проверить его вы сможете убрав комментарии со строки return Interface() в TicTacToeGrid.build . Мы не изменили ничего глобального, а всего лишь показали более углубленный пример использования языка kv, где мы использовали привязку свойств, чтобы автоматически обновлять текст на кнопках и изменять размеры поля, таким образом, чтобы оно всегда оставалось пропорциональным. Вы можете поэкспериментировать со свойствами, чтобы окончательно разобраться: за что отвечает каждое из них или изменить типы виджетов и посмотреть как будут реагировать на них другие виджеты.
Дополнительные кнпоки в совместной игре
Предложить ничью — позволяет отправить сорпенику предложение о ничьей. В случае его согласия игра будет завершена как ничья, при этом количество очков у обоих игроков не изменится;
Сдаться — завершает игру (засчитывается поражение).
Покинуть игру — позволяет немедленно завершить текущую игру (засчитывается поражение).
Создаем свою вьюшку и рисуем на ней сетку
Создадим новый файл. Для этого в правой части проекта щелкните ПКМ по ru.otus.tictactoe → New → Kotlin Class/File и введите название FieldView.
И напишите следующее в этот файл:
Обязательно нужно наследоваться от androidx.gridlayout.widget.GridLayout .
Еще нужно добавить в ресурсы в которых будет указан цвет и размер линии. Для этого ПКМ по res → New → Android Resource File.
В появившемся окне, в поле File name: написать values и нажать OK.
Появится новый файл values.xml. откройте его и напишите следующее:
Теперь ошибки должны исчезнуть.
Осталось поменять нашу вьюшку в верстке.
Что еще можно сделать
Ко всему уже изложенному, у меня остались еще несколько соображений, на счет улучшения качества алгоритма, которыми мне бы хотелось поделиться.
Игнорировать ходы, которые в принципе не могут привести к победе
Идея в том, что нет смысла производить оценку хода в некоторой линии, если количество свободных и собственных ячеек в этой линии, около ячейки, хода меньше выигрышной длины.
Объединить интуитивные рассуждения с минимаксной процедурой.
Не смотря на то, что интуитивный подход сам по себе дает не плохие результаты, его можно применить в качестве эвристики в минимаксной процедуре. Это должно повысить качество решений, принимаемых алгоритмом.
Упростить определение терминального состояния.
Условием терминального состояния, для минимаксной процедуры, является победа одного из игроков или ничья. Если для представления игрового поля вы используете двумерный массив, то можно избежать его перепросмотра с целью найти победную комбинацию после каждого совершенного хода.
Идея заключается в том, что состояние игры изменяется в результате хода, который влияет не на все поле целиком, а только на окрестность ячейки, в которую был выполнен ход, в радиусе выигрышной длины. Достаточно проверять, не привел ли ход к завершению игры и в соответствии с этим менять состояние игрового поля.
Для ничьи, ничего умнее полного перебора предложить не могу. Были мысли по кешированию свободных клеток, но это скорее только навредит.
Сократить количество потенциальных ходов
Обычно, в качестве возможных ходов, выбираются пустые клетки поля. Но если поле имеет относительно большой размер, вариантов ходов может оказаться очень много. Есть подозрения, что достаточно рассматривать не все пустые клетки поля, а только пустые клетки в окрестности уже занятых:
Такой подход дает большой выигрыш на больших полях, практически нивелируя влияние размера поля на время действия алгоритма.
Добавить критерии оценки хода
Помимо длины, собираемой в результате хода последовательности, в роли критерия качества хода можно брать полное количество своих (или чужих) клеток в ряду:
Игра за крестики до 5. Ход «б» приводит крестиков к победе |
Теоретически, это должно позволить повысить интеллектуальность алгоритма, тк позволит строить алгоритму «вилки». Но здесь важно аккуратно подойти к выбору функций, зависящих от таких параметров. Общее количество клеток в ряду, зачастую, будет выше количества клеток, идущих подряд, что может привести к иррациональному поведению алгоритма.
Pubblicato il
Спасибо за видео, ты лучше всех остальных, кто рассказывает о питоне, выбрал тебя и все, когда что-то забываю — смотрю тебя) В принципе контента много, всегда есть что найти) А про это видео еще не смотрел, не было нужды) Объясняешь толково и по теме, голос для ушей счастье и диктовка текста отличная, продолжай, уверен 100к+ подписчиков точно будет, молодец!)
Дядя Артем — как же хочется — чтоб ты в своей манере запилил видосы по ООП и Классам на пайтон, ну очень надо))))
Круто! Заделал. Все же пайтон интуитивно понятный, Круг нарисовал просто просто по логике, пока видео стояло на паузе.
Спасибо, за понятное объяснение для чайников. Давно думаю написать программу для решения судоку. Поможешь?
Привет! Очень нравятся твои видосы. Я недавно перешёл на python с плюсов и твои уроки очень помогают!! Спасибо))
честно, я в шоке) такой лаконичный яп. на JavaScript этот самый код, выглядел бы, раза в 3 длиннее! начинаю изучать Python)))
У меня к Вам вопрос? Ваша программа отрисовывает поле с частотой прохода цикла по true. При этом бОльшую часть времени поле статично и не изменяется. Можете сделать пример с прорисовкой только изменений а не всего поля? То есть только после нажатия клавиши происходит перерисовка 1 квадрата, а не всех. Тем более, не полная проверка массива каждый тик процессора. Спасибо за труд!
Да да. Почему просто бы не переключать очередь true на false после каждого хода(true красный, false зеленый к примеру)
про динамическое программирование хотелось бы чегонить, примеров решения задач, как это в код превращается.. вроде с теоретической часть более менее что то понятно и даже самые простые задачи удается решать. но хотелось бы побольше в той теме, но в основном в сетях лекции по 1-2 часа (откуда теоретическую базу и подтягиваю) а практики мало.
Почему то у меня выходит только 3 квадрата диагональю, остальное поле чёрное. Что делать подскажите пожалуйста
@egoroff_channel спасибо, а то я уже всё сделал, а дальше жду вашего видео)) Всё закоментировал, чтобы вникнуть в код)
Забавный баг, нажимаешь допустим крестик, по идей следущий 0 , но если кликнуть на х, можно ещё раз сходить x)
Народ на 3 минуте надо дописать тоже самое только в конце fliip поставить потом до этого убрать color и поставить green ,автор посмотри и можешь как то подробнее о них рассказать :)?
Люди пожалуйста скиньте исходный код . У меня не получилось на моменте заполния красным цветом . Помогите пожалуйста!
добрый день,немного не по теме,но подскажите,пожалуйста: модуль пайгейм установлен,могу им пользоваться через idle sublime и тд,но хочется заниматься разработкой в пайчарме,но в настройках при установке выдаёт ошибку(ниже),при попытке скачать любую версию модуля,знаете,в чем может крыться проблема? Collecting pygame==1.9.6 Using cached files.pythonhosted.org/packages/0f/9c/78626be04e193c0624842090fe5555b3805c050dfaa81c8094d6441db2be/pygame-1.9.6.tar.gz Complete output from command python setup.py egg_info: WARNING, No «Setup» File Exists, Running «buildconfig/config.py» Using WINDOWS configuration. Download prebuilts to «prebuilt_downloads» and copy to «./prebuilt-x86»? [Y/n]Traceback (most recent call last): File «», line 1, in File «C:UsersДНСAppDataLocalTemppycharm-packagingpygamesetup.py», line 194, in buildconfig.config.main(AUTO_CONFIG) File «C:UsersДНСAppDataLocalTemppycharm-packagingpygamebuildconfigconfig.py», line 210, in main deps = CFG.main(**kwds) File «C:UsersДНСAppDataLocalTemppycharm-packagingpygamebuildconfigconfig_win.py», line 576, in main and download_win_prebuilt.ask(**download_kwargs): File «C:UsersДНСAppDataLocalTemppycharm-packagingpygamebuildconfigdownload_win_prebuilt.py», line 302, in ask reply = raw_input( EOFError: EOF when reading a line
pip под windows проблемно работает с путями в которых есть русские буквы. У вас путь содержит русские буквы: C:UsersДНС.
Реализация программы «крестики-нолики»
Предлагать Вам полный код всей программы я не буду, все же лучше чему то научится самим. Но основной костяк программы я вам предложу. Собирать же воедино останется Вам. Итак, начнем мы с основополагающих правил. Надеюсь, вы не забыли, что эти правила должны проверяться перед каждый ходом.
Проверка на возможность победы
Перед тем как писать код, необходимо уяснить смысл ее работы. Выигрышных комбинаций всего 8. Можете посмотреть скриншоты: я специально выделил и указал номер этих комбинаций(они понадобятся нам). Эти номера комбинаций будет хранить переменная cherta, которая сразу после выигрыша отдаст команду нарисовать выигрышную черту.
Мы должны проверить каждую из этих комбинаций на предмет того, стоят ли там две наши крестики(или нолики), а так же свободно ли третья клетка. Но перед тем как мы перейдем к этому, я немного познакомлю вас с другой основой программы.
Для хранения ходов как компьютера, так и пользователя прекрасно подходит обычная матрица 3×3, в которой можно указывать специальный номер ходившей стороны. Для своей игры я задал такие значения:
- Изначально матрица обнуляется и это значит, что все 9 клеток пусты. Перед каждый ходом нужно проверять, пустая ли клетка, и можно ли на нее сходить. Полезно, пользуйтесь.
- Для обозначения компьютера я использовал цифру 1.
- Для обозначения пользователя я использовал цифру 2.
Далее нам необходимо будет создать специальный метод, который будет отрисовывать игровое поле, используя данные этой матрицы(метод paint, который будет мелькать в коде). А вот собственно и код данного метода:
Тут так же появляется переменная win, которая хранит значение победившей стороны. Я использовал только два значения: 0-ничья, 1 — победа компьютера. В моей программе нет даже поздравления пользователя с возможной победой, так как это невозможно.
Проверка на возможность проигрыша следующим ходом
Как видите, смысл защиты от возможного поражения является почти что точной копией предыдущего метода. Тут стоит лишь напомнить и уточнить несколько вещей:
- Ходы противника мы отмечаем значением 2. Для этого используется массив a.
- Метод paint вызывает отрисовку на основе данных матрицы.
- Переменная булевого типа hdpc(hod pc, ход компьютера) принимает значение false, если пришла очередь ходить пользователю.
Дирижер всех ходов компьютера
Я использовал несколько переменных, которые сохраняли некоторое значение, на основании которых можно было бы понять, чей сейчас ход и кто ходил первым. Очень важным моментом всей программы является необходимость передавать управление то пользователю, то компьютеру. Для этого я рекомендую простой способ: лично я использовал элемент panel, который выполняет роль игрового поле. С помощью булевой переменной hdpc, я либо разрешал принимать нажатие мышкой пользователя на panel, либо нет, что обеспечивало только своевременный ход пользователя. Так же сразу после хода пользователя я запускал на действие специальный метод, который я образно назвал дирижером всех ходом компьютера. В чем это определение очень даже подходит для него, ведь именно здесь будут приниматься решения, какой метод активировать, то есть именно тут можно увидеть всю стратегию данной игры:
[code language=»csharp»]nichia(); //проверяем, если хотя бы одно свободное место на поле. Если да, то ходим. Если нет, то вывод сообщения о ничье. Данный метод предлагаю написать вам самим, он довольно прост.
pobeda(); //это тот самый метод для проверки возможности выигрыша
if (win == 0) //как помните мы использовали переменную win, чтобы обозначить победу компьютера. Если компьютер еще не выиграл, то продолжаем
zachita(); //этот метод мы так же описали. Компьютер защищается от возможного проигрыша
if (hdpc == true) //до сих пор ход компьютера, а это значит компьютер пока не может выиграть и поражением никто не пугает, а значит можно ходить по стратегии
if (pc == 1) //данная переменная хранит информацию о том, кто первым ходил. Если первым ходил компьютер, то значение равно 1, если пользователь — то 2.
krestiki(); //так называется метод, который выполняет ход в самый отдаленный угол от предыдущего хода пользователя
>
else //компьютер ходит вторым
if (xfir == 1 && yfir == 1) //пользователь первым ходом сходил в центр
ugol(); //ищем любой свободный угол и ходим туда, если это невозможно, ходим в любую свободную клетку
>
else //пользователь первым ходом не сходил в центр
if (pervhod) //данная булевая переменная хранит true, если пользователь собирается сделать первый ход в этой партии
hod1(); //ходим в центр
pervhod = false;
>
else
ugol(); //ходим в свободный угол
>
>
>
> //конец противоположного хода
nichia();
>
else
winner();
>[/code]
В данной методе, который я заботливо уложил комментариями, и хранится вся стратегия игры в «крестики-нолики». Нам же остается дописать все необходимые методы.
Ход в противоположный от предыдущего хода угол
Данный метод, который в представленном коде был назван как krestiki, выполняет ход в противоположный от предыдущего шага пользователя угол. Чтобы выполнить данную операцию, мы должны знать, куда последним шагом сходил пользователь. Именно для этих целей я использую специальные переменные. Парочку из них(xfir и yfir — сократил от x first и y first) я уже использовал в предыдущем методе. Данные переменный запоминают только первый ход пользователя. Следующие переменные, которые вы встретите, будут хранить каждый последний шаг пользователя.
В данном методе мы знакомимся с новым методом random, который отвечает, надеюсь вы догадались, за абсолютно рандомный(случайный шаг). Помните, в стратегии есть и такие ходы. Данный метод я так же оставлю для реализации Вам.
Ход в любой из углов
Последний метод, который я опишу в данной статье, которая неимоверно растянулась, это ход в любой из пустых углов, если конечно такая возможность имеется. Любуйтесь!
[code language=»csharp»]if (a[0, 0] == 0)
a[0, 0] = 1;
hdpc = false;
paint();
>
else
if (a[2, 0] == 0)
a[2, 0] = 1;
hdpc = false;
paint();
>
else
if (a[0, 2] == 0)
a[0, 2] = 1;
hdpc = false;
paint();
>
else
if (a[2, 2] == 0)
a[2, 2] = 1;
hdpc = false;
paint();
>
else
random();
>
>
>
>[/code]
Данный метод сделан на основе предыдущего метода, разница лишь в том, что в нем отсутствуют лишние проверки. Тут все просто: находим пустой угол — ходим, не находим — ходим рандомно.
Я понимаю, что приведенная часть это только половина всей программы. Но это основная половина всей программы. В ближайшее время я напишу еще одну статью, в которой опишу «рисовательную» часть этой программы, а так же укажу как отловить ход пользователя на panel`и. Напомню, что все это будет на языке C#. Так же напомню, что мы только что писали код программы, которая имитирует игру компьютера с пользователем в «Крестики-нолики»
Update: Боюсь у меня нет времени и еще больше нет желания заново разбираться в игре, которую я некогда написал и поэтому, скорее всего, обещанная рисовательная часть программы и прочие фишки никогда не увидят свет на страницах сайта About-windows.ru. В связи с этим просто предлагаю вам скачать исходник этой игры и дальше уже самим разобраться в ее коде. Прошу не судить строго по поводу «красоты» программирования.
P.S. Для тех кто заявляет, что программу можно выиграть, просьба предоставить доказательства(скриншот; порядок ходов с указанием того, кто начинает партию). При этом не нужно обременять себя рассказами про Ваши геройства, если вы играли нечестно(защита от дурака и хакера не продумана так же хорошо, так алгоритм программы).