Range check feedback in Python

Question:

For an assignment for school, I’ve got to come up with a code breaker that follows certain rules.

  • Code is 4 numbers. (not random)
  • I can’t use functions/lists/arrays. Only loops.
  • Implement a stop code. (9999)
  • Every step of the way the user needs to get feedback.
  • Feedback includes, but not limited to;
    • What turn the player is on. (Limit of 10)
    • If a number is used more than once.
    • If a number is used outside of the range(0,8) and/or a symbol.
    • Feedback(hint) where a used number actually should be placed if it had been used on a turn.

So, I’ve brewed something up that kinda does all of the above.
However, 2 main issues remain that I just can’t seem to tackle.

  1. Feedback, (aka the hint), prints out multiple times. If the user used for example ‘1111’ the program would print 4 times that number 1 should be used at location X. How can I limit my print output to only once, or even even better, to only once during the 10 turns?

  2. No matter what number I use within or not within the range(0,8), the program always gives me feedback that I’ve used something that I shouldn’t. What would be the best way for me to solve this?

I’m not asking anyone to make my assignment, but just some tips or tricks to keep me going would be enormously appreciated! As you may see at first glance, I’m a complete beginner. So I apologise if things look messy.

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
Asked By: Duckbug

||

Answers:

So for the first problem, I am taking a look at this piece of code:

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

What happens here, is that, for every number in gok, if the number matches "1", it will print out that statement. However, you want to also check whether that number is actually in the first position. You can do that by keeping track of the index of the number in your for loop:

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

With enumerate, you keep track of both the index of the item in gok as well as the item itself. Repeat that for every if statement, and the first problem will be fixed.


For the second problem, you would want to check if your input is in the range 0-8. Currently you are doing that by:

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

What you could do instead, is test whether the number as integer is in between 0 and 8. This is done by:

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.") 
Answered By: Lexpj

To check that the input is valid, you can use this:

    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
Answered By: Barmar

In such cases, when the task is easy and the overall code looks messy, I would suggest you to rewrite it from scratch.
But in this time, split your task into small pieces.
And use your previous experience to write better and more structured code.

So, first of all – let’s repeat our task.
This is important step, so don’t skip it (read it again, even if you think you get it).

  1. Code is 4 numbers. (not random)
  2. I can’t use functions/lists/arrays. Only loops.
  3. Implement a stop code. (9999)
  4. Every step of the way the user needs to get feedback. Feedback includes, but not limited to;
    • What turn the player is on. (Limit of 10)
    • If a number is used more than once.
    • If a number is used outside of the range(0,8) and/or a symbol.
    • Feedback (hint) where a used number actually should be placed
      if it had been used on a turn.

Secondly, let’s think of it as a plan (as Dutch from RDR2 said "Don’t worry, I have a plan, just have a little faith").
In order to write down the plan, you should ask yourself three simple questions:

  • What user input will program request?
  • What output it should give?
  • How it going to look like (interface, hints, overall behavior etc)

And when you got the answers, you can write down the plan of how your code will work like.
Let’s say:

  1. The code will have some configuration variables (searched code, stop code, current attempt etc)
  2. The code must first greet the user, explain the rules and then ask for an input.
  3. There will be only ONE single input throughout the code, and that is – user guess.
  4. After every input, the code must check whether the user guess is right or not. If it’s not, we continue the game. If it is, the game is
    over because user WIN the game.

    (this and all next steps
    will only be used, if user guess is wrong)

  5. If the user exceeds his attempts, the game is also OVER.
  6. Next we should give some feedback to help user guess the searched code.
    This includes:

    • Current attempt
    • If a number is used more than once
    • If some number in user input is out of given range
    • If a searched code actually contains one of the used numbers in user input, we must give a hint about it (along with the according
      number position within the searched code)

Ok, now we have a textual representation of our code (scenario, if you want to).
And only now, we are able to write down the solution using actual Python code.
You can try it by your own at this point, and then come back when you succeed to compare results.

First of all, let’s create an empty python file and define some variables.

# 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

Next, according to our plan, we have to greet the user and explain the rules of the game.

print("Welcome to the CODE BREAKER game!nn"
+"Rules are simple:n"+
f"- The code you need to crack contains {len(searched_code)} numbersn"
+f"- You have only {max_attempts} attemptsn"
+"- Numbers cannot be consecutiven"
+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}"
+"nn")

Our third and fourth step is similar, – request an input from the user and check whether it’s correct or not.

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

What was that step five in our plan? …
Nailed it! We have to give a user some feedback, if he did not guessed the code.

Check if a user input numbers is within the required range:

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!")

Check if a user input numbers is consecutive:

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

Check if a user input numbers are only used once:

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

And finally, give a hint if some of a user input numbers is correct (location hint):

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

And that’s all! Our plan is done. Every step is written as a code.
And everything seems to work just as planned!
Just as Dutch planned … 😀

By the way, here is the full final code (if you need it): https://pastebin.com/hayVjJTm

p.s. I’ve tried to write down the whole code as simple as I can (like the very beginner in Python would do it, I guess).

Answered By: Abraham Tugalov
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.