用一种更短更好的Ruby风格的方式来编写这个#valid_rook_moves方法,或者是一种替代算法?

osh3o9ms  于 2023-06-22  发布在  Ruby
关注(0)|答案(2)|浏览(114)

我正在尝试编写一个方法,它将输出Rook棋子可以合法移动的有效移动(不考虑棋盘上的任何其他棋子)。下面是我写的一个工作方法。它可以访问可读(和可写,因此.dup@x@y变量,其值是棋子在8x8网格棋盘上的零索引格式坐标的位置。但我认为这是一个非常冗长和丑陋的方法,有人能提供a)一个更好的语法方式来编写下面的内容,或者b)一个很好的替代方式来实现期望的输出。

def valid_rook_moves
    moves = []
    new_x = x.dup
    until new_x >= 7
      new_x += 1
      moves.push([new_x, y])
    end
    
    new_x = x.dup
    until new_x <= 0
      new_x -= 1
      moves.push([new_x, y])
    end
    
    new_y = y.dup
    until new_y >= 7
      new_y += 1
      moves.push([x, new_y]) 
    end
    
    new_y = y.dup
    until new_y <= 0
      new_y -= 1
      moves.push([x, new_y]) 
    end
    
    moves
  end

例如,在@x和@y都设置为0的情况下运行此方法输出:

[[1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0], [0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7]]
pgccezyw

pgccezyw1#

另一种方法...

VEC = (0..7).to_a.freeze
  #=> [0, 1, 2, 3, 4, 5, 6, 7]
def valid_rook_moves(x, y)
  ([x].product(VEC)).concat(VEC.product([y]))- [[x,y]]
end
valid_rook_moves(0, 0)
  #=> [[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7],
  #    [1, 0], [2, 0], [3, 0], [4, 0], [5, 0], [6, 0], [7, 0]]
valid_rook_moves(3, 5)
  #=> [[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 6], [3, 7],
  #    [0, 5], [1, 5], [2, 5], [4, 5], [5, 5], [6, 5], [7, 5]]

参见Array::new、Array#product和Array#concat。
注意,对于x = 3y = 5

[x].product(VEC)
  #=> [[3, 0], [3, 1], [3, 2], [3, 3], [3, 4], [3, 5], [3, 6], [3, 7]]
VEC.product([y])
  #=> [[0, 5], [1, 5], [2, 5], [3, 5], [4, 5], [5, 5], [6, 5], [7, 5]]

还有一个...

def valid_rook_moves(x, y)
  (0..7).each_with_object([]) do |i,a|
    a << [x,i] unless i == y
    a << [i,y] unless i == x
  end
end
valid_rook_moves(0, 0)
  #=> [[0, 1], [1, 0], [0, 2], [2, 0], [0, 3], [3, 0], [0, 4],
  #    [4, 0], [0, 5], [5, 0], [0, 6], [6, 0], [0, 7], [7, 0]]
valid_rook_moves(3, 5)
  #=> [[3, 0], [0, 5], [3, 1], [1, 5], [3, 2], [2, 5], [3, 3],
  #    [3, 4], [4, 5], [5, 5], [3, 6], [6, 5], [3, 7], [7, 5]]
y1aodyip

y1aodyip2#

这样的怎么样?

def range_excluding(value)
  [*0...value, *(value+1)...8]
end

def valid_rook_moves(current_x, current_y)
  ([current_x] * 7).zip(range_excluding(current_y)) +
    range_excluding(current_x).zip([current_y] * 7)
end

p valid_rook_moves(0, 0)
p valid_rook_moves(3, 5)

使用方法参数而不是使用当前位置传递位置的一个好处是,它提供了考虑未来移动序列的灵活性,而不是将您限制在下一个移动。

相关问题