Сегодня перед нами стоит задача написать игру крестики-нолики на питоне. Напомним, что крестики-нолики это логическая игра для двух игроков на поле 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 <= 9: if (str(board[player_answer-1]) not in "XO"): board[player_answer-1] = player_token valid = True else: print "Эта клеточка уже занята" else: print "Некорректный ввод. Введите число от 1 до 9 чтобы походить."
Как вы видите, функция 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