Reputation: 2792
I'm trying to populate a multi-dimensional array in ruby by reading from a file. Here is the code:
class Maze
attr_accessor :array
def initialize(filename)
handler = File.open(filename,"r")
@array = Array.new(10,Array.new(10))
n = 0;
i = 0;
while(line = handler.gets) do
i = 0
line.chomp.each_char do |char|
p char
@array[n][i] = char
i += 1
end #iterator over character in every line
n += 1
end #iterator over file lines
handler.close
end #constructor
end #class
a = Maze.new("maze.txt")
p a.array
Here is the content of the file:
##########
# #
# #### #
# # # #
@ # # ?
# # # #
# # #
# #### #
# #
##########
However this line of code (the last line of code)
p a.array
Will print an array 10 by 10 but full of "#" symbols. No spaces nor "?". Something important to note is that
p char
In the block where I assign the array with values prints the right characters. It prints spaces at the right time and question marks etc... I know it's something very simple but it's bugging me and I think I need a fresh pair of eyes to look over it
Why is it that the array has only "#" symbols. Why aren't all the other characters such as " ", "@", "?" in my array? Is the assigning in my code wrongly coded
Upvotes: 0
Views: 379
Reputation: 160551
I'd write the code differently. It's not quite clear what you're trying to do, so here's two different things I'd do:
class Maze
attr_accessor :array
def initialize(filename)
@array = []
File.foreach(filename) do |line|
@array << line.chomp
end
end
end
a = Maze.new("maze.txt")
p a.array
puts a.array
Which outputs:
["##########", "# #", "# #### #", "# # # #", "@ # # ?", "# # # #", "# # #", "# #### #", "# #", "##########"]
##########
# #
# #### #
# # # #
@ # # ?
# # # #
# # #
# #### #
# #
##########
Or:
class Maze
attr_accessor :array
def initialize(filename)
@array = []
File.foreach(filename) do |line|
@array << line.chomp.split('')
end
end
end
a = Maze.new("maze.txt")
p a.array
puts a.array.map(&:join)
which outputs:
[["#", "#", "#", "#", "#", "#", "#", "#", "#", "#"], ["#", " ", " ", " ", " ", " ", " ", " ", " ", "#"], ["#", " ", "#", "#", "#", "#", " ", " ", " ", "#"], ["#", " ", "#", " ", " ", "#", " ", " ", " ", "#"], ["@", " ", "#", " ", " ", "#", " ", " ", " ", "?"], ["#", " ", "#", " ", " ", "#", " ", " ", " ", "#"], ["#", " ", "#", " ", " ", " ", " ", " ", " ", "#"], ["#", " ", "#", "#", "#", "#", " ", " ", " ", "#"], ["#", " ", " ", " ", " ", " ", " ", " ", " ", "#"], ["#", "#", "#", "#", "#", "#", "#", "#", "#", "#"]]
##########
# #
# #### #
# # # #
@ # # ?
# # # #
# # #
# #### #
# #
##########
The primary problem in your code is you're using array references when you assign to the sub-arrays, which results in them all pointing to the same memory. I think you did that because you're used to another language where you have to predefine your array size. Ruby is more friendly than that, allowing us to append to an array easily. I used to <<
operator, but other methods exist to do the same thing; <<
is easier to see and understand.
Instead of opening the file, then using a while
loop to iterate over it, it's more idiomatic to use foreach
, which accomplishes the same thing and automatically closes the file when the block exits.
Also, instead of iterating over each line's characters, simply split the line using split('')
which will return an array of characters. Append that to @array
and move on.
Upvotes: 1
Reputation: 26690
The culprit is the way you are initializing the array in this line:
@array = Array.new(10,Array.new(10))
this is creating an array of 10 elements and it is initializing all of them with a pointer to another array of 10 elements. All the 10 elements will be sharing the same array. You can see a simplified example in here:
b = Array.new(3,Array.new(3))
b[0][0] = '00'
puts b # you'll see '00' printed 3 times!
One way to fix your program will be to create the array of rows first, then then initialize each row to a different array:
@array = Array.new(10)
for i in 0..9
# initialize each row to a unique array
@array[i] = Array.new(10)
end
# the rest of your code
Upvotes: 0