0
Обложка: Игра «Быки и коровы», которая играет сама в себя на языке программирования Python

Игра «Быки и коровы», которая играет сама в себя на языке программирования Python

Всем доброго времени суток. Как-то раз на получении дополнительного образования преподаватель решил проверить знания студентов и предложил написать игру «Быки и коровы». Игру я написал довольно быстро и даже успел сделать так, чтобы игра играла сама в себя через встроенную библиотеку random.

Что такое «Быки и коровы»

Это логическая игра. В ходе неё игрок за несколько попыток должен. понять, что загадал соперник (это могут быть числа, символы, слова и так далее). После каждой попытки задумавший игрок выставляет «оценку»: сколько букв/цифр/символов угадано без совпадения с позициями (то есть показывает количество «коров») и сколько угадано точно, вместе с расположением (то есть показывает количество «быков»).

Идея

  1. Сгенерировать два разных числа.
  2. Найти количество «коров» и «быков» в каждом числе.
  3. С помощью цикла for пройтись по числу:
    3.1 Если цифра есть в списке индексов «быков», то не трогать эту цифру.
    3.2 Если цифра есть в списке индексов коров, то поменять рандомно эту цифру с другой «коров», если такие имеются
    3.3 Если цифра ни «корова» и не «бык», то рандомно сгенерировать новую цифру.
  4. Получить два одинаковых числа.

Реализация игры «Быки и коровы»

Создаём переменные и списки для дальнейшей работы с ними. Генерируем уникальные числа. Для генерации уникального числа пишем функцию, которая будет проверять переданное ему число.

def is_valid(number):
""" Проверка числа на уникальность. Все 4 цифры числа должны быть разные """
  try:
    # переводим наше число в список из символов.
    # сравниваем с множеством.
    # (в множестве нет повторяющихся символов)
    number_list = list(str(number))
    if len(set(number_list)) == 4:
      return True
    return False
  except:
    return False
# переменные
number_guess = 0  # загаданное число
number_computer = 0  # число, которое нужно отгадать
n = 0  # кол-во попыток
# списки
n_c = []
n_b = []
# генерируем число, которое нужно отгадать
while not is_valid(number_guess):
  number_guess = random.randint(1000, 9999)
# генерируем число от которого наша программа будет отталкиваться
while not is_valid(number_computer):
  number_computer = random.randint(1000, 9999))

Пишем функция для нахождения «коров» и «быков» в числе.

def check(number_guess, number_computer):
    """ Находим количество коров и быков в числе """

    # индексы коров и быков
    n_c, n_b = [], []

    try:
        # переводим наши числа в список из символов.
        number_guess_list = list(str(number_guess))
        number_computer_list = list(str(number_computer))

        # проходимся по числ
        for index in range(len(number_guess_list)):

            # если в разных числа в одинаковых
            # индексах цифры ровны,   то это бык
            if number_computer_list[index] == number_guess_list[index]:
                n_b.append(index)
            # если в числах есть одинаковые цифры, но на разных местах, то это корова
            elif number_guess_list[index] in number_computer_list:
                n_c.append(index)

        # возвращаем списки индексов коров и быков
        return n_c, n_b

    except:
        return n_c, n_b

Пишем функцию, которая будет пересобирать число из имеющихся данных.

def game(number_guess, n_c, n_b):
    """ Ф-я, пересоборки числа из имеющихся данных """

    # переводим наше число в список из символов
    number_guess_list = list(str(number_guess))

    # проходимся по списку number_guess_list
    for index in range(len(number_guess_list)):
        # если индекса цифры нет в списке индексов быков,
        # но есть в в списке коров
        if index not in n_b and index in n_c:
            # рандомным способом переставляем
            index_random = n_c[random.randint(0, len(n_c)-1)]
            number_guess_list[index], number_guess_list[index_random] = number_guess_list[index_random], number_guess_list[index]
        # если индекса цифры нет ни в одном из списков
        if index not in n_b and index not in n_c:
            number_guess_list[index] = str(random.randint(1, 9))
            while not is_valid(int(''.join(number_guess_list))):
                number_guess_list[index] = str(random.randint(1, 9))

    return int(''.join(number_guess_list))

Пишем главный цикл, который будет работать, пока не будет 4 «быка». В этом цикле пересоберем наше число и по новому числу получаем новый список индексов «коров» и «быков».

# главный цикл, работает, пока не будет 4 быка, то есть
# два числа не будут ровны между собой

# получаем списки индексов коров и быков
n_c, n_b = check(number_guess, number_computer)

while len(n_b) != 4:
    # пересоберем число из имеющихся данных
    number_guess = game(number_guess, n_c, n_b)

    # получаем списки индексов коров и быков
    n_c, n_b = check(number_guess, number_computer)
    n += 1
    print(f"Попытка: {n}; Число: {number_guess}; Число, которое нужно отгадать: {number_computer}")

print(number_guess)

КОНЕЦ

Надеюсь данная статья была вам полезна. Буду рад прочитать критику в комментариях.

код на github: https://github.com/alex-sandalov/cow