0

I have a program that scores a Scrabble game, and the main() function at the end of the program calls the functions needed depending on user input.

def main():
    option = home()
    if option.lower() == "a":
        add_score()
    elif option.lower() == "v":
        view_scores()
    elif option.lower() == "u":
        undo()
    elif option.lower() == "end":
        end_game()
    else:
        print("Please enter a valid option.")
        main()

At the end of the program, there is an if function to check if it is being used as an import.

if __name__ == "__main__":
    main()

There is also the function end_game(), which prints scores and is supposed to end the game.

def end_game():
    for name, score in players:
        print("Player %s has a score of %d" % (name, score))

The problem occurs when after the user types "end" and the end_game() function executes. After end game executes it runs into the if function checking for an import at the end of the program which triggers main again. Basically, the user gets stuck in a loop that could only be exited using CTRL+C. Would setting name to a different value such as "stop" be a valid way to bypass the if statement. I have not seen people changing name before in code, so I'm not sure if it would be a valid way to stoop the if statement from executing.

unkn0wn.dev
  • 235
  • 2
  • 8
  • 1
    First, I want to say that recursion is **not** the right approach to getting user input. Typically, one would use a `while True` loop and break upon valid input. Recursion like this uses unnecessary memory by keeping a stack of all the function calls until correct input is received. This has the potential to run out of memory and crash -- But with that aside, why is your `main` function being run twice? If you only call `main` in the `if __name__ == "__main__"` block, it should only run once. **How do you call `main` the first time?** I don't see it here. – SyntaxVoid Nov 20 '19 at 01:50
  • 1
    Adding imports at the end of a script is something that has to be done only if really necessary (circular dependencies, etc) and after considering other options; otherwise, there's probably some conceptual error somewhere in your code. Anyway, we need you to provide a [minimal, reproducible example](https://stackoverflow.com/help/minimal-reproducible-example) to better understand what's going on. – musicamante Nov 20 '19 at 01:52
  • @SyntaxVoidsupportsMonica What do you mean by recursion here? The if statement is used to execute certain functions based on user input. Can you explain what you are suggesting? – unkn0wn.dev Nov 20 '19 at 01:58
  • 1
    Recursion means that your `main` function calls itself. – kaya3 Nov 20 '19 at 01:58
  • @kaya3 What is suggested that I should do, if I use a while loop, I'll still need and else at the end of the nested if statement. Could someone give an example of what should be done? – unkn0wn.dev Nov 20 '19 at 02:01
  • 1
    See e.g. https://stackoverflow.com/questions/23294658/asking-the-user-for-input-until-they-give-a-valid-response – kaya3 Nov 20 '19 at 02:03
  • @kaya3 How could I share a piece of code with you without posting it as an answer? I think I get what you are saying about recursion but I wanted to check with you – unkn0wn.dev Nov 20 '19 at 02:12
  • If you solved the problem for yourself, then you can post it as an answer. Otherwise if it didn't solve the problem, then edit the question with the new code. – kaya3 Nov 20 '19 at 12:51
  • As you noticed, the recursion is in your `else` statement. Every time the user enters bad input and the code enters that block, a new "frame" has to be created (behind the scenes) to hold, essentially, the state of your program. Each frame costs memory so this is very inefficient. However, I still don't see how `main` is called the first time. If you say it's running once, and then it's running again when if hits the `if __name__` block, then you are calling it twice *somewhere*. – SyntaxVoid Nov 20 '19 at 16:10
  • If the edit doesn't significantly change your main question, you can edit the new code into your original post. – SyntaxVoid Nov 20 '19 at 16:11
  • @SyntaxVoidsupportsMonica `main` is called the first time in the if statement at the end of the code. – unkn0wn.dev Nov 21 '19 at 22:27
  • And then after `end_game` executes it goes through the if statement again and runs `main` again, which I do not want it to do. – unkn0wn.dev Nov 21 '19 at 22:28
  • That's not how python works (or any language, as far as I know). I've pieced together what you've provided here in a repl and you can see it here: https://repl.it/repls/PlaintiveIdolizedBackground (URL name is auto-generated). Enter "end" when prompted for a choice and you'll see the `end_game` function will execute and then the program will be over. Something, somewhere, is running `main` again and it isn't in the code you've provided. Figure out how your IDE's debugger works and use it to step through the code one line at a time. – SyntaxVoid Nov 21 '19 at 23:14
  • @SyntaxVoidsupportsMonica Very sorry for the ignorance on my part I finally figured out what was wrong. It was a simple overlooked mistake on my part. Thank you for all the help though and could you give some more insight on the recursion in `main` – unkn0wn.dev Nov 21 '19 at 23:22
  • Recursion is only suited for problems that are guaranteed to be reduced over time. In other words, when the input gets smaller. Getting user input is not one of those problems. A particularly dumb user of your program could enter wrong input many times. Each time, python dedicates a new piece of memory to the new function call. If the user enters 10 mistakes, then you are using 10 of those chunks of memory -- this is very wasteful and can even crash your entire program if the user enters enough mistakes. – SyntaxVoid Nov 21 '19 at 23:30
  • The solution is to put it inside a loop that will try to accept the user's input until valid input (however *you* define valid input) is retrieved. Once that happens, do what you need and then `break` out of the while loop. This uses only one "chunk" of memory as I mentioned in the previous comment. The memory usage will not grow over time when using a while loop approach. – SyntaxVoid Nov 21 '19 at 23:32
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/202834/discussion-between-pythonier500-and-syntaxvoid-supports-monica). – unkn0wn.dev Nov 21 '19 at 23:42
  • Unfortunately, the location I'm at blocks access to the stack chat urls. Going forward, I suggest you look up tutorials for validating user input. Try writing one yourself that doesn't use recursion and feel free to ask another question on stackoverflow if you are getting errors. good luck – SyntaxVoid Nov 21 '19 at 23:47

0 Answers0