Блог учителя Информатики

Комментарии отключены

Пишем игру «15 спичек» на python

Попробуем написать игру, известную как «15 спичек», на языке python. Напомним правила этой игры. У нас есть 15 спичек. Каждый игрок по очереди берет за ход по одной, две или три спички. Выигрывает тот, кто забирает оставшиеся спички.

Для начала определим логику игры. У нас будет игрок и компьютер, наш ai, который будет делать ходы. Вынесем действия игрока и ai в отдельные функции, для удобства организации игрового цикла. Каждая функция будет принимать текущее значение спичек и возвращать количество спичек, которое нужно убрать за ход.
Но начнем мы написание с функции start() в которой укажем название игры и кратко напомним о правилах игры.

def start():
    print(f'################## Игра "15 спичек" ##################')
    print(f'Всего в куче 15 спичек')
    print(f'Каждый игрок по очереди берет от 1 до 3х спичек')
    print(f'Выигрывает тот, кто заберет последние спички из кучи!')
    print(f'######################################################\n')

Эта функция будет выводить текст на экран используя оператор вывода print().
Дальше нам понадобится еще одна служебная функция, которая будет определять за кем будет первый ход в игре. Выделим три варианта: первым ходит игрок, первым ходит компьютер или случайный выбор. Для этого пользователю нужно ввести 0, 1 или 2.
Сначала выведем информацию о возможных вариантах. Затем организуем бесконечный цикл while для возможного повтора ввода если пользователь при выборе сделает ошибку.
В переменную n поместим ввод от пользователя. Напомним, что если пользователь введет 0, то будет первым ходить игрок, если 1 то первым будет ходить компьютер и 2, то очередность ходов будет определяться случайным образом.
Сразу после ввода проверим используя метод .isdidgit() ввел ли пользователь число. И если это так, то используя функцию int() переведем введенное значение из строки в число. Теперь когда у нас есть число, проверим его на правильный вариант ввода. Нам нужно чтобы пользователь ввел 0, 1 или 2. И если это не так, то выведем соответствующее сообщение об ошибке. Иначе проверим, не ввел ли пользователь число 2. Это означает, что нам надо с помощью генератора случайных чисел выбрать очередность ходов. Полученное случайное значение перезапишем в переменную n. После этого проинформируем игрока о сделанном выборе и прервем цикл оператором break. В самом конце функции вернем с помощью return значение переменной n. Это нам понадобится для организации главного игрового цикла.

def rnd_turn():
    print(f'Выбор очередности ходов: ')
    print(f'Введите 0, если ходить первым будет игрок')
    print(f'Введите 1, если ходить первым будет компьютер')
    print(f'Введите 2, чтобы выбрать очередность ходов случайным образом')
    while True:
        n = input('> ')
        if n.isdigit():
            n = int(n)
            if n > 2 or n < 0:
                print(f'Введите число 0, 1 или 2')
            else:
                if n == 2:
                    n = random.randint(0, 1)
                if n == 0:
                    print(f'Первым будет ходить игрок!')
                else:
                    print(f'Первым будет ходить компьютер!')
                break
        else:
            print(f'Вы ввели недопустимый символ. Введите число 0, 1 или 2')
    return n

Теперь напишем функцию, которая будет отвечать за ход игрока. В нее передадим количество спичек matches которое осталось после предыдущего хода. Дополнительные уведомления о количестве оставшихся спичек, чтобы игрок смог принимать решения, мы реализуем в основной программе.
Возьмем переменную n, в которой мы будем хранить количество спичек, которое возьмет игрок, и присвоим ей любое недопустимое значение. Это нам нужно для организации цикла ввода данных пользователем, для того, чтобы перезапускать его при некорректном вводе. Для этого зададим условие цикла while, что когда значение n или больше 3, или меньше 1. Затем в переменную n запишем результат ввода данных используя оператор input(). Проверим его так же методом .isdidgit() на то, что ввели только числа, и если это не так, через конструкцию else выведем соответствующее уведомление и переприсвоим переменную n некорректным числовым значением чтобы перезапустить цикл. Если же мы ввели число, то проверим его на корректность ввода условием, где n должен быть от 1 до 3. И если это не так, то выведем сообщение об ошибке и так же перезапустим цикл.

