Towers of Hanoi Loop

I’ve been having an issue with this project where it appears I am stuck in a loop where the code prints out the else statement ("Invalid Move. Try Again) even when I intentionally put in inputs that meet the criteria of the if or elif statements that proceed it.

From what I can see, my code is identical to the solution video. Am I missing something???

https://www.codecademy.com/paths/computer-science/tracks/linear-data-structures/modules/cspath-stacks/projects/towers-of-hanoi

from stack import Stack

print("\nLet's play Towers of Hanoi!!")

#Create the Stacks
stacks = []

left_stack = Stack('Left')
middle_stack = Stack('Middle')
right_stack = Stack('Right')
stacks += [left_stack, middle_stack, right_stack]


#Set up the Game

num_disks = int(input('\nHow many disks do you want to play with?\n'))

while num_disks < 3:
  num_disks = int(input("Enter a number greater than or equal to 3\n"))

for i in range(num_disks, 0, -1):
  left_stack.push(i)


num_optimal_moves = (2 ** num_disks) - 1

print("\nThe fastest you can solve this game is in {0} moves".format(num_optimal_moves))
  
#Get User Input
def get_input():
  choices = [stack.get_name()[0] for stack in stacks]
  while True:
    for i in range(len(stacks)):
      name = stacks[i].get_name()
      letter = choices[i]
      print('Enter {0} for {1}'.format(letter, name))
      
    user_input = input('')
    
    if user_input in choices:
      for i in range(len(stacks)):
        return stacks[i]
      
#Play the Game

num_user_moves = 0

while right_stack.get_size() != num_disks:
  print("\n\n\n...Current Stacks...")
  for stack in stacks:
    stack.print_items()
    
  while True:
    
    print("\nWhich stack do you want to move from?\n")
    from_stack = get_input()
    
    
    print("\nWhich stack do you want to move to?\n")
    to_stack = get_input()
    
    if from_stack.get_size() == 0:
      print('\n\nInvalid Move. Try Again')
    elif to_stack.get_size() == 0 or from_stack.peek() < to_stack.peek():
      disk = from_stack.pop()
      to_stack.push(disk)
      num_user_moves += 1
      break
    else:
      print('\n\nInvalid Move. Try Again')
      
      
print("\n\nYou completed the game in {0} moves, and the optimal number of moves is {1}".format(num_user_moves, num_optimal_moves))

I have the exact same issue and still haven’t solved it yet. the code is apparently skipping the elif statement and going to the else statement.

There could be multiple reasons.

  1. The to_stack is not empty
  2. the elif statement logic is just wrong.
  3. The statement that moves the stacks are wrong, such that they don’t actually do anything

I removed all of the conditional statements and simplified the code to move the stacks regardless of the size. after which it prints out the stacks are the same as the starting point. It seems that the code to move stacks are not working at all.

#Play the Game

num_user_moves = 0

while right_stack.get_size() != num_disks:
  
  print("\n\n\n...Current Stacks...")
  for stack in stacks:
    stack.print_items()
  
  while True:
  
    print("\nWhich stack do you want to move from?\n")
    from_stack = get_input()
    print("\nWhich stack do you want to move to?\n")
    to_stack = get_input()
    
    
    disk = from_stack.pop()
    to_stack.push(disk)
    num_user_moves += 1
    break

I personally think the get_input method is messed up somewhere, such that it’s not actually taking the inputs. going to have to poke around some more.

Ok. I found the solution to break the loop.

The problem was indeed in the get_input method

the last for loop is missing an if statement in the video solution that equations the

the working code is this:

if user_input in choices:
      for i in range(len(stacks)):
        if user_input == choices[i]:
        	return stacks[i]

The get_input method wasn’t actually returning a stack.
They really should update that solutions video, but I guess it creates discussion in the forums…

Thanks!

I’m not sure how he was able to get his to work in the solution video, but this worked for me.

Without adding

if user_input == choices[i]:

would this get_input() method have been returning multiple items? One for each object in the range, thus not meeting the conditions of the if and elif statement that come in the while loops and ultimately printing out the else statement each time?

yep, it would return stack[i] for the size of that stack. So I think it would actually return the last stack. So when you type L, you would actually return R. And it would return R everytime.

This is an excellent pick-up, @design2539198751 & @system9706114496 !

Upon receiving an input and verifying that it is in the list, choices (which is ['L', 'M', 'R']), the next lines of code executed are:

      for i in range(len(stacks)):       
        	return stacks[i]

Since the first i will always be zero, and since return halts execution of the function, stacks[0] (which is left_stack) will always be returned. That’s fine for the very first “from” entry, but of course won’t work for “to”.

You have correctly identified a fix. Congratulations! I’ll try to pass on the error info.


Aside: If you have enjoyed this exercise (apart from the bug!), check out my ASCII-Graphic and Self-solving add-ons.

2 Likes