ruby动态类实例创建

时间:2014-12-17 21:10:18

标签: ruby oop

我将棋盘游戏编程为Ruby OOP学习练习的一部分。我试图创建一个游戏板,其中包含三排三排的九个空间。以下是当前无效代码的片段:

class Board

  def initialize()
    #dynamically creates instances of the Space class named @s1 through @s9 with #s 1-9 as the location parameter
    9.times do |x|
      x += 1
      y = "@s" + x.to_s
      instance_variable_set( y , x.to_s) = Space.new
    end
  end

  def print_board
    #prints a 3X3 grid containing each instance's location parameter
    puts "\n\n#{@s1.location}|#{@s2.location}|#{@s3.location}\n-----\n#{@s4.location}|#{@s5.location}|#{@s6.location}\n-----\n#{@s7.location}|#{@s8.location}|#{@s9.location}\n\n\n"
  end
end

class Space

  attr_accessor :location

  def initialize(location)
    @location = location
  end

end

board = Board.new
board.print_board

所需的输出是:

X|X|X
-----
X|X|X
-----
X|X|X

...但我一直收到与创建Space类实例有关的错误。我尝试了很多不同的事情,我无法记住它们。我知道必须有这样的方法来做到这一点,但我是Ruby的新手,而且让我难过。我知道可以创建9个单独的Space类实例,但这看起来既便宜又脏。

1 个答案:

答案 0 :(得分:0)

这是一个稍微重新编写的,更具Ruby风格的版本:

class Board
  def initialize
    @board = Array.new(9) do
      Space.new
    end
  end

  def move(x,y,set)
    @board[(x - 1) + (y - 1) * 3].location = set
  end

  def to_s
    @board.each_slice(3).collect do |row|
      row.join('|')
    end.join("\n------\n") + "\n"
  end
end

class Space
  attr_accessor :location

  def initialize(location = nil)
    @location = location || ' '
  end

  def to_s
    @location
  end
end

board = Board.new
puts board.to_s

board.move(1,2,'x')
puts board.to_s

值得注意的是一些技巧:

  • Array.new会考虑预先填充的条目数。
  • 可以为数组提供一个块来评估,该块提供用于默认条目的值。
  • each_slice抽出一组 N 条目进行处理。
  • collect将每一行转换为一个简单的字符串。
  • join将行与水平线组合在一起。
  • to_s是“show as string”的默认名称,除非另有说法,否则应该使用它。
  • Space初始化程序
  • 的默认值为nil
  • 不带参数的方法不需要括号,因此initializer优于initializer()

通过使用代表单元格的 9个变量,您使用instance_variable_set进行的方法更难维护并违反Zero, One or Infinity Rule。你需要的是一个理论上无限大小的变量,只有你必要时施加的约束才会受到限制。拥有多个变量会使迭代变得更加困难,使得作为参数传递变得不方便,并且通常会使应该简单的事情变得混乱。