ruby methods dry

ruby - SECADO de tijeras de papel roca



methods dry (4)

Soy un programador de rubí novato y, aunque este código funciona, me pregunto cómo puedo mejorarlo. Tengo un conocimiento muy limitado sobre lambdas y procs y similares, pero cualquier consejo sería genial. ¿Hay alguna manera de simplificar las declaraciones if else en cada caso? Además, ¿hay alguna manera alternativa de omitir el enunciado de case lugar de hacer que casi la totalidad del código sea una declaración grande si no?

def rps(roll) roll_ops = ["rock", "paper", "scissors"] pick = roll_ops.sample result = nil if roll == pick result = "tie" else case roll when "scissors" then if pick == "paper" result = "win" else result = "lose" end when "rock" then if pick == "scissors" result = "win" else result = "lose" end when "paper" then if pick == "rock" result = "win" else result = "lose" end else puts "Please input rock paper or scissors" end end puts "#{pick}, #{result}" end rps("scissors")


Aquí hay un par de formas:

# 1 Usar ciclo de matriz

OPS = %w[rock paper scissors] def rps(roll) pick = OPS.sample enum = OPS.cycle (prev = enum.next) until enum.peek == roll return [pick, "lose"] if prev == pick enum.next return [pick, "win"] if enum.peek == pick [pick, "tie"] end rps "scissors" #=> ["scissors", "tie"] rps "scissors" #=> ["scissors", "tie"] rps "scissors" #=> ["rock", "win"] rps "scissors" #=> ["paper", "lose"]

# 2 Lleva la respuesta de @MiFoFoX un paso más allá

def rps(roll) roll_ops = %w|rock paper scissors| h = (roll_ops + [roll_ops.first]).each_cons(2). with_object(Hash.new("tie")) { |(a,b),h| h[[a,b]]="lose"; h[[b,a]]="win" } pick = roll_ops.sample [pick, h[[roll,pick]]] end rps "scissors" #=> ["rock", "lose"] rps "scissors" #=> ["scissors", "tie"] rps "scissors" #=> ["paper", "win"]

Aquí:

h #=> {["rock", "paper"]=>"lose", ["paper", "rock"]=>"win", # ["paper", "scissors"]=>"lose", ["scissors", "paper"]=>"win", # ["scissors", "rock"]=>"lose", ["rock", "scissors"]=>"win"}

y debido al valor predeterminado "empate":

h[["rock", "rock"]] #=> "tie" h[["paper", "paper"]] #=> "tie" h[["scissors", "scissors"]] #=> "tie"


Puede construir un hash que contenga la selección y qué opción perder contra esa selección:

hash = {''scissors'' => ''paper'', ''rock'' => ''scissors'', ''paper'' => ''rock''}

Luego, comprueba si la selección de la máquina es la misma que la que hizo:

roll_ops = ["rock", "paper", "scissors"] pick = roll_ops.sample if roll == pick

Y la condición de ganar / perder se convierte en algo como esto:

if hash[roll] == pick "win" else "lose" end

Agradable y limpio con solo 2 condiciones.


Creo que un proceso u otra configuración similar es probablemente excesivo. Solo use ifs en línea:

def rps(roll) raise "Choose rock, paper, or scissors" if roll.nil? roll_ops = ["rock", "paper", "scissors"] pick = roll_ops.sample result = if roll == pick "tie" else case roll when "scissors" pick == "paper" ? ''win'' : ''lose'' when "rock" pick == "scissors" ? ''win'' : ''lose'' when "paper" then pick == "rock" ? ''win'' : ''lose'' end end puts "#{pick}, #{result}" end rps("scissors")

Eliminé tu extra adicional que se suponía que manejaba sin entrada. Es mejor usar errores en tal caso.

Hay un par de trucos aquí:

1- Los ifs en línea. Esos deberían ser bastante claros.

2- La variable de resultado se establece igual al valor de retorno de la expresión if. Este es un truco útil que puedes usar porque en Ruby, ¡todo es una expresión!

Si está interesado en usar una lambda para esto, también debería funcionar bastante bien:

def rps(roll) raise "Choose rock, paper, or scissors" if roll.nil? roll_ops = ["rock", "paper", "scissors"] pick = roll_ops.sample did_win = lambda do |choice| return choice == pick ? ''win'' : ''lose'' end result = if roll == pick "tie" else case roll when "scissors" did_win.call(''paper'') when "rock" did_win.call(''scissors'') when "paper" then did_win.call(''rock'') end end puts "#{pick}, #{result}" end


ROLL_OPS = %w[rock paper scissors] RESULTS = %w[tie lose win] def rps(roll) unless i = ROLL_OPS.index(roll) return puts "Please input rock paper or scissors".freeze end pick = ROLL_OPS.sample puts "#{pick}, #{RESULTS[(i - ROLL_OPS.index(pick)) % 3]}" end