Search code examples
rubyconditional-statementstowers-of-hanoi

Towers of Hanoi, Ruby conditional


I'm having trouble with my first if conditional, which checks to make sure the the new piece added is smaller than the one under/before it. My Towers of Hanoi game worked fine until I added it. Below is my code:

arrays = [[5,4,3,2,1],[],[]]
win = false

while win != true
   puts "Choose a top piece: (1, 2, 3) "
   top = gets.to_i
   puts "Which stack to place this piece? (1, 2, 3)"
   stack = gets.to_i

   if (arrays[stack-1] == nil) ||
      (arrays[stack-1][arrays[stack-1].count-1] > arrays[top-1][arrays[top-1][arrays[top-1].count]])
     arrays[stack-1].push(arrays[top-1].pop)
   else
     "You need to follow the rules."
   end

   print arrays
   if arrays[1] == [5,4,3,2,1] || arrays[2] == [5,4,3,2,1]
     print "You're a winner!"
     win = true
   end
end
~

Below is the error I get. How do I perform my check and deal with my nil value arrays in a concise manner?

towers_hanoi:13:in `[]': no implicit conversion from nil to integer (TypeError)
        from towers_hanoi:13:in `<main>'

Solution

  • There are a lot of strange things going on in that if statement.

    Definitely use Array#empty? to check if an array if empty. An empty array is not nil.

    Secondly some of your array bracketing is way too convoluted, I'm not sure what you are trying to accomplish here but you are definitely going to be checking if nil > number in some cases:

    (arrays[stack-1][arrays[stack-1].count-1] > arrays[top-1][arrays[top-1][arrays[top-1].count]])
    

    I doubt this is what you are trying to do (since it will throw an error). I would take a minute to think about your logic and refactor. In Towers of Hanoi, you only need to worry about checking if the piece you are moving is less than the LAST piece on the stack you are moving to (which represents the top).

    Use Array#last and you will be on your way to a much simpler solution.