def turn_player(matches):
    n = 4
    while n > 3 or n < 1:
        n = input('Сколько вы возьмете спичек? ')
        if n.isdigit():
            n = int(n)
            if n > 3 or n < 1:
                print(f'Вы вязли недопустимое количества спичек! Возьмите от 1 до 3х')
            # проверка на остаток
            if n > matches:
                print(f'Вы взяли больше чем осталось спичек!')
                n = 4
        else:
            print(f'Вы ввели недопустимые символы. Введите число от 1 до 3х')
            n = 4
    return n

В случае ввода пользователем корректных данных вернем их с помощью return из нашей функции.
Теперь опишем функцию для хода компьютера. Для правильной реализации алгоритма хода компьютера нам необходимо знать количество оставшихся спичек, поэтому передадим их в функцию используя переменную matches.
Теперь разберем алгоритм ходов компьютера. Необходимо, чтобы каждый ход, который делает компьютер приводил к выигрышу, а для этого нам надо определить оптимальную стратегию. Очевидно то, что для того, чтобы побеждать, нам необходимо чтобы после нашего хода оставалось количество спичек кратное числу 4. Разберем этот случай более подробно. Представим что у нас осталось 4 спички. Вы можете взять 1, 2 или 3. Беря любое их количество противнику остается такое же их количество, которое он за ход и может забрать, тем самым обеспечив себе победу.
Для этого найдем остаток от деления на 4 от общего числа спичек и запишем их в переменную n. Теперь надо рассмотреть вариант, когда у нас уже количество спичек кратное четырем. При нахождения остатка от деления на 4 для такого числа результат будет 0. Но 0 спичек мы не можем взять по условию игры. По этому мы с помощью генератора случайных чисел получим любое допустимое число от 1 до 3 включительно. Его и вернем с помощью return в основную программу.

def turn_ai(matches):
    n = matches % 4
    if n == 0:
        n = random.randint(1, 3)
    return n

После того как мы описали функции для ходов игрока и компьютера напишем основной игровой цикл. Для начала зададим две переменные: matches = 15 — это общее количество спичек на начало игры и count = 1 счетчик ходов.
Так же в самом начале вызовем функции start() и rnd_turn(), значение последней присвоим переменной turn. Эта переменная будет определять чей сейчас ход, игрока или компьютера. Как мы помним, если функция rnd_turn() вернет 0, то первым будет ходить игрок, а если 1, то компьютер. Соответственно в цикле мы будем проверять эту переменную на четность или нечетность. При четном значении turn ходит игрок, а при нечетном компьютер. Внутри цикла переменные turn и count будем увеличивать на единицу.
Сделаем бесконечный цикл while. Выведем сообщение с номером текущего хода. Затем с помощью условия turn % 2 определим очередность ходов. Внутри условия укажем чей сейчас ход и оставшееся на этот момент количество спичек. Затем вызовем ту функцию, которая отвечает хода игрока или компьютера. Результат работы этих функций запишем в переменную n. После условия отнимем от общего количества спичек в переменной matches количество спичек за ход.
После вычислений необходимо проверить результат на победу. Если значение matches становится равно нулю, то завершаем цикл командой break, перед этим выводя сообщение о победе игрока или компьютерного ai.

matches = 15
count = 1
start()
turn = rnd_turn()
while True:
    print(f'\n******** Ход номер: {count} ********')
    if turn % 2 == 0:
        print(f'Ход игрока! Всего спичек: {matches}')
        n = turn_player()
        print(f'Игрок взял спичек: {n}')
    elif turn % 2 == 1:
        print(f'Ход компьютера! Всего спичек: {matches}')
        n = turn_ai(matches)
        print(f'Компьютер взял спичек: {n}')
    matches -= n
    if matches == 0:
        if turn % 2 == 0:
            print(f'Победил игрок!')
        else:
            print(f'Победил компьютер!')
        break
    turn += 1
    count += 1

Также не забудем в самом верху программы подключить модуль random для работы генератора случайных чисел.

Ниже вы можете или попробовать поиграть в получившуюся у нас игру или посмотреть ее код полностью, нажав на соответствующую кнопку.

Играть OnLine Посмотреть код программы
Поделиться:
Вам также может понравится
Решение олимпиадных задач по информатике: Наименьший остаток
Решение олимпиадных задач по информатике: Последовательность
Решение олимпиадных задач по информатике: От перестановки чисел что-то меняется
Делаем Черепашку в виде снежинки