Я новичок в программировании и только начал изучать Ruby. Я написал приведенную ниже программу, чтобы попрактиковаться в циклах, переменных и т. д. По сути, программа имитирует карточную машину для стирки, где пользователь может получить новую карту или загрузить значение в существующую карту. Принцип работы заключается в том, что он случайным образом выбирает значение карты: либо необходимо купить новую карту, либо иметь существующую карту с суммой X в $s.
Кажется, это работает, но у меня возникает проблема: когда пользователь пытается вернуться к экрану приветствия, а затем вводит значение, независимо от того, что вводит пользователь, он просто переходит непосредственно к отображению меню. В идеале он должен отображать «НЕВЕРНЫЙ ВВОД», если пользователь вводит что-либо, кроме «ввод». Я подозреваю, что я неправильно написал свой цикл.
Что я делаю неправильно?
Заранее спасибо, что нашли время прочитать и помочь :)
# Method that randomly generates either need for a card or existing card with balance between $1-25
def card_value
# "NO CARD"
arr = [nil, (1..25)]
value = arr.sample
if value == nil
"NO CARD"
else
rand(value)
end
end
# Variable assigned to return value of method card_value
balance = card_value
# Method that outputs a string when user input is incorrect
def invalid
puts "INVALID RESPONSE"
end
# Method for main screen, prompts user to start
def welcome
puts ""
puts "*******************************"
puts " HERCULES ADD VALUE STATION"
puts " WELCOME"
puts ""
puts " | Enter? |"
puts "*******************************"
puts " Type Enter to continue:"
puts "-------------------------------"
puts ""
start = gets.chomp
end
# Method that displays the need of a card or the card balance
def card_balance(balance)
puts ""
puts "-------------------------------"
puts ""
if balance == "NO CARD"
puts " | #{balance} |"
else
puts " | BALANCE IS $#{balance} |"
end
puts ""
puts "-------------------------------"
balance
end
# Method that displays the option screen, prompts user to get a card or add balance to card
def menu(balance)
loop do
card_balance(balance)
puts ""
puts "*******************************"
puts "| NEW CARD? | or | ADD VALUE? |"
puts "*******************************"
puts " Type '1' to buy new card"
puts " Type '2' to add value"
puts " Type 'X' to exit"
puts "-------------------------------"
puts ""
buy_add = gets.chomp
if buy_add == "1" && balance == "NO CARD"
buy_card(balance)
elsif buy_add == "2" && (balance.is_a? Integer)
add_value(balance)
elsif buy_add.upcase == "X"
welcome
else
invalid
end
end
end
# Method that displays buy new card, prompts user to add money to buy card
def buy_card(balance)
loop do
puts ""
puts "*******************************"
puts " |NEW CARD - $5|"
puts "*******************************"
puts " Type '5' to purchase card"
puts " Type 'X' to exit"
puts "-------------------------------"
puts ""
new_card = gets.chomp
if new_card == "5" && balance == "NO CARD"
puts ""
puts "*******************************"
puts " |NEW CARD PURCHASED!|"
puts "*******************************"
balance = 0
puts "BALANCE IS $#{balance}"
balance
elsif new_card == "5" && balance == 0
puts "YOU ALREADY HAVE A CARD"
elsif new_card.upcase == "X"
menu(balance)
else
invalid
end
end
end
# Method that displays the options for loading card value, prompts user for amount and displays
# the updated balance
def add_value(balance)
loop do
puts ""
puts "*******************************"
puts " |ADD VALUE|"
puts " |$15| |$35| |$50| |$75|"
puts "*******************************"
puts " Type '15' to add $15"
puts " Type '35' to add $35"
puts " Type '50' to add $50"
puts " Type '75' to add $75"
puts " Type 'X' to exit"
puts "-------------------------------"
puts ""
puts "BALANCE IS $#{balance}"
add_more = gets.chomp
if add_more == "15"
new_balance = balance += 15
elsif add_more == "35"
new_balance = balance += 35
elsif add_more == "50"
new_balance = balance += 50
elsif add_more == "75"
new_balance = balance += 75
elsif add_more.upcase == "X"
menu(balance)
else
invalid
end
puts "NEW BALANCE = #{balance}"
end
end
loop do
if welcome.downcase == "enter"
menu(balance)
else
invalid
end
end
Я думаю, что проблема заключается в :menu(balance).. но не могу понять, что делать.
После входа в цикл menu
он останется там навсегда, так как вы никогда из него не вырветесь.
Один из быстрых способов исправить это — использовать break
после вызова экрана welcome
, чтобы он возвращался к основному циклу в конце файла:
elsif buy_add.upcase == "X"
welcome
break
В этом отношении, всякий раз, когда вам нужно вернуться к родительскому/внешнему циклу, просто используйте break
еще раз. Я вижу еще два случая в вашем коде: buy_card
и add_value
. Если вы добавите break
в условие "X"
на этих экранах, это должно исправить все застрявшие циклы.
И если вы проанализируете код еще немного, вы также обнаружите, что вызов «родительского» экрана и прерывание после него не исправляет еще одну скрытую ошибку, которая, как ни странно, представляет собой переполнение стека. Если вы продолжаете входить и выходить из экранов в течение длительного времени, через некоторое время стек переполнится, потому что вы продолжаете входить в циклы и вызывать новые функции, которые создают новые циклы и никогда фактически не завершают предыдущие циклы. Чтобы исправить это раз и навсегда, вы должны сделать что-то вроде:
elsif buy_add.upcase == "X"
break
Что также следует воспроизвести в других "X"
условиях и для других функций. Таким образом, после того, как пользователь введет «X», он просто завершит функцию и вернется к родительской/вызывающей функции.
В тех случаях, когда вы вызываете menu(balance)
, конечно, замена его только на break
не приведет к обновлению баланса пользователя, поэтому вам нужно воспользоваться преимуществами работы функций, чтобы действительно правильно обновить баланс. Я бы посоветовал вам всегда return balance
в конце любого подменю вместо использования break
в таких случаях и обновлять баланс в функции menu
, например balance = buy_card(balance)
. Я не буду раскрывать вам весь фиксированный фрагмент кода, но этого должно быть достаточно, чтобы вы могли начать отладку и исправление некоторых проблем, с которыми вы сталкиваетесь.
Это потрясающе – определенно есть над чем подумать. Большое спасибо, что нашли время ответить на мой вопрос.