Pasando argumentos a funciones en ruby ​​usando variables

Siguiendo el tutorial Zed A. Shaw, I'm writing a soccer game. My code so far is as follows:

$team_a_players = ["Basar", "Mehmet", "Abdullah", "Alpaslan", "Salih", "Recep", "Ibrahim", "Orhan", "Hakki", "Yakup", "Serdar"]
$team_a_substitutes = ["Hasan", "Turgay", "Umit"]
$team_b_players = ["Habib", "Erkan", "Sahin", "Cemal", "Ahmet", "Fikret", "Yucel", "Pergel", "Ali", "Sabri", "Yilmaz"]
$team_b_substitutes = ["Abdulkadir", "Gokhan", "Mustafa"]
$yellow = []
$red = []
$reasons = ["corner", "direct attack", "free kick", "side attack", "speed kick"]
$team_a_attack = 90.0
$team_a_defense = 80.0
$team_b_attack = 70.0
$team_b_defense = 60.0
$team_a_goals = 0
$team_b_goals = 0

def prompt()
  print "> "
end

def dice()
  if rand(2) == 0
    round_team_a()

  else
    round_team_b()
  end
end

def fauls()
  if rand(0) > 0.95 and rand(10) % 2 == 0
    faul_player = $team_a_players[rand(11)]
    if $yellow.include?(faul_player)
      $red.push(faul_player)
      $team_a_players.delete("faulplayer")
      puts "#{faul_player} of Team A gets a red card in #{$i}. minute!"
      puts "Who would you like to substitute in place of #{faul_player}?"
      list_subs_a()
      prompt()
      substitute = STDIN.gets.chomp()
      $team_a_players.push("substitute")
      $yellow.delete(faul_player)

    else
      $yellow.push(faul_player)
      puts "#{faul_player} of Team A gets a yellow card in #{$i}. minute!"
    end

  elsif rand(0) > 0.95 and rand(10) % 2 == 1
    faul_player = $team_b_players[rand(11)]
    if $yellow.include?(faul_player)
      $red.push(faul_player)
      $team_b_players.delete("faulplayer")
      puts "#{faul_player} of Team B gets a red card in #{$i}. minute!"
      puts "Who would you like to substitute in place of #{faul_player}?"
      list_subs_b()
      prompt()
      substitute = STDIN.gets.chomp()
      $team_b_players.push("substitute")
      $yellow.delete(faul_player)

    else
      $yellow.push(faul_player)
      puts "#{faul_player} of Team B gets a yellow card in #{$i}. minute!"
    end

  else
    faul_player = nil
  end
end

def list_subs_a()
  $team_a_substitutes.each {|p| puts p}
end

def list_subs_b()
  $team_b_substitutes.each {|p| puts p}
end

def list_yellow()
  $yellow.each {|p| puts p}
end

def list_red()
  $red.each {|p| puts p}
end

def round_team_a()
  score = $team_a_attack / $team_b_defense * rand(0)
  if score > 1
    goal = 1
    $team_a_goals += 1
    reason = $reasons[rand(5)]
    puts "Team A scored #{goal} goal through a #{reason} in #{$i}. minute!"

  else
    goal = 0
  end
end

def round_team_b()
  score = $team_b_attack / $team_a_defense * rand(0)
  if score > 1
    goal = 1
    $team_b_goals += 1
    reason = $reasons[rand(5)]
    puts "Team B scored #{goal} goal through a #{reason} in #{$i}. minute!"

  else
    goal = 0
  end
end

def match()
  $i = 0
  until $i > 59 do
    dice()
    fauls()
    $i += 1
  end
  puts "Team A scored a total of #{$team_a_goals} goals and Team B scored a total of #{$team_b_goals} goals."
  if $team_a_goals > $team_b_goals
    puts "Team A won against Team B by #{$team_a_goals}:#{$team_b_goals}!"

  elsif $team_b_goals > $team_a_goals
    puts "Team B won against Team A by #{$team_b_goals}:#{$team_b_goals}!"

  else
    puts "It's a tie!"
  end

  if $yellow.length > 0
    puts "Players shown a yellow card are:"
    list_yellow() 

  else
    puts "No yellow cards in the end of the game"
  end

  if $red.length > 0
    puts "Players shown a red card are:"
    list_red()

  else
    puts "No red cards in the end of the game"
  end
end

match()

From here, I would like to do the following:

  • Replace the arrays $yellow y $red with hashes so that I can also report minutes and teams of yellow- and red-cards.
  • Replace the arrays starting with the name $team_ with hashes so that I can add individualized attack- and defense-powers to players so that substitutions mean sth. but before the code gets any more complex, I have to solve sth. This looks similar to this question concerning php.
  • Definir las funciones list, round y faul in a way that can be used common to a_players y b_players . traté de hacer team_#{team}_players en lugar de team_a_players etc, but cannot achieve it.

What I seek is a guide to that problem, not a solution, so that I can fix this myself. A link or long explanation in clear words is very much more welcome than a fixed code. And please note that the tutorial has not mentioned classes yet, so this is not an option yet.

preguntado el 10 de marzo de 12 a las 12:03

If the ebook taught you to create all those global variables, I'd probably try a different book ;) I know you're new to ruby, but if there's one thing I could tell you to try and get right early, it would be to think about your code in terms of small units (Player, Team, Substitute, Match, Score, etc...) and to limit the data you externalize in those units to whatever is needed to glue everything together. Using global variables gets out of hand quickly, as you can see from your variable names. -

No, the book is certainly not guilty. Actually I even read este link about global variables but couldn't get the whole thing since I lack basics of computer programming. But thank you for reminding me of this. -

1 Respuestas

The basic idea you haven't seemed to grasp is passing arguments to functions. Assume we have two global variables and we wish to perform identical operations on them - say multiply elements of arrays by 2. You write:

$a = [1,2,3]
$b = [2,3,4]

def multiply_a
  result = []
  for element in $a do
    result << element * 2
  end
  result
end

def multiply_b
  result = []
  for element in $b do
    result << element * 2
  end
  result
end

But this code is bad. First of all, you should note that in Ruby $a is a special variable - a global variable. You should never need to use them - writing code containing them means that there is something wrong with it. So how to fix it? The basic idea is to pass an argument to a function, instead of hard coding the variable, the function operates on. So you can transform the code as follows:

a = [1, 2, 3]
b = [2, 3, 4]
def multiply(argument)
  result = []
  for element in argument do
    result << element * 2
  end
  result
end
# and then call
multiply(a) # instead of multiply_a
multiply(b) # instead of multiply_b 

This is the way you should fix your code.

respondido 10 mar '12, 13:03

I fixed the code according to your suggestion and got rid of the globals. But this also costs me the methods. Could you very mind to check THE NEW CODE ON THIS PAGE and tell me if I'm in the right track or not. *PS: this is a one time request, I promise. - barrerd

I am afraid, that this is not what you should do. Don't remove the methods, just make them accept parameters. - Alejandro Pohl

Thank you for responding. I made the methods accept parameters, but if you don't mind, could you just check the final version and tell me if the passing of variable "min" is the proper way to do it? The document is here - barrerd

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.