ruby 中关于实例方法的问题。

Questions about instance methods in ruby.

我有一项任务是使用 ruby classes 构建一个井字游戏。

到目前为止,我对编程和自学还是个新手,但被一个项目录取了,需要完善一些概念才能在游戏中脱颖而出。

我了解大部分概念并获得了适用于我的游戏的大部分规格文件,但我确实需要多次参考解决方案代码以帮助解决最后一点问题。

  1. 在创建板 class 时,创建了两个使用空数组定义的方法。我以前从未见过这个,想知道发生了什么。当我进入我的 IDE 并创建一个名为 [](空数组)和两个参数的方法时,我会收到一个错误(语法错误,期望输入结束)试图 运行 它.看来这一定是你只能在设置class时才能做的事情?

    我假设这些是 getter 和 setter 方法?

      def [](pos)
        row, col = pos
        grid[row][col]
      end
    
      def []=(pos, value)
        row, col = pos
        grid[row][col] = value
      end
    
  2. 上述代码中,grid是board的一个实例变量class。为什么可以在方法中使用实例变量而无需在其前面放置“@”符号 - (@grid,而不是 grid)。这有点令人困惑,因为对于普通方法,如果您在方法外部定义变量,则该方法无法识别它。为什么它在 classes 内部不同?

    #example 
    
    x = 6 
    
    def add(b)
      x + b
    end 
    
    => will return an error - local variable x is undefined.
    

下面是完整的公告板 class 以防理解和回答问题更有意义。谢谢!

class Board
  attr_reader :grid, :marks

  def initialize(grid = [])
    if grid.empty?
      @grid = Array.new(3) { Array.new(3) }
    else
      @grid = grid
    end
    @marks = [:X, :O]
  end

  def place_mark(pos, mark)
    grid[pos[0]][pos[1]] = mark
  end

  def [](pos)
    row, col = pos
    grid[row][col]
  end

  def []=(pos, value)
    row, col = pos
    grid[row][col] = value
  end

  def empty?(pos)
    grid[pos[0]][pos[1]].nil? ? true : false
  end

  def winner
    (grid + grid.transpose + diagnol).each do |win|
      return :X if win == [:X,:X,:X]
      return :O if win == [:O,:O,:O]
    end
    nil
  end

  def diagnol
    diag1 = [[0, 0], [1, 1], [2, 2]]
    diag2 = [[0, 2], [1, 1], [2, 0]]

    [diag1, diag2].map do |diag|
      diag.map {|row, col| grid[row][col]}
    end
  end

  def over?
    return true if grid.flatten.compact.size == 9 || winner
    return false if grid.flatten.compact.size == 0 || winner.nil?
  end


end
  1. 是的,这是 Board 上数组对象的 getter 和 setter。 (FWIW 我认为这样做的 Ruby 风格很差,所以我以后不会在你自己的代码中使用它。我认为这就是为什么你的 IDE 也有这个方法的问题.
  2. 您可以在没有 @ 的情况下使用 grid,因为 class 顶部的 attr_reader 声明。这为 class 上的 public 实例变量创建了一个只读变量。它有效地创建了一个名为:

    的方法
    def grid
      @grid
    end
    

    您将无法执行 grid = [],因为 attr_reader 仅创建一个只读方法。要创建读写访问器,您可以使用 attr_accessor。请记住,使用 attr_ 方法会使相关变量 public 在 class 上,因此如果您想保留一些内部内容,则不会使用它们。

有点晚了,但我也在调查这个并在网上找到了这个。显然,它是 类 的语法糖,带有类似网格的实例变量。

The Syntactic Sugar

These are all equivalent ways to get the bottom-left square:

board.grid[2][0]
board.[](2, 0)
board[2, 0] # syntactic sugar

The syntactic sugar allows us to call the Board#[] method with our arguments inside of the square brackets themselves rather than in parentheses following the square brackets.

Similarly, the following are equivalent ways to set the top-right square:

board.grid[0][2] = :x
board.[]=(0, 2, :x)
board[0, 2] = :x  # syntactic sugar

Naturally, if we bother to set up the special [] and []= methods, we'll use the syntactic sugar way. :)

可以从这里找到更多信息 link:

https://github.com/emgreen33/Practice/blob/master/W2D4/bracket-methods.md