1

I want to iterate through a Ruby array by index. I have a game where I want the players to have individual turns of rolling a dice until one gets to 20, each turn adds to their score. So far it will do all the turns for player 1 until they get to 20 and then will do player 2 until they get to 20

 players_array.each do |player|
        player = Person.new(player)
        until player.players_score.inject(0, :+) >= 20 do
          score = player.dice_roll
          player.add_to_score(score)
          print player.players_score
          print "\n"
          print player, + player.players_score.inject(0, :+).to_s
          print "\n"
      end
    end

I understand it might be with each_with_index any ideas?

thanks

new code:

players_array.each do |player|
  while TRUE
    player = Person.new(player)
    score = player.dice_roll
    player.add_to_score(score)
    if player.players_score.inject(0, :+) > 20
      # puts player.players_score
      puts '20 hit'
      break
    else
      next
    end
  end
end
5
  • Change to players_array.each_with_index do |player, idx|, where idx will be the index Commented May 27, 2016 at 9:48
  • @Santhosh Do you mean players_array.each_with_index...? Commented May 27, 2016 at 9:50
  • Yes, it was a typo. My bad. thanks Commented May 27, 2016 at 9:51
  • why do you create a new instance of player in every iteration? Commented May 27, 2016 at 11:12
  • I think you would benefit from psuedocoing. You're overcomplicating things. Commented May 27, 2016 at 16:26

2 Answers 2

2

Your problem is that in the first player iteration, the until expression iterates until the score gets to 20. It never gets to any other players.

I suggest removing the until expression, surround the players loop with an infinite loop using loop, and then break when a player reaches 20. break might break from only the inner loop, so better would be to write a method that does all this, and then return from the method, instead of breaking.

To be more precise, I'm suggesting writing a method that takes the players array (and maybe the 20 threshold) as input, and returns whatever information you need (maybe winning player object and final score) as its return expression.

You can return multiple expressions in Ruby as an array, e.g. ['Juan De La Cruz', 22], and then deconstruct it, like this:

winning_player, winning_score = play_round(players, 20)
Sign up to request clarification or add additional context in comments.

2 Comments

ok still not quite getting it. see edited code and see if you can help again. thanks
Better to use loop do...end than while...end. The loop do...end should be outside the players.each... Also, please fix indentation. Also, break may not work, you may need to put it in a method and return.
0

Here is an attempt to do the same using some Ruby idioms.

players = ["P1", "P2"].cycle

scores = Hash.new {|hash, k| hash[k] = []}

begin
  scores[winner = players.next] << (1..6).to_a.sample 
end until scores.any? {|_,v| v.reduce(:+) >= 20}

p winner # Prints winning player's id

Explanation:

  1. players is an array containing list of players.

  2. players.cycle is an enumerator, calling next on which will give us next element from the array, and after the last element of array is returned, next call to next will return the first element - this effectively sets up a players' turns as a loop.

  3. scores is a hash to track all the dice rolls by using player's id as key. It has been setup up such a way that when a non-existing key is accessed for first time, it is is initialised to have an empty array ([]) as its value.

  4. Next is the begin ... until loop that will roll a dice for each player one by one, and loop will break moment any player has score more than 20. To track the winner, the last user for which dice was rolled is captured in variable winner in a clever manner.

  5. Roll of dice is simulated by sampling a value from an array containing numbers 1 to 6.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.