如何使用数组方法作为 Ruby 中 if 语句的条件

How to use an array method as condition for if statement in Ruby

我正在 Ruby 中构建一个井字游戏。为了确定是否有人赢得了比赛,我有一个二维数组 check_array,其中包含您可以用来获胜的所有可能集合。我想看看检查数组中的任何数组是否具有所有相同的元素。我的 javascript 大脑很难弄清楚如何在 Ruby 中做到这一点。没有我的卷发来描绘街区,我很困惑。我理解这种语法:

if check_array.any? {|row|row.uniq.count == 1}
  @winner = @whos_turn
  winning
end 

但是如果我需要为我的 any 使用不止一行逻辑怎么办?逻辑。可以像这样吗?

if check_array.any? do |row|
    row.uniq.count == 1
    <<some more code>>
  end
  @winner = @whos_turn
  winning
end 

只需使用一个单独的变量。

match = check_array.any? do |row|
  row.uniq.count == 1
  <<some more code>>
end
if match 
  @winner = @whos_turn
  winning
end 

或者,更好的是,

def my_check(row)
  row.uniq.count == 1
  <<some more code>>
end

if check_array.any? { |x| my_check(x) }
  @winner = @whos_turn
  winning
end

我不知道建议的嵌套 do .. end 语法是否有效,但我不知道的事实表明它不是很直观,应该重构。

不管你怎么做,你当然不用担心代码的效率问题。因此,我建议您专注于可读且易于测试的代码,也许是以下几行。

game = [[:X, :O, :X],
        [:O, :X, :O], 
        [:O, :X, :X]]
def winner(game)
  return :X if player_win?(game, :X)
  return :O if player_win?(game, :O)
  :NO_WINNER
end
def player_win?(game, mark)
  row_win?(game, mark) || col_win?(game, mark) || diag_win?(game, mark)
end
def row_win?(game, mark)
  game.any? { |row| row == [mark, mark, mark] }
end
def col_win?(game, mark)
  row_win?(game.transpose, mark)
end
def diag_win?(game, mark)
  3.times.all? { |i| game[i][i] == mark } ||
  3.times.all? { |i| game[i,2-i] == mark } 
end

game = [[:X, :O, :X],
        [:O, :X, :O], 
        [:O, :X, :X]]
winner(game)
  #=> :X
game = [[:X, :O, :X],
        [:O, :O, :O], 
        [:X, :X, :_]]
winner(game)
  #=> :O
game = [[:X, :O, :X],
        [:O, :O, :X], 
        [:X, :X, :O]]
winner(game)
  #=> :NO_WINNER