Угадай число на Python: пишем первую игру
Угадай число на Python - классическая первая игра: программа загадывает случайное число, а игрок пытается его отгадать по подсказкам "больше" и "меньше". В статье разобран рабочий код по шагам, затем игра дополняется проверкой ввода, лимитом попыток, уровнями сложности и режимом, в котором угадывает компьютер.

Содержание статьи
Что нужно знать перед началом
Игра собирается из нескольких базовых конструкций языка, поэтому хорошо подходит для закрепления первых уроков. Понадобятся:
- функция
randint()из модуля random для выбора случайного числа; input()иint()для ввода и перевода строки в число;- условия
if,elif,elseдля сравнения; - цикл while, который повторяет попытки, пока число не угадано.
Правила простые. Программа загадывает целое число от 1 до 100. Игрок вводит вариант, а программа отвечает, больше или меньше загаданное число. Когда игрок попадает, программа сообщает количество потраченных попыток.
Базовая версия игры
Вот полный код минимальной версии. Он спрашивает имя, загадывает число и в цикле принимает варианты игрока.
import random
secret = random.randint(1, 100)
attempts = 0
print("Я загадал число от 1 до 100. Попробуй отгадать")
player = input("Как тебя зовут? ")
while True:
guess = int(input(f"{player}, введи число: "))
attempts += 1
if guess > secret:
print("Загаданное число меньше")
elif guess < secret:
print("Загаданное число больше")
else:
print(f"Угадал за {attempts} попыток!")
breakПример партии:
Я загадал число от 1 до 100. Попробуй отгадать
Как тебя зовут? Тимур
Тимур, введи число: 50
Загаданное число больше
Тимур, введи число: 75
Загаданное число меньше
Тимур, введи число: 62
Загаданное число больше
Тимур, введи число: 68
Угадал за 4 попыток!Разбор кода по строкам
random.randint(1, 100) возвращает случайное целое число, причем обе границы входят в диапазон, в отличие от range(). Переменная attempts считает попытки и увеличивается на 1 на каждом проходе цикла.
Цикл while True бесконечный, выход из него выполняет break в ветке else, когда число угадано. Подробно о том, как работают такие выходы, рассказано в статье про операторы break и continue. Можно написать и условие while guess != secret, но тогда переменную guess придется заранее создать со значением, которое точно не совпадет с загаданным.
Функция input() всегда возвращает строку, поэтому ее оборачивают в int(). Без этого сравнение строки с числом через > вызовет TypeError.
Защита от неправильного ввода
Если игрок случайно введет букву или пустую строку, int() выбросит ValueError и программа завершится с ошибкой. Исправить это помогает конструкция try/except, о ней подробно в материале про обработку исключений. Заодно проверим, что число попадает в допустимый диапазон.
def read_number(prompt, low, high):
while True:
raw = input(prompt).strip()
try:
value = int(raw)
except ValueError:
print("Нужно ввести целое число")
continue
if low <= value <= high:
return value
print(f"Число должно быть от {low} до {high}")Функция повторяет запрос, пока не получит корректное значение, и не увеличивает счетчик попыток за ошибочный ввод. Вынос проверки в отдельную функцию делает основной цикл короче и понятнее.
Лимит попыток и уровни сложности
Игра становится интереснее, когда количество попыток ограничено. Диапазон и лимит удобно хранить в словаре, а сам игровой процесс оформить функцией, которая возвращает True при победе. В цикле ниже используется конструкция while ... else: блок else выполняется, только если цикл закончился без break.
import random
LEVELS = {
"1": ("легкий", 50, 10),
"2": ("средний", 100, 7),
"3": ("сложный", 1000, 10),
}
def play(high, max_attempts):
secret = random.randint(1, high)
attempts = 0
while attempts < max_attempts:
guess = read_number(f"Попытка {attempts + 1}: ", 1, high)
attempts += 1
if guess == secret:
print(f"Победа за {attempts} попыток")
break
print("Больше" if guess < secret else "Меньше")
else:
print(f"Попытки закончились, было загадано {secret}")
return False
return TrueЛимиты выбраны не случайно. При разумной стратегии число от 1 до 100 всегда угадывается не более чем за 7 попыток, а от 1 до 1000 не более чем за 10. Поэтому даже на сложном уровне выигрыш возможен, если думать, а не перебирать числа подряд.
Повтор партии
Чтобы не запускать программу заново, основной код оборачивают во внешний цикл с вопросом о новой игре.
while True:
name, high, limit = LEVELS.get(input("Уровень 1, 2 или 3: "), LEVELS["2"])
print(f"Уровень {name}: число от 1 до {high}, попыток {limit}")
play(high, limit)
if input("Сыграть еще? (д/н) ").strip().lower() != "д":
breakКомпьютер угадывает число игрока
Обратный вариант игры: число загадывает человек, а программа отгадывает. Оптимальная стратегия называется бинарным поиском. Компьютер каждый раз называет середину оставшегося диапазона и по ответу отбрасывает половину вариантов.
low, high = 1, 100
tries = 0
print("Загадай число от 1 до 100 и отвечай: б - больше, м - меньше, = - угадал")
while low <= high:
middle = (low + high) // 2
tries += 1
answer = input(f"Это {middle}? ").strip()
if answer == "=":
print(f"Угадал за {tries} попыток")
break
elif answer == "б":
low = middle + 1
elif answer == "м":
high = middle - 1
else:
print("Кажется, в ответах была ошибка")Сто вариантов делятся пополам: 100, 50, 25, 13, 7, 4, 2, 1. На это уходит не больше 7 шагов, потому что 2 в седьмой степени равно 128, а это больше 100. Ту же стратегию полезно применять и человеку в основной версии игры.
Сравнение версий игры
В таблице собраны варианты, которые получились в статье, и конструкции Python, которые в них отрабатываются.
| Версия | Что добавлено | Новые конструкции |
|---|---|---|
| Базовая | Подсказки и счетчик попыток | randint, while True, break, f-строки |
| С проверкой ввода | Программа не падает на буквах | try/except, функция с return |
| С уровнями | Лимит попыток, выбор сложности, повтор | словарь, while ... else |
| Угадывает компьютер | Бинарный поиск | целочисленное деление // |
Для дальнейшей практики можно сохранять рекорд в файл, вести таблицу лучших результатов для нескольких игроков или сделать окно на Tkinter с полем ввода и кнопкой. Если функции пока вызывают вопросы, повторите урок про функции Python.
Частые вопросы
Ответы на вопросы, которые возникают при написании этой игры.
Почему программа падает с ошибкой ValueError?
Игрок ввел не число, и int() не смог преобразовать строку. Оберните преобразование в try/except ValueError, как в функции read_number().
Как сделать, чтобы при каждом запуске было одно и то же число?
Для отладки вызовите random.seed(42) перед randint(). С одинаковым зерном генератор выдает одну и ту же последовательность чисел.
Входит ли 100 в диапазон randint(1, 100)?
Да, randint(a, b) включает обе границы. А вот randrange(1, 100) вернет число не больше 99.
За сколько попыток можно гарантированно угадать число от 1 до 100?
За 7, если каждый раз называть середину оставшегося диапазона. Для диапазона до 1000 хватит 10 попыток.