Обратная связь проверки диапазона в Python

Для школьного задания мне нужно придумать дешифровщик, который следует определенным правилам.

  • Код 4 цифры. (не случайно)
  • Я не могу использовать функции/списки/массивы. Только петли.
  • Внедрите стоп-код. (9999)
  • На каждом шагу пользователь должен получать обратную связь.
  • Обратная связь включает, но не ограничивается;
    • На какой очереди проигрыватель. (Ограничение 10)
    • Если номер используется более одного раза.
    • Если используется число вне диапазона (0,8) и/или символ.
    • Обратная связь (подсказка), куда на самом деле должен быть помещен использованный номер, если он был использован на ходу.

Итак, я сварил что-то вроде того, что делает все вышеперечисленное. Тем не менее, остаются 2 основные проблемы, которые я просто не могу решить.

  1. Обратная связь (также известная как подсказка) распечатывается несколько раз. Если бы пользователь использовал, например, «1111», программа напечатала бы 4 раза больше, чем число 1, которое должно использоваться в местоположении X. Как я могу ограничить свой вывод на печать только один раз или, что еще лучше, только один раз за 10 ходов?

  2. Независимо от того, какое число я использую в пределах или вне диапазона (0,8), программа всегда дает мне обратную связь о том, что я использовал что-то, чего не должен был. Что было бы лучшим способом для меня решить эту проблему?

Я не прошу никого выполнять мое задание, но просто несколько советов или приемов, которые помогут мне двигаться дальше, были бы очень признательны! Как вы можете видеть на первый взгляд, я полный новичок. Поэтому прошу прощения, если что-то выглядит сумбурно.

code= "1436"     #gezochte code
beurt = 0        #beurten voor user
stop = "9999"    #stopcode voor user
gok = ''         #user input
num_range = range(0,8)
print("""Welkom, je mag 10 keer raden naar de juiste code van 4 nummers.
De nummers mogen niet opeenvolgend zijn.
De nummers gaan van 1 tem 7.
Je kan altijd vroegtijdig stoppen door 9999 in te geven.""")
print()
while gok != code:
    gok = (input("Geef een 4 cijferige code in: "))
    if gok == stop:
        print()
        print("U heeft gekozen om te stoppen.")
        break
    if gok == code:
        print()
        print("Super! Je hebt de code gekraakt!")
        break
    if gok != (num_range):
        print()
        print("Uw code zit niet binnen 1 tem 7 en/of is geen nummer.")   
    if gok != code:
        beurt +=1
        print()
        print("Niet juist. Je zit aan beurt:",beurt)
    if beurt == 10:
        print()
        print("Uw beurten zijn opgebruikt.")
        break
    for i in num_range:
        if i == i\*2:
            print()
            print("Elk nummer kan maar 1 keer gebruikt worden.")
            print()
    else:
        for i in gok:
            if i == "1":
                print("Nummer 1 staat op de eerste plaats.")
                continue
            elif i == "4":
                print("Nummer 4 staat op de tweede plaats.")
                continue
            elif i == "3":
                print("Nummer 3 staat op de derde plaats.")
                continue
            elif i == "6":
                print("Nummer 6 staat op de vierde plaats.")
                continue
i\*2 недопустимый синтаксис, это ошибка копирования?
Barmar 08.12.2022 22:28
i == i*2 будет верным только тогда, когда i == 0.
Barmar 08.12.2022 22:28
gok != (num_range) всегда будет правдой. gok — строка, num_range — диапазон. Что вы там пытаетесь сделать?
Barmar 08.12.2022 22:30

Привет, Бармар, да. В IDE это было написано как i == i*2 Теперь, когда вы сказали, что gok != (num_range) всегда будет True, я так же сбит с толку, как я думал, что я что-то понял. Я пытался реализовать способ проверки количества гоков в диапазоне. :С

Duckbug 08.12.2022 22:48

Если бы gok было целым числом, вы могли бы использовать if gok not in num_range:

Barmar 08.12.2022 22:50
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
5
62
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Итак, для первой проблемы я смотрю на этот фрагмент кода:

for i in gok:
    if i == "1":
        print("Nummer 1 staat op de eerste plaats.")
        continue

Что здесь происходит, так это то, что для каждого числа в gok, если число соответствует "1", будет напечатано это утверждение. Однако вы также хотите проверить, действительно ли это число находится на первой позиции. Вы можете сделать это, отслеживая индекс числа в цикле for:

for index, i in enumerate(gok):
    if index == 0 and i == "1":
        print("Nummer 1 staat op de eerste plaats.")
        continue

