Home > Enterprise >  How to populate a 2D array with random elements?
How to populate a 2D array with random elements?

Time:06-23

For a Memory game, I'm trying to randomly populate a 2D array with letters.

The grid is size × size and each letter occurs twice.

This is my code so far. I don't understand why it is giving an error

alpha = ("A".."Z").to_a
letters_range = alpha[0...size*size/2]
chosen_letters = (letters_range   letters_range).shuffle

(0...size).each do |row|
    (0...size).each do |col|
        letter = chosen_letters.select
        @grid[row][col] = Card.new(letter)
        letter_idx = chosen_letters.index(letter)
        chosen_letters.delete_at(letter_idx)  #error line
    end
end

CodePudding user response:

chosen_letters is an array containing single-character strings.

When running letter = chosen_letters.select, you may assume that Array#select returns a random element. However, when not passing it a block, it returns an Enumerator. As such, your letter variable does not contain an element from the chosen_letter array and thus, an index for this object can not be found, resulting in letter_idx to be nil.

To fix this, you may want to use a more appropriate statement to fetch an element, e.g. Array#pop to return and remove the last element from the array.

CodePudding user response:

Since chosen_letters is already shuffled, you don't have to pick a random element. Instead you can just pop the last or shift the first element off the array which makes your loop a lot simpler:

(0...size).each do |row|
  (0...size).each do |col|
    letter = chosen_letters.shift
    @grid[row][col] = Card.new(letter)
  end
end

It might be a little cleaner to start with an array of cards, e.g. by creating a pair of two cards for each letter:

cards = letters_range.flat_map { |letter| [Card.new(letter), Card.new(letter)] }

cards.shuffle!

You can then assign the cards to the grid via:

(0...size).each do |row|
  (0...size).each do |col|
    @grid[row][col] = cards.shift
  end
end

or you could build the @grid right out of the array via each_slice:

@grid = cards.each_slice(size).to_a
  • Related