优化国际象棋车合法移动方法的Ruby实现:语法简化或算法改进
优化国际象棋车合法移动方法的Ruby实现:语法简化或算法改进
嘿,你的方法逻辑是完全正确的,但确实有点重复冗余——四个几乎一样的循环确实不够优雅。我来分享几种Ruby风格的简化方式,让代码更简洁易读,同时保持功能不变。
一、最直观的简化:利用Range与迭代器
Ruby的Range和高阶方法能帮我们摆脱重复的循环,直接生成目标坐标:
def valid_rook_moves # 生成同一列的所有合法移动(排除当前位置) column_moves = (0..7).reject { |nx| nx == @x }.map { |nx| [nx, @y] } # 生成同一行的所有合法移动(排除当前位置) row_moves = (0..7).reject { |ny| ny == @y }.map { |ny| [@x, ny] } # 合并两类移动并返回 column_moves + row_moves end
解释:
(0..7)直接生成棋盘上所有合法的坐标值(0到7的整数)reject过滤掉当前位置的坐标,避免把自身位置加入移动列表map把单个坐标值转换成[x,y]格式的位置数组- 最后合并列和行的移动结果,和你原方法的输出完全一致
比如当@x=0且@y=0时,这段代码会生成和你示例完全相同的输出,逻辑清晰且没有重复代码。
二、更紧凑的写法:用flat_map简化判断
如果喜欢更紧凑的代码,可以用flat_map把过滤和转换合并成一步:
def valid_rook_moves # 生成列移动:如果nx不是当前x,就生成坐标,否则返回空数组 column_moves = (0..7).flat_map { |nx| nx == @x ? [] : [[nx, @y]] } # 生成行移动:同理 row_moves = (0..7).flat_map { |ny| ny == @y ? [] : [[@x, ny]] } column_moves + row_moves end
flat_map会自动把嵌套的数组展开,省去了单独的过滤步骤,代码更短但依然保持可读性。
三、Ruby风格的组合写法:用product方法
还可以用product(笛卡尔积)来快速生成坐标组合,这种写法很有Ruby特色:
def valid_rook_moves [ # 列坐标组合:所有x值(除当前x)和当前y的乘积 (0..7).to_a.reject { |i| i == @x }.product([@y]), # 行坐标组合:当前x和所有y值(除当前y)的乘积 [[@x]].product((0..7).to_a.reject { |i| i == @y }) ].flatten(1) end
product方法会把两个数组的元素两两组合,正好符合我们“固定一个坐标,遍历另一个”的需求,最后用flatten(1)把嵌套的数组层级拉平,得到最终的移动列表。
为什么这些写法更好?
- 消除重复代码:原方法的四个循环逻辑几乎完全一致,优化后的代码把重复逻辑抽象成了通用的范围处理,维护起来更方便
- 可读性更高:代码直接表达了“生成列移动”“生成行移动”的意图,而不是用底层的循环步骤来实现
- Ruby风格:充分利用了Ruby的Enumerable模块方法,让代码更简洁优雅
备注:内容来源于stack exchange,提问作者jbk
相关产品推荐
相关产品推荐

