0

私はあなたのためにタフな人を持っています。

2D配列を「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)

4

1 に答える 1

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ループ、カウンターインクリメントなどがあり、それらが実際にはインデックス作成以外の目的で使用されていない場合、それはコードの臭いです。.eachCanonical Rubyは、ブロックなどを使用して、より機能的なスタイルにする傾向があります。

あなたはあなたの数学が間違っていたということは正しかったが、あなたはそれがどれほど間違っていたかを知らなかったのではないかと思う。このような数学は本当に簡単にデバッグできます。手動で実行してください。グリッドを描画します。プログラム(cx, cy)を取り、手作業で計算します。いくつかの健全性チェックを実行して、自分が行っていると思うことが(a)実際に行っていること、および(b)官能的であることを確認します。

たとえば、あなたの距離は時々数百になりました。グリッドが...である場合、それは明らかに意味がありません(20, 20)。一度それを見ると、解決策は明白です。ステップを省略しました。

同じ論理を残りの数学の問題に使用することができます。

コンピューターを再生する...コンピューターになります。紙の上で、その手順に従ってください。「画面の下」で実際に起こっていることを内部化することほど、理解へのより速い道はありません。

于 2012-10-05T21:50:45.387 に答える