I have got a toughie for you.
I have a program that fills a 2d array with Tile objects of “w” type. Then the program selects a random point(center) in the array and attempts to turn all of the objects within a radius of 4 from the center. Somehow the program doesn’t do it and I think the issue is the math formula, but I cant find the mistake.
class Map
def initialize(d1,d2)
@data = Array.new(d1) { Array.new(d2)}
end
def [](x, y)
@data[x][y]
end
def x(x)
@data[x]
end
def y(y)
@data[y]
end
def []=(x, y, value)
@data[x][y] = value
end
end
# TILES
class Tile
# Types = ["l", "w", "r"]
attr_accessor :type
def initialize(type)
@type = type
end
def set(string)
@type = string
end
def to_s
@type
end
end
# REAL ACTION HERE
def generate
h = 20
w = 20
i = 0
worldmap = Map.new(20, 20)
while i < h do
n = 0
while n < w do
worldmap.[] = (i, n, Tile.new("w"))
n = n + 1
end
i = i + 1
end
gen(worldmap)
look(worldmap)
end
def look(map)
z = 0
b = 0
c = 0
string = " "
while b < 20 do
while z < 20 do
string = string + map.[](b, z).to_s
z = z + 1
end
b = b + 1
puts string
c = c + 1
end
end
def gen(map)
circle_amount = 1
i = 0
x = 0
y = 0
while i < circle_amount do
#select a center
cy = (rand(1..20))
cx = (rand(1..20))
center = map.[](cx,cy)
center.set("C")
radius = 4
puts cy.to_s + " " + cx.to_s
while y < 20
while x < 20
offsetY = y - cy
offsetX = x - cx
distance = offsetY**2 + offsetX**2
if distance <= radius**2 then
tile = map.[](y, x)
tile.set("l") # I DID IT
end
x = x + 1
end
y = y + 1
end
i = i + 1
end
end
generate
Here are the examples of output
wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww
wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww
wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww
wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww
wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww
wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww
wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwwwC:/Users/borya/Documents/NetBeansProjects/LearningPurporse/lib/main.rb:7:in
[]': >undefined method[]’ for nil:NilClass (NoMethodError)
I’d probably code this something closer to the below, although it’s a bit off-the cuff, and I preserved some of your original code even when it might not be how I would have done it.
Once you fix your math, you can end up with something like this:
Caveat: this code is above your skill-level, you may wish to translate it back into while-loops with the extra verbosity until you’re further along.
Boris, your original code was difficult to reason about, for a number of reasons, including the random indentation/formatting and simple syntax errors. It’s important to format your code consistently. Doing so enables both you, and others, to read it more easily.
It’s important to become familiar with the paradigms of the language you’re using. In general, if Ruby code has while-loops, counter increments, etc. when they’re not really used for anything other than indexing, it’s a code smell. Canonical Ruby tends towards a more functional style using
.each, blocks, and so on.You were correct that your math was wrong, although I suspect you weren’t aware just how wrong it was. Math like this is really easy to debug: do it by hand. Draw a grid. Take the program’s
(cx, cy)and do the calculation by hand. Do some sanity checks to make sure what you think you’re doing is (a) what you’re actually doing, and (b) sensical.For example, your distances were in the hundreds sometimes. Clearly that makes no sense when your grid is
(20, 20)… once you see that, the solution is obvious–you omitted a step.The same logic can be used for the rest of the math issues.
Play computer… be the computer. Follow its steps, on paper. There is no faster path to understanding than internalizing what’s actually happening “underneath the screen”.