С enumerate вы отслеживаете как индекс элемента в gok, так и сам элемент. Повторите это для каждого оператора if, и первая проблема будет устранена.


Для второй проблемы вы хотели бы проверить, находится ли ваш ввод в диапазоне 0-8. В настоящее время вы делаете это:

if gok != (num_range):
    print()
    print("Uw code zit niet binnen 1 tem 7 en/of is geen nummer.")  

Вместо этого вы можете проверить, находится ли целое число в диапазоне от 0 до 8. Это делается с помощью:

for i in gok:
    if not 0 <= int(i) <= 8:
        print()
        print("Uw code zit niet binnen 1 tem 7 en/of is geen nummer.") 

Последняя петля for не имеет смысла. num_range — это жестко закодированный range(0, 8), а не что-то связанное с пользовательским вводом.

Barmar 08.12.2022 22:32

Виноват! Неправильно это понял. Я отредактирую это!

Lexpj 08.12.2022 22:35

Большое спасибо, Lexpj! Я не знал о перечислении, так весело изучать новые трюки! Собираюсь проверить как можно скорее, куда все это меня привело.

Duckbug 08.12.2022 22:43

Чтобы проверить правильность ввода, вы можете использовать это:

    if len(gok) != 4:
        print()
        print("Number is not 4 digits")
        break
    all_digits = True
    for digit in gok:
        if not '0' <= digit < '8':
            all_digits = False
            break
    if not all_digits:
        print()
        print("Digits not in range(0, 8)")
        break

Спасибо, Бармар, к сожалению, мне не разрешено работать. Я должен прибить его только петлями. Но я сохраняю ваше предложение для будущих проектов.

Duckbug 08.12.2022 22:51

Я обновил его, чтобы использовать циклы.

Barmar 08.12.2022 22:56
Ответ принят как подходящий

В таких случаях, когда задача проста, а код в целом выглядит беспорядочно, я бы предложил вам переписать его с нуля.
Но в это время разделите свою задачу на маленькие кусочки.
И используйте свой предыдущий опыт, чтобы писать более качественный и структурированный код.

Итак, прежде всего - повторим нашу задачу.
Это важный шаг, поэтому не пропускайте его (прочитайте еще раз, даже если вам кажется, что вы его поняли).

  1. Код 4 цифры. (не случайно)
  2. Я не могу использовать функции/списки/массивы. Только петли.
  3. Внедрите стоп-код. (9999)
  4. На каждом шагу пользователь должен получать обратную связь. Обратная связь включает, но не ограничивается;
    • На какой очереди проигрыватель. (Ограничение 10)
    • Если номер используется более одного раза.
    • Если используется число вне диапазона (0,8) и/или символ.
    • Обратная связь (подсказка), где на самом деле следует разместить использованный номер если бы он был использован на ходу.

Во-вторых, давайте думать об этом как о плане (как сказал Датч из RDR2: «Не волнуйтесь, у меня есть план, просто поверьте»). Для того, чтобы записать план, вы должны задать себе три простых вопроса:

  • Какой пользовательский ввод будет запрашивать программа?
  • Какой вывод это должно дать?
  • Как это будет выглядеть (интерфейс, подсказки, общее поведение и т. д.)

И когда вы получили ответы, вы можете записать план того, как будет работать ваш код.
Скажем:

  1. Код будет иметь некоторые переменные конфигурации (искомый код, код остановки, текущая попытка и т.д.)
  2. Код должен сначала приветствовать пользователя, объяснить правила, а затем запросить ввод.
  3. Во всем коде будет только ОДИН вход, и это - предположение пользователя.
  4. После каждого ввода код должен проверять, верно ли предположение пользователя. Если нет, продолжаем игру. Если да, то игра окончено, потому что пользователь ВЫИГРАЛ игру.

    (этот и все последующие шаги будет использоваться только в том случае, если пользователь ошибся)
  5. Если пользователь превышает свои попытки, игра также ОКОНЧАЕТСЯ.
  6. Затем мы должны дать обратную связь, чтобы помочь пользователю угадать искомый код.
    Это включает в себя:
    • Текущая попытка
    • Если номер используется более одного раза
    • Если какое-то число в пользовательском вводе выходит за пределы заданного диапазона
    • Если искомый код действительно содержит одно из используемых чисел в пользовательском вводе, мы должны дать об этом подсказку (вместе с соответствующим номер позиции в искомом коде)

Хорошо, теперь у нас есть текстовое представление нашего кода (сценарий, если хотите).
И только сейчас мы можем записать решение, используя реальный код Python.
Вы можете попробовать это самостоятельно на этом этапе, а затем вернуться, когда вам удастся сравнить результаты.

