2016-04-08 9 views
1

Ich möchte wissen, ob dies eine gute Möglichkeit ist, eine Schleife in der case-Anweisung zu tun. Ist es in Ordnung, die Methode zurückzurufen, wenn die Antwort (Benutzereingabe) eine schlechte Eingabe ist? Gibt es einen besseren Weg?können Sie eine Methode in einer Case-Anweisung aufrufen Ruby

def game_type # Selecting humans or computers as players 
    puts "Please select game type by number:" 
    puts "1 - human vs human" 
    puts "2 - computer vs computer" 
    puts "3 - human vs computer" 
    response = gets.chomp.to_i 

    case response 
    when 1 
     puts "human vs human" 
    when 2 
     puts "computer vs computer" 
    when 3 
     puts "human vs computer" 
    else 
     game_type 
    end 
    end 

Antwort

3

Das rekursive Aufrufen der Methode ist sehr schlecht, da für jeden rekursiven Aufruf eine zusätzliche Tiefe zum Aufruf-Stack hinzugefügt wird und Sie nicht vorhersagen können, wie tief sie sein wird, was die Performance beeinträchtigt. Im Allgemeinen sollte Rekursion möglichst vermieden werden. Verwenden Sie in diesem Fall eine Schleife, für die kein rekursiver Aufruf erforderlich ist.

def game_type 
    loop do 
    puts <<~_ 
     Please select game type by number: 
     1 - human vs human 
     2 - computer vs computer 
     3 - human vs computer 
    _ 
    response = gets.to_i 
    case response 
    when 1 
     puts "human vs human" 
     break 
    when 2 
     puts "computer vs computer" 
     break 
    when 3 
     puts "human vs computer" 
     break 
    end 
    end 
end 
0

Das Standardmuster für diese Art der Interaktion ist eine else Zweig zu haben, die für eine andere Schleife beschwert und sendet Ihnen zurück.

Eine Sache zu beachten bei Ruby ist, sollten Sie versuchen, solche Dinge in einer regelmäßigen Struktur zu definieren, um eine Menge Wiederholungen zu vermeiden. Das Prinzip "Do not Repair Yourself" (DRY) ist sehr wichtig. Halte es trocken!

Also in diesem Fall:

GAME_TYPE_LIST = [ 
    "Human vs. Human", 
    "Computer vs. Computer", 
    "Human vs. Computer" 
] 

# Convert this list to a hash indexed by 1, 2, 3, etc. 
GAME_TYPES = Hash[GAME_TYPE_LIST.each_with_index.map { |type, i| [ i + 1, type ] }] 

, dass es ziemlich einfach macht mehr Arten in der Zukunft hinzuzufügen, und auch super einfach Ihr Menü zu präsentieren:

GAME_TYPES.each do |i, type| 
    puts '%d - %s' % [ i, type ] 
end 

Ebenso, wenn es darum geht, Zeit zu wählen:

game_type = nil 

begin 
    puts "Enter type:" 

    game_type = gets.chomp.to_i 
end while (!GAME_TYPES[game_type]) 

Das wird Schleifen Sie util Sie erhalten es richtig.

+0

Komm schon, du weißt es besser als 'chomp' zu benutzen. – sawa

+0

@sawa Was ist so schlimm daran, die Newline zu entfernen? 'to_i 'ist vielleicht egal, aber ich mag es saubere Daten zu füttern. – tadman

-1

Ich möchte wissen, ob dies eine Ordnung Art und Weise ist eine Schleife in der Case-Anweisung zu tun. Ist es in Ordnung, die Methode zurückzurufen, wenn die Antwort (Benutzereingabe) eine schlechte Eingabe ist?

Während Sie kann tun, als Sawa gesagt, das ist keine gute Praxis in Ruby, aus Gründen, die Leistung bezogen.

Gibt es einen besseren Weg?

Anstatt Verwendung Rekursion verwenden loop:

GAME_TYPES = { 
    1 => "human vs computer", 
    2 => "computer vs computer", 
    3 => "human vs human" 
} 

def game_type 
    loop do  
    puts <<~___ 
     Please select game type by number: 
     1 - human vs human 
     2 - computer vs computer 
     3 - human vs computer 
    ___ 
    selection = gets.to_i 
    if game_type_str = GAME_TYPES[selection] 
     puts game_type_str 
     break 
    end 
    end 
end 

(Ich habe auch Ihren Code ein Wörterbuch eher als eine case Anweisung zu verwenden, die den Code viel prägnanter macht als ein Bündel von break mit Aussagen).

+0

"Ich ** habe ** auch ** deinen ** Code geändert, um ein Wörterbuch zu verwenden" --- Ist das nicht das ** einzige ** was du von ** meiner ** Antwort geändert hast? Bitte nicht auf andere Antworten parasitieren. Wenn Sie etwas zu sagen haben, schreiben Sie es in Ihren eigenen Worten, verwenden Sie Ihren eigenen Code, nicht so, als ob Sie es geschrieben hätten. – sawa

+0

Entschuldigung, ich denke, ich habe es kopiert, aber es gibt wirklich nicht hundert Möglichkeiten, einen "while" -Block in einen "loop" zu verwandeln ... Ich schrieb den Code in sublime, bevor ich posten konnte und sah erst danach deine Antwort redigiert, um Ihre Antwort zu erwähnen, die ich auch upvoted). –

+1

Es ist schwer zu glauben, dass die Verwendung einer einzigen "puts" -Methode mit einem heredoc mit dem gleichen Modus "~", mit der gleichen Kennung "_" und das präzise Entfernen des redundanten "chomp" alles Zufall war. – sawa

Verwandte Themen