0

I need to convert a string (64 character representation of a checker board):

game_state = "r_____r__r___r_rr_r___r__________________b_b______b_b____b_b___b"

into a two dimensional, 8 X 8, array of checker objects:

[ [red_checker, nil, nil, nil, nil....and so on times 8], ]

This is my way of doing it, which is ugly and not very ruby like with the increment near the end.

def game_state_string_to_board(game_state)
    board = Board.new
    game_board = board.create_test_board

    game_state_array = []
    game_state.each_char { |char| game_state_array << char}
    row_index = 0
    game_state_array.each_slice(8) do |row|
      row.each_with_index do |square, col_index|
        unless square == '_'
          game_board[row_index][col_index] = create_checker(square, row_index, col_index)
        end
      end
      row_index += 1
    end
    game_board
  end

Does anyone have a cleaner, simpler, more ruby-ish way? Thanks.

2
  • Sounds like a homework assignment. Commented Feb 28, 2012 at 18:49
  • @the Tin Man Nah, this is actually my job right now. Commented Feb 28, 2012 at 21:49

2 Answers 2

2

Something like this ought to work (Ruby 1.9.x):

game_state = "r_____r__r___r_rr_r___r__________________b_b______b_b____b_b___b"

game_state.split( '' ).each_with_index.map do |square, idx|
  square == '_' ? nil : create_checker( square, idx / 8, idx % 8 )
end.each_slice( 8 ).to_a

Output:

[ [ #<RedChecker(0,0)>, nil, nil, nil, nil, nil, #<RedChecker(0,6)>, nil],
  [ nil, #<RedChecker(1,1)>, nil, nil, nil, #<RedChecker(1,5)>, nil, #<RedChecker(1,7)>],
  [ #<RedChecker(2,0)>, nil, #<RedChecker(2,2)>, nil, nil, nil, #<RedChecker(2,6)>, nil],
  [ nil, nil, nil, nil, nil, nil, nil, nil],
  [ nil, nil, nil, nil, nil, nil, nil, nil],
  [ nil, #<BlackChecker(5,1)>, nil, #<BlackChecker(5,3)>, nil, nil, nil, nil],
  [ nil, nil, #<BlackChecker(6,2)>, nil, #<BlackChecker(6,4)>, nil, nil, nil],
  [ nil, #<BlackChecker(7,1)>, nil, #<BlackChecker(7,3)>, nil, nil, nil, #<BlackChecker(7,7) ]
]

Since it's a bit dense I'll break it down:

game_state.
  # change the string into an Array like [ "r", "_", "_", ...]
  split( '' ).

  # `each_with_index` gives us an Enumerable that passes the index of each element...
  each_with_index.

  # ...so we can access the index in `map`
  map do |square, idx|
    square == "_" ?
      # output nil if the input is "_"
      nil :
      # otherwise call create_checker
      create_checker( square,
        idx / 8,  # the row can be derived with integer division
        idx % 8   # and the column is the modulus (remainder)
      )
  end.

  # take the result of `map` and slice it up into arrays of 8 elements each
  each_slice( 8 ).to_a
Sign up to request clarification or add additional context in comments.

Comments

1

if you want an 8 x 8 array this would do:

game_state = "r_____r__r___r_rr_r___r__________________b_b______b_b____b_b___b"

game_state.split('').each_slice(8).to_a

"[[\"r\", \"_\", \"_\", \"_\", \"_\", \"_\", \"r\", \"_\"], [\"_\", \"r\", \"_\", \"_\", \"_\", \"r\", \"_\", \"r\"], [\"r\", \"_\", \"r\", \"_\", \"_\", \"_\", \"r\", \"_\"], [\"_\", \"_\", \"_\", \"_\", \"_\", \"_\", \"_\", \"_\"], [\"_\", \"_\", \"_\", \"_\", \"_\", \"_\", \"_\", \"_\"], [\"_\", \"b\", \"_\", \"b\", \"_\", \"_\", \"_\", \"_\"], [\"_\", \"_\", \"b\", \"_\", \"b\", \"_\", \"_\", \"_\"], [\"_\", \"b\", \"_\", \"b\", \"_\", \"_\", \"_\", \"b\"]]"

I dont know what some methods in your code do, but this should answer your question

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.