Прежде всего, давайте создадим пустой файл Python и определим некоторые переменные.

# CODE BREAKER v0.1 BETA

allowed_range = (0, 8)  # minimum and maximum allowed numbers that can be used within the code
searched_code = "1436"  # the code user will need to guess
stop_code = "9999"  # the stop code, if user enter it - game ends
max_attempts = 10  # how much attempts user will have

user_input = None  # this will contain current user guess
current_attempt = 0  # number of current attempt of a user

Далее по нашему плану мы должны поприветствовать пользователя и объяснить правила игры.

print("Welcome to the CODE BREAKER game!\n\n"
+"Rules are simple:\n"+
f"- The code you need to crack contains {len(searched_code)} numbers\n"
+f"- You have only {max_attempts} attempts\n"
+"- Numbers cannot be consecutive\n"
+f"- Numbers must fit the given range from {allowed_range[0]} to {allowed_range[1]}\n"
+f"\nYou can always stop the game by typing {stop_code}"
+"\n\n")

Наш третий и четвертый шаг аналогичны — запрашиваем ввод у пользователя и проверяем, правильный он или нет.

while True:
    # request input
    print(f"Attempts left - {max_attempts-current_attempt}")
    user_input = input(f"What's your guess?: ").strip()

    # compare guess with the actual searched code
    if user_input == searched_code:
        print("FAN-TA-STIC!!! You won the game. Awesome!!!")
        break
    elif user_input == stop_code:
        print("You quit the game.")
        break
    else:
        print("Wrong ...\n")

    # increment attempts
    current_attempt += 1

    # if attempts exceeded, quite the game
    if current_attempt > max_attempts:
        print("You have exceeded your attempts. Sorry, no luck this time.")
        break

Что это был за пятый шаг в нашем плане? ...
Успешно справился! Мы должны дать пользователю обратную связь, если он не угадал код.

Проверьте, находятся ли введенные пользователем числа в требуемом диапазоне:

for num in user_input:
    if int(num) < allowed_range[0] or int(num) > allowed_range[1]:
        print(f"HINT: The number {num} you entered is not within the required range!")

Проверьте, являются ли введенные пользователем числа последовательными:

prev_num = None
for num in user_input:
    if prev_num is None:
        prev_num = int(num)
        continue

    if prev_num+1 == int(num):
        print(f"HINT: The numbers {prev_num}{num} you entered is consecutive, but it's forbidden by the rules of the game!")
        break

Проверьте, используются ли введенные пользователем числа только один раз:

i_pos = 1
for i in user_input:
    j_pos = 1
    for j in user_input[i_pos:]:
        if i == j and i_pos != j_pos:  # skip, if it's the same position
            print(f"HINT: The number {i} is used more than once! Which is forbidden by the rules of the game.")
            break
        j_pos += 1  # track the sub loop number position
    if i == j:
        break # quite the upper loop

    i_pos += 1  # track the main loop number position

И, наконец, дайте подсказку, если некоторые из введенных пользователем чисел верны (подсказка местоположения):

i_pos = 1
for i in searched_code:
    for j in user_input:
        if j == i:
            print(f"HINT: The number {j} you have entered is located at position {i_pos} in the searched code.")
            break # break & check other positions

    i_pos += 1  # offset of a number in searched_code variable

И это все! Наш план выполнен. Каждый шаг написан в виде кода.
И все работает, как и планировалось!
Как и планировал Датч... :D

Кстати, вот полный финальный код (если он вам нужен): https://pastebin.com/hayVjJTm

p.s. Я попытался написать весь код как можно проще (как, наверное, сделал бы самый новичок в Python).

Авраам! Это невероятно! Большое вам спасибо за то, что нашли время, чтобы записать все это. Я смотрел на экран и размышлял в течение 2 недель, чтобы получить простой прототип, и вот вы случайно выскакиваете все это на суперскорости. xD Помимо всех советов по коду, мне очень понравились советы о том, как подходить к данной задаче!

Duckbug 09.12.2022 00:01

@Duckbug Нет смысла записывать код, не понимая, что вам на самом деле нужно сделать в первую очередь. Насчет подхода, он тоже довольно простой. Человеческий мозг просто не может справиться со слишком большими задачами, поэтому разделение его на множество мелких подзадач обычно работает как шарм. Надеюсь, вы продолжите свой путь в программировании, как видите, это очень увлекательно =)

Abraham Tugalov 09.12.2022 00:06

Другие вопросы по теме