В данной статье мы разработаем небольшую консольную программу «Крестики-нолики» для закрепления темы «Функции в Python«. Сначала рекомендуем изучить теорию создания функций и потом возвращаться к этой статье.
Используемые функции в программе
draw_board() — рисует игровое поле в привычном для человека формате. take_input() — принимает ввод пользователя. Проверяет корректность ввода. check_win — функция проверки игрового поля, проверяет, выиграл ли игрок. main() — основная функция игры, которая будет запускать все ранее описанные функции.
Данная функция запускает и управляет игровым процессом.
Полный листинг программы
print(«*» * 10, » Игра Крестики-нолики для двух игроков «, «*» * 10) board = list(range(1,10)) def draw_board(board): print(«-» * 13) for i in range(3): print(«|», board[0+i*3], «|», board[1+i*3], «|», board[2+i*3], «|») print(«-» * 13) def take_input(player_token): valid = False while not valid: player_answer = input(«Куда поставим » + player_token+»? «) try: player_answer = int(player_answer) except: print(«Некорректный ввод. Вы уверены, что ввели число?») continue if player_answer >= 1 and player_answer 4: tmp = check_win(board) if tmp: print(tmp, «выиграл!») win = True break if counter == 9: print(«Ничья!») break draw_board(board) main(board) input(«Нажмите Enter для выхода!»)
Функция draw_board()
Мастер класс Python. Игра крестики-нолики. Консоль
Внутри программы игровое поле представлено в виде одномерного списка с числами от 1 до 9.
Функция take_input()
Задачи данной функции: 1. Принять ввод пользователя. 2. Обработать некорректный ввод, например, введено не число. Для преобразования строки в число используем функцию int(). 3. Обработать ситуации. когда клетка занята или когда введено число не из диапазона 1..9. Для обработки некорректного ввода мы используем блок try…except.
Если пользователь введет строку, то выполнение программы не прервется, а будет выведено сообщение «Некорректный ввод. Вы уверены, что ввели число?», а затем цикл перейдет на следующую итерацию с возможностью по-новому ввести число.
Функция check_win()
Данная функция проверяет игровое поле. Мы создаем кортеж с выигрышными координатами и проходимся циклом for по нему. Если символы во всех трех заданных клетках равны — возвращаем выигрышный символ, иначе — возвращаем значение False. Непустая строка(выигрышный символ) при приведении ее к логическому типу вернет True.
Функция main()
В данной функции создаем цикл while. Цикл выполняется пока один из игроков не выиграл. В данном цикле мы выводим игровое поле, принимаем ввод пользователя, при этом определяя токен(икс или нолик) игрока. Ждем, когда переменная counter станет больше 4 для того, чтобы избежать заведомо ненужного вызова функции check_win. Переменная tmp была создана для того, чтобы лишний раз не вызывать функцию check_win, мы просто «запоминаем» ее значение и при необходимости используем в строке «print(tmp, «выиграл!»)». Вывод программы:
Наша игра получилась очень простой. Рекомендуется самостоятельно написать данный код для полного его понимания. Ждем ваших предложений по улучшению или модернизации данной игры. Видео по созданию игры:
Источник: it-black.ru
Как написать программу для игры в крестики нолики
Don’t learn to code. Code to learn!
Введение в Python
- Python — Обзор
- Основы синтаксиса Python
- Операторы в Python
- Типы данных в Python
- Условные конструкторы в Python
- Циклы в Python
- Функции в Python
- Функциональное программирование в Python
- ООП в Python
- Модули в Python
- Работа с файлами в Python
- Обработка исключительных ситуаций в Python
Сегодня перед нами стоит задача написать игру крестики-нолики на питоне. Напомним, что крестики-нолики это логическая игра для двух игроков на поле 3х3 клетки.
Для начала зададим поле. Поле у нас будет одномерным списком (list) с числами от 1 до 9. Для создания воспользуемся функцией range()
board = range(1,10)
Теперь напишем функцию, которая будет выводить наше поле в привычном формате.
def draw_board(board): print «————-» for i in range(3): print «|», board[0+i*3], «|», board[1+i*3], «|», board[2+i*3], «|» print «————-»
Результат выполнения данного кода
Самое время дать пользователям возможность вводить данные в нашу игру. Пишем функцию take_input
def take_input(player_token): valid = False while not valid: player_answer = raw_input(«Куда поставим » + player_token+»? «) try: player_answer = int(player_answer) except: print «Некорректный ввод. Вы уверены, что ввели число?» continue if player_answer >= 1 and player_answer
Как вы видите, функция take_input принимает параметр player_token — крестик или нолик, в зависимости от того, чей сейчас ход. Нам важно ограничить выбор пользователя числами от 1 до 9. Для этого мы используем конструкции try/except и if/else, чтобы удостовериться, что выбранная клеточка не занята. Обратите внимание, что функция take_input не возвращает никакого значения, а только изменяет имеющийся список board.
Осталось написать функцию проверки игрового поля. Назовем эту функцию check_win.
def check_win(board): win_coord = ((0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)) for each in win_coord: if board[each[0]] == board[each[1]] == board[each[2]]: return board[each[0]] return False
Проверка результатов игры крестики-нолики достаточно распространенная задача по программированию. Как часто бывает, одно и то же задание в программировании можно решить несколькими способами.
В данном случае мы просто создали кортеж (tuple) с выигрышными координатами и прошлись циклом for по нему. Если символы во всех трех заданных клетках равны — возвращаем выигрышный символ, иначе — возвращаем значение False. При этом важно помнить, что непустая строка (наш выигрышный символ) при приведении ее к логическому типу вернет True (это понадобится нам в дальнейшем).
Осталось создать функцию main, в которой мы соберем вместе все описанные функции.
def main(board): counter = 0 win = False while not win: draw_board(board) if counter % 2 == 0: take_input(«X») else: take_input(«O») counter += 1 if counter > 4: tmp = check_win(board) if tmp: print tmp, «выиграл!» win = True break if counter == 9: print «Ничья!» break draw_board(board)
Работа функции main предельно понятна, разве что строки 45 и 46 могут вызвать непонимание. Мы ждем когда переменная counter станет больше 4 для того, чтобы избежать заведомо ненужного вызова функции check_win (до пятого хода никто точно не может выиграть). Переменная tmp была создана опять же для того, чтобы лишний раз не вызывать функцию check_win, мы просто «запоминаем» ее значение и при необходимости используем на строке 48. Польза от такого подхода не так заметна при работе с небольшими объемами данных, но в целом подобная экономия процессорного времени — хорошая практика.
Теперь мы можем спокойно играть, запустив main(board)
И последнее уточнение. Для того, чтобы у вас корректно отображались символы кириллицы вставьте следующий код в самое начало вашего файла.
# -*- coding: utf-8 -*-
PS. Исходный код игры крестики-нолики на Python 3 на github
Источник: www.pythonicway.com
Python: нестандартные функции. Игра «Крестики-нолики».
Продолжаем учить язык программирования пайтон Python. Переходим к изучению 6 главы «Функции. Игра Крестики-нолики» по книге: Майкл Доусон “Программируем на Python”, 2014 (Michael Dawson “Python Programming for the Absolute Beginner”, 3rd Edition), чтобы создавать собственные функции и работать с глобальными переменными.
Как создать функцию?
Общий вид функции в Python: название_функции()
Чтобы создать собственную функцию, нужно ее объявить.
Общий вид объявления функции
def название_функции(параметр1, параметр2. ):
»’Документирующая строка»’
Блок выражений функции
Функции могут:
- принимать значения через параметры,
- возвращать значения через return .
Параметр функции
— это имя переменной в скобках после названия функции. В момент объявления функции параметр может не иметь конкретного значения. При вызове функции параметру нужно присвоить значение.
Позиционные параметры функции
В функции можно перечислить несколько параметров:
def название_функции(параметр1, параметр2. ):
Вызов этой функции с позиционными аргументами :
название_функции(‘значение параметра1’,значение параметра2. )
Вызов этой функции с именованными аргументами (для них не важен порядок!) :
название_функции(параметр1=’значение параметра1′, параметр2=значение параметра2. )
название_функции(параметр2=значение параметра2, параметр1=’значение параметра1′. )
Параметры по умолчанию
def название_функции(параметр1=’значение’, параметр2=значение. ):
Если при вызове функции никакие другие значения параметрам не присвоятся, то отобразятся значения параметров по умолчанию.
Присваивая значение по умолчанию одному параметру, это нужно сделать для всех остальных параметров в объявляемой функции.
Параметры по умолчанию можно переопределить при вызове функции, при чем переопределять их можно и по отдельности, а не все сразу. Например, так:
def название_функции(параметр1=’значение’, параметр2=значение):
Функция, которая возвращает значения
def vozvrat():
imya=’kot’
return imya
def vozvrat(): imya=’kot’ return imya print(‘Возврат: ‘, vozvrat())
Запуск программы дает:
Возврат: kot >>>
Можно возвращать несколько значений через запись return p1,p2,p3.
Функция main()
Основной код программы можно не оставлять в глобальной зоне видимости, а поместить в функцию, которое можно дать любое имя, например, main()
Тогда код запуска программы будет выглядеть так:
main()
input(‘Нажмите Entr, чтобы выйти’)
Глобальные переменные
Переменные внутри функции доступны только там. Есть глобальные переменные, которые объявляются вне функций, при этом они доступны внутри функций тоже, то только для «чтения», если не указано обратное.
Глобальная переменная — создается в общей области видимости.
Локальная переменная — создается внутри функции.
Изменение глобальной переменной внутри функции
Чтобы менять глобальные переменные, находясь внутри функции, пишем global
Если создана глобальная переменная g_peremennaya , то изменить ее внутри функции можно написав: global g_peremennaya
Затенение глобальной переменной
Так как в общем случае внутри функции нельзя изменить значение глобальной переменной, но можно создать одноименную переменную внутри функции. Это и будет затенение. Новая одноименная переменная будет работать только внутри функции. Но это вносит путаницу, лучше так не делать.
Глобальные константы
Переменные мы изменяем по ходу кода. А константы — это переменные, записанные большими буквами ( CONSTANTA ), которые мы решили не менять. В общем случае лучше использовать глобальные константы, чем глобальные переменные.
Игра «Крестики-нолики»
Задача: написать программу, в которой пользователь может играть с компьютером в крестики-нолики на поле 3х3. Сначала показывается инструкция к игре. Далее идет выбор, кто будет ходить первым. Начинается игра, игроки делают ходы по очереди. Когда кто-то выигрывает или игра сыграна вничью, выводятся результаты и программа завершает работу.
Начнем с создания собственной функции, которая будет показывать пользователю инструкцию к игре :
def instrukciya(): print(»’ Привет! Это игра «Крестики-нолики». Чтобы сделать ход, введи номер клетки, куда хочешь поставить свой символ: 0 | 1 | 2 ——— 3 | 4 | 5 ——— 6 | 7 | 8 »’)
Игра начинается с того, что пользователь выбирает, кто делает первый ход.
Для этого напишем функцию, которая задает пользователю вопрос «Вы хотите быть первым, кто сделает ход (играть крестиками)?» , на который можно ответить «да» или «нет». В объявлении функции можно на задавать конкретный вопрос, можно написать просто vopros , а потом при вызове функции в скобках написать любой текст.
Чтобы реализовать этот блок программы, сначала объявим первую общую функцию, которая будет задавать вопрос и получать ответ «да» или «нет»:
def nachalo(vopros): otvet=None while otvet not in (‘да’,’нет’): otvet=input(question).lower() return otvet
Вторая часть функции присваивает игрокам тип фишек в зависимости от того, кто ходит первый, и будет состоять из уже объявленной функции nachalo(vopros) :
def fishki(): perviy_hod=nachalo(«Вы хотите быть первым, кто сделает ход (играть крестиками)? «) if perviy_hod==’да’: print(‘Окей, ты играешь крестиками!’) human=Х comp=O else: print(‘ОК, я делаю первый крестиками’) human=O comp=Х return human, comp
В этих двух функциях мы используем имена переменных Х и O , чтобы компьютер правильно их использовал в игре, нужно дополнительно ввести эти переменные на глобальном уровне. То есть объяснить, что значит X и O :
Глобально задаем переменные: X=’X’ O=’0′
Далее в программе нужно сделать функцию, которая будет спрашивать о том, куда пользователь хочет поставить свою фишку . Поле будет 3х3 и каждому полю условно дается свой номер от 0 до 8. То есть нужно сделать функцию, куда пользователь введет номер клетки для своего хода.
def hod(vopros,low,high): otvet=None while otvet not in range(low,high): otvet=int(input(vopros)) return otvet
Сделаем функцию, которая генерирует игровые поля :
- потребуется две глобальные константы: RAZMER_DOSKI и HODI
RAZMER_DOSKI=9 HODI=’ ‘
Функция, создающая каждый раз новую доску с ходами выглядит так:
def new_doska(): doska=[] for i in range(RAZMER-DOSKI): doska.append(HODI) return doska
Теперь нужно сделать функцию, которая будет показывать пользователю доску с результатом каждого хода:
def pokaz_doski(doska): print(‘n’, board[0], ‘|’, board[1], ‘|’, board [2]) print(‘———‘) print(‘n’, board[3], ‘|’, board[4], ‘|’, board [5]) print(‘———‘) print(‘n’, board[6], ‘|’, board[7], ‘|’, board [8], ‘n’)
Нам еще потребуется функция, которая проверяет, куда можно пойти. Для этого нужно сделать функцию с перебором всех пустых клеток, чтобы все незанятые места добавились в список, который и есть «доступные ходы»:
def dostupnie_hodi(doska): dostupnie_hodi=[] for i in range(RAZMER_DOSKI): if doska(i)== HODI: dostupnie_hodi.append(i) return dostupnie_hodi
Отдельно сделаем функцию, которая выводит победителя. Если победит игрок, ставящий крестики, то функция выдаст X , если победитель играл ноликами — 0 , ничья задается глобальной константой NICHYA=’Ничья’ , если игра еще не дошла до конца, то функция выдаст None . Есть способ определения победы через перебор всех возможных наборов из трех клеток, при которых игрок считается победителем:
def winner(doska): VAR_POBED=((0,1,2), (3,4,5), (6,7,8), (0,3,6), (1,4,7), (2,5,8), (0,4,8), (2,4,6)) for i in varianti_pobed: if doska[i[0]]==doska[i[1]]==doska[i[2]]!=HODI: winner=doska[i[0]] return winner if HODI not in doska: return NICHYA return None
Следующая функция учитывает ходы пользователя, для этого нужно сначала понять, куда можно пойти, затем ожидается ввод пользователя числа из доступных. Функция принимает доску и тип фишек пользователя. В итоге работы функции пользователь делает ход:
def human_hod(doska,human): dostupnie=dostupnie_hodi(doska) hod=None while hod not in dostupnie: hod=hod(‘Твоя очередь ходить. Напиши номер поля 0-8: ‘, 0,RAZMER_DOSKI) if hod not in dostupnie: print(‘Поле занято. Напиши другой номер: ‘) print(‘Супер!’) return hod
Пришло время самой сложной для меня функции — это ходы компьютера. Нужно, чтобы компьютер делал «хорошие» ходы, старался выиграть у пользователя.
Ходить наугад можно, если компьютер будет выбирать любое свободное место на поле. Но тогда ему будет трудно выиграть.
Чтобы не «испортить» исходную доску, опытные программисты советуют создавать внутри функции «копию» доски, в которую мы и будем вносить изменения:
def comp_hod(doska,comp,human): doska=doska[:]
Чтобы компьютер не ходил «от балды», учтем следующую стратегию:
- «лучшее» поле — по центру;
- если центральное поле уже занято, то «лучшими» считаются угловые поля;
- компьютер ходит в «лучшее» из свободных мест на поле.
Лучшие поля задаются константой внутри функции:
BEST_HODI=(4,0,2,6,8,1,3,5,7)
В итоге вся функция ходов компьютера получается такой:
def comp_hod(doska,comp,human): doska=doska[:] BEST_HODI=(4,0,2,6,8,1,3,5,7) print(‘Мой ход: ‘) for i in dostupnie_hodi(doska): doska[i]=comp if winner(doska)==comp: print(hod) return hod doska[i]=HODI for j in dostupnie_hodi(doska): doska[j]=human if winner(doska)==human: print(hod) return hod doska[j]=HODI for k in dostupnie_hodi(doska): print(k) return k
Нужна еще одна функция, которая будет давать сделать ход следующему игроку, определяя какими фишками был сделан последний ход и передавая ход другим фишкам:
def next_hod(hod): if hod==X: return O else: return X
Потребуется еще функция, которая выявит победителя и поздравит пользователя с окончанием игры. Эта функция будет использоваться только в самом конце игры:
def pozdrav_pobeditela(pobeditel,comp,human): if pobeditel!=NICHYA: print(‘Собрана линия ‘, pobeditel) else: print(NICHYA) if pobeditel==comp: print(‘/n Компьютер выиграл!’) elif pobeditel==human: print(‘Ты победил!’) elif pobeditel==NICHYA: print(NICHYA)
Когда у нас есть все функции, нужно записать общую функцию main() , которая объединит все отдельные функции в единое целое:
def main(): instrukciya() comp,human=fishki() hod=X doska=new_doska() pokaz_doski(doska) while not winner(doska): if i==human: hod=human_hod(doska,human) doska[hod]=human else: hod=comp_hod(doska,comp,human) doska[hod]=comp pokaz_doski(doska) i=next_hod(hod) pobeditel=winner(doska) pozdrav_pobeditela(pobeditel,comp,human)
Попробуем запустить программу с игрой «Крестики-Нолики», для запуска потребуется всего две строки кода:
main() input(‘n Нажми Entr, чтобы выйти’)
Запуск программы показал, что игра не работает как надо. Несмотря на то, что логика построения программы верная, в самих функциях где-то допущены ошибки. Нужно их исправить.
Исправление ошибок в игре «Крестики-нолики».
Тестирование программы игры и исправление ошибок оказалось довольно трудной задачей, чтобы сделать это «на глаз». Как искать ошибки в программе? Наверное, лучший способ — это протестировать работу каждой функции отдельно. Запустим каждую функцию и посмотрим, где есть проблемы:
Функция instrukciya() работает:
Привет! Это игра «Крестики-нолики». Чтобы сделать ход, введи номер клетки, куда хочешь поставить свой символ: 0 | 1 | 2 ——— 3 | 4 | 5 ——— 6 | 7 | 8 >>>
Запускаем функцию fishki() , и с ней все в порядке:
Вы хотите быть первым, кто сделает ход (играть крестиками)? да Окей, ты играешь крестиками! >>>
В функции hod(low,high) я решила добавить конкретный вопрос, и ее запуск тоже прошел успешно со значениями 0-8 hod(0,8) :
Делай свой ход — напиши номер поля (0-8): 2 >>>
Запуск функции new_doska() ошибок не выдал, но и результата тоже, так как изначально этот блок пустой.
Спустя еще пару часов блужданий по коду, поиска ошибок, запусков отдельных функций и групп функций, я обнаружила, что в нескольких местах знак «крестика» X был написан разными символами, а также кое-где крестик стоял в кавычках. Еще некоторые мелочи были исправлены. Конечный вариант кода программы (которая заработала и выиграла у меня!) выглядит так:
X=’X’ O=’0′ RAZMER_DOSKI=9 HODI=’ ‘ NICHYA=’Ничья’ def instrukciya(): print(»’ Привет! Это игра «Крестики-нолики». Чтобы сделать ход, введи номер клетки, куда хочешь поставить свой символ: 0 | 1 | 2 ——— 3 | 4 | 5 ——— 6 | 7 | 8 »’) def nachalo(vopros): otvet=None while otvet not in (‘да’,’нет’): otvet=input(vopros).lower() return otvet def fishki(): perviy_hod=nachalo(«Вы хотите быть первым, кто сделает ход (играть крестиками)? «) if perviy_hod==’да’: print(‘Окей, ты играешь крестиками!’) human=X comp=O else: print(‘ОК, я делаю первый ход крестиками’) human=O comp=X return comp, human def hod_number(low,high): otvet=None while otvet not in range(low,high): otvet=int(input(«Делай свой ход — напиши номер поля (0-8): «)) return otvet def new_doska(): doska=[] for i in range(RAZMER_DOSKI): doska.append(HODI) return doska def pokaz_doski(doska): print(‘n’, doska[0], ‘|’, doska[1], ‘|’, doska [2]) print(‘———‘) print(‘n’ , doska[3], ‘|’, doska[4], ‘|’, doska [5]) print(‘———‘) print(‘n’, doska[6], ‘|’, doska[7], ‘|’, doska [8], ‘n’) def dostupnie_hodi(doska): dostupnie_hodi=[] for i in range(RAZMER_DOSKI): if doska[i]== HODI: dostupnie_hodi.append(i) return dostupnie_hodi def winner(doska): VAR_POBED=((0,1,2), (3,4,5), (6,7,8), (0,3,6), (1,4,7), (2,5,8), (0,4,8), (2,4,6)) for i in VAR_POBED: if doska[i[0]]==doska[i[1]]==doska[i[2]]!=HODI: winner=doska[i[0]] return winner if HODI not in doska: return NICHYA return None def human_hod(doska,human): dostupnie=dostupnie_hodi(doska) hod=None while hod not in dostupnie: hod=hod_number(0,RAZMER_DOSKI) if hod not in dostupnie: print(‘Поле занято. Напиши другой номер: ‘) print(‘Супер!’) return hod def comp_hod(doska,comp,human): doska=doska[:] BEST_HODI=(4,0,2,6,8,1,3,5,7) print(‘Мой ход: ‘) for i in dostupnie_hodi(doska): doska[i]=comp if winner(doska)==comp: print(i) return i doska[i]=HODI for j in dostupnie_hodi(doska): doska[j]=human if winner(doska)==human: print(j) return j doska[j]=HODI for k in dostupnie_hodi(doska): print(k) return k def next_ochered(ochered): if ochered==X: return O else: return X def pozdrav_pobeditela(pobeditel,comp,human): if pobeditel!=NICHYA: print(‘Собрана линия ‘, pobeditel) else: print(NICHYA) if pobeditel==comp: print(‘Компьютер выиграл!’) elif pobeditel==human: print(‘Ты победил!’) elif pobeditel==NICHYA: print(NICHYA) def main(): instrukciya() comp,human=fishki() ochered=X doska=new_doska() pokaz_doski(doska) while not winner(doska): if ochered==human: hod=human_hod(doska,human) doska[hod]=human else: hod=comp_hod(doska,comp,human) doska[hod]=comp pokaz_doski(doska) ochered=next_ochered(ochered) pobeditel=winner(doska) pozdrav_pobeditela(pobeditel,comp,human) main() input(‘n Нажми Entr, чтобы выйти’)
Мой первый матч в крестики-нолики с компьютером выглядел так:
Привет! Это игра «Крестики-нолики». Чтобы сделать ход, введи номер клетки, куда хочешь поставить свой символ: 0 | 1 | 2 ——— 3 | 4 | 5 ——— 6 | 7 | 8 Вы хотите быть первым, кто сделает ход (играть крестиками)? да Окей, ты играешь крестиками! | | ——— | | ——— | | Делай свой ход — напиши номер поля (0-8): 4 Супер! | | ——— | X | ——— | | Мой ход: 0 0 | | ——— | X | ——— | | Делай свой ход — напиши номер поля (0-8): 5 Супер!
0 | | ——— | X | X ——— | | Мой ход: 3 0 | | ——— 0 | X | X ——— | | Делай свой ход — напиши номер поля (0-8): 2 Супер! 0 | | X ——— 0 | X | X ——— | | Мой ход: 6 0 | | X ——— 0 | X | X ——— 0 | | Собрана линия 0 Компьютер выиграл! Нажми Entr, чтобы выйти
Источник: skobki.com