更改数组中对象的属性,这是一个数学问题

时间:2012-10-05 21:14:18

标签: ruby

我为你做了一件事。

我有一个用“w”类型的Tile对象填充二维数组的程序。然后程序选择数组中的随机点(中心)并尝试从中心转动半径为4的所有对象。不知怎的,程序没有这样做,我认为问题是数学公式,但我找不到错误。

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 

以下是输出

的示例
  

wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww   wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww   wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww   wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww   wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww   wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww   wwwwwwwwwwwwlllllwww wwwwwwwwwwwwlllllwww

     

C:/Users/borya/Documents/NetBeansProjects/LearningPurporse/lib/main.rb:7:in []': >undefined method []'for nil:NilClass(NoMethodError)

1 个答案:

答案 0 :(得分:2)

 > m = Map.new(5,5)
 => #<Map:0x007fa5d9838fc0 @data=[[nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil]]> 
ruby-1.9.3-p125 :040 > m[1,1]="hi"
(x=1, y=1) = hi
@data[x][y]=hi
 => "hi" 
 > m
 => #<Map:0x007fa5d9838fc0 @data=[[nil, nil, nil, nil, nil], [nil, "hi", nil, nil, nil], [nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil], [nil, nil, nil, nil, nil]]> 

我可能会将这些内容编写得更接近下面的内容,虽然它有点偏离袖口,但我保留了一些原始代码,即使它可能不是我原来的代码。

class Map
  attr_reader :data, :x, :y

  def initialize(x, y)
    @x = x
    @y = y
    @data = Array.new(x) { Array.new(y) }
  end

  def set(&block)
    (0..x-1).each do |i|
      (0..y-1).each do |j|
        result = yield i, j, @data[i][j]
        @data[i][j] = result if result
      end
    end
  end

  def [](x, y)
    @data[x][y]
  end

  def []=(x, y, value)
    @data[x][y] = value
  end

  def dump
    (0..x-1).each do |i|
      string = ""
      (0..y-1).each do |j|
        string += "#{self[i, j]} "
      end
      puts string
    end
  end
end

def generate 
  map = Map.new(20, 20)
  map.set { |x, y, at| Tile.new('w') }
  gen(map)
end

def gen(map)
  3.times do |i|
    cy = rand(0..map.x-1)
    cx = rand(0..map.y-1)
    puts "cx=#{cx}, cy=#{cy}"
    map[cx, cy].set('C')
    map.dump

    radius = 3.0

    map.set do |x, y, at|
      offsetX = x - cx
      offsetY = y - cy
      distance = Math.sqrt(offsetY**2 + offsetX**2)
      distance.abs <= radius ? '.' : false
    end

    puts ''
    map.dump
  end
end

一旦你修好了数学,你就可以得到这样的结论:

w w w w w w w w w w w w w w w w w . w w 
w w w w w w w w w w w w w w w . . . . . 
w w w w w w w w w w w w w w w . . . . . 
w w w w w w w w w w w w w w . . . . . . 
w w w w w . w w w w w w w w w . . . . . 
w w w . . . . . w w w w w w w . . . . . 
w w w . . . . . w w w w w w w w w . w w 
w w . . . . . . . w w w w w w w w w w w 
w w w . . . . . w w w w w w w w w w w w 
w w w . . . . . w w w w w w w w w w w w 
w w w w w . w w w w w w w w w w w w w w 
w w w w w w w w w w w w w w w w w w w w 
w w w w w w w w w w w w w w w w w w w w 
w w w w w w w w w w w w w w w w w w w w 
w w w w w w w w w w w w . w w w w w w w 
w w w w w w w w w w . . . . . w w w w w 
w w w w w w w w w w . . . . . w w w w w 
w w w w w w w w w . . . . . . . w w w w 
w w w w w w w w w w . . . . . w w w w w 
w w w w w w w w w w . . . . . w w w w w 

警告:此代码高于您的技能等级,您可能希望将其转换为带有额外冗长的while循环,直到您继续进行。

Boris,由于多种原因,包括随机缩进/格式化和简单的语法错误,您的原始代码难以推理。一致地格式化代码非常重要。这样做可以让您和其他人更轻松地阅读它。

熟悉您正在使用的语言范例非常重要。一般来说,如果Ruby代码具有while循环,计数器增量等,当它们实际上不用于索引以外的任何东西时,它就是代码味道。 Canonical Ruby倾向于使用.each,块等更具功能性的风格。

你的数学错误是对的,虽然我怀疑你不知道它有多么错误。像这样的数学真的易于调试:手工完成。画一个网格。拿着程序的(cx, cy)并手动进行计算。做一些健全性检查,以确保你所做的你正在做的是(a)你实际做了什么,(b)有感觉。

例如,您的距离有时会达到数百。显然,当你的网格为(20, 20)时,没有有意义......一旦你看到,解决方案很明显 - 你省略了一步。

同样的逻辑可以用于其余的数学问题。

玩电脑......是电脑。按照纸上的步骤操作。没有更快的理解途径,而是内化“屏幕下方”实际发生的事情。