Tuesday, November 5, 2019
Creating Two Dimensional Arrays in Ruby
Creating Two Dimensional Arrays in Ruby The following article is part of a series.à For more articles in this series, seeà Cloning the Game 2048 in Ruby.à For the complete and final code,à see the gist. Now that we know how the algorithm will work, its time to think about the data this algorithm will work on. There are two main choices here: a flat array of some kind, or a two-dimensional array. Each has their advantages, but before we make a decision, we need to take something into account. DRY Puzzles A common technique in working with grid-based puzzles where you have to look for patterns like this is to write one version of the algorithm that works on the puzzle from left to right and then rotate the entire puzzle around four times. This way, the algorithm only has to be written once and it only has to work from left to right. This dramatically reduces the complexity and size of the hardest part of this project. Since well be working on the puzzle from left to right, it makes sense to have the rows represented by arrays. When making a two dimensional array in Ruby (or, more accurately, how you want it to be addressed and what the data actually means), you have to decide whether you want a stack of rows (where each row of the grid is represented by an array) or a stack of columns (where each column is an array). Since were working with rows, well choose rows. How this 2D array is rotated, well get to after we actually construct such an array. Constructing Two Dimensional Arrays The Array.new method can take an argument defining the size of the array that you want. For example, Array.new(5) will create an array of 5 nil objects. The second argument gives you a default value, so Array.new(5, 0) will give you the array [0,0,0,0,0]. So how do you create a two dimensional array? The wrong way, and the way I see people trying often is to say Array.new( 4, Array.new(4, 0) ). In other words, an array of 4 rows, each row being an array of 4 zeroes. And this appears to work at first. However, run the following code: It looks simple. Make a 4x4 array of zeroes, set the top-left element to 1. But print it and we getâ⬠¦ It set the entire first column to 1, what gives? When we made the arrays, the inner-most call to Array.new gets called first, making a single row. A single reference to this row is then duplicated 4 times to fill the outer-most array. Each row is then referencing the same array. Change one, change them all. Instead, we need to use the third way of creating an array in Ruby. Instead of passing a value to the Array.new method, we pass a block. The block is executed every time the Array.new method needs a new value. So if you were to say Array.new(5) { gets.chomp }, Ruby will stop and ask for input 5 times. So all we need to do is just create a new array inside this block. So we end up with Array.new(4) { Array.new(4,0) }. Now lets try that test case again. And it does just as youd expect. So even though Ruby doesnt have support for two-dimensional arrays, we can still do what we need. Just remember that the top-level array holds references to the sub-arrays, and each sub-array should refer to a different array of values. What this array represents is up to you. In our case, this array is laid out as rows. The first index is the row were indexing, from top to bottom. To index the top row of the puzzle, we use a[0], to index the next row down we use a[1]. To index a specific tile in the second row, we use a[1][n]. However, if we had decided on columnsâ⬠¦ it would be the same thing. Ruby doesnt have any idea what were doing with this data, and since it doesnt technically support two-dimensional arrays, what were doing here is a hack. Access it only by convention and everything will hold together. Forget what the data underneath is supposed to be doing and everything can fall apart real fast.
Subscribe to:
Post Comments (Atom)
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.