在阵列中找到3个元素的连续序列的最有效方法?

时间:2022-09-01 21:00:15

I have a 2D array:

我有一个2D数组:

      winning moves = [
        ["a1","a2", "a3"],
        ["b1","b2", "b3"],
        ["c1","c2", "c3"],
        ["a1","b1", "c1"],
        ["a2","b2", "c2"],
        ["a3","b3", "c3"],
        ["a1","b2", "c3"],
        ["a3","b2", "c1"],
        ]

Then I have 2 other arrays of variable arbitrary lengths

然后我有另外两个可变任意长度的数组

 Player X = ["c3", "b3", "a2", "a1", "c2" ]

 Player Y = ["b1", "c1", "a3", "b2"]

In the above scenario, Y is a sequence that exists in wm.

在上面的场景中,Y是存在于wm中的序列。

I have the following way that works but is this the best way?

我有以下方式可行,但这是最好的方法吗?

wm.each_with_index do |arr, index|

    puts "wm[#{index}]=#{arr}"
    winner = nil
    matchx = 0
    matchy = 0

    arr.each do|el|
        if(X.include?(el))
            matchx = matchx + 1
        end 
        if(Y.include?(el))
            matchy = matchy + 1
        end 
    end

    puts "matchx = #{matchx}"
    puts "matchy = #{matchy}"

    if(matchx == 3) 
        puts "winner = X"
    end

    if(matchy == 3) 
        puts "winner = Y"
    end

end 

OUTPUT of the above code is this:

上面代码的输出是这样的:

 wm[0]=["a1", "a2", "a3"]
 matchx = 2
 matchy = 1
 wm[1]=["b1", "b2", "b3"]
 matchx = 1
 matchy = 2
 wm[2]=["c1", "c2", "c3"]
 matchx = 2
 matchy = 1
 wm[3]=["a1", "b1", "c1"]
 matchx = 1
 matchy = 2
 wm[4]=["a2", "b2", "c2"]
 matchx = 2
 matchy = 1
 wm[5]=["a3", "b3", "c3"]
 matchx = 2
 matchy = 1
 wm[6]=["a1", "b2", "c3"]
 matchx = 2
 matchy = 1
 wm[7]=["a3", "b2", "c1"]
 matchx = 0
 matchy = 3
 winner =Y

2 个解决方案

#1


0  

If you are playing TicTacToe you can do the next which is more effective

如果你正在玩TicTacToe,你可以做下一个更有效的

For each row/column/diagonal(only 2) save 2 values: the number of mark each played did on that row/column/diagonal

对于每行/列/对角线(仅2)保存2个值:每个在该行/列/对角线上播放的标记数

Each move you update the values, if one of the value reach 3 , the player won the game. if player i play on (x,y) cell, the pseudo code code look like this

每次移动都会更新值,如果其中一个值达到3,则玩家赢得游戏。如果玩家在(x,y)单元格上播放,则伪代码代码如下所示

row[x][i]++
column[y][i]++
if (x == y) then diagonalA[i]++
if ((x + y) == 2) then diagonalB[i]++


if (row[x][i] == 3 || column[y][i] == 3 || 
      diagonalA[i] == 3 || diagonalB[i] == 3) 
           then 'player i has won'

EDIT

编辑

update the code to handle both diagonal

更新代码以处理两个对角线

#2


0  

I originally approached this using sets, but after seeing @vidaica's answer, it was obvious that using array intersections would be more straightforward. The latter is equivalent to using sets (with Set#subset?, for example), but avoids the need to convert between arrays and sets.

我最初使用套装接近这个,但在看到@ vidaica的答案之后,很明显使用阵列交叉点会更直接。后者等同于使用集合(例如,使用Set#subset?),但是避免了在数组和集合之间进行转换的需要。

   WM = [
      ["a1","a2", "a3"], ["b1","b2", "b3"], ["c1","c2", "c3"],
      ["a1","b1", "c1"], ["a2","b2", "c2"], ["a3","b3", "c3"],
      ["a1","b2", "c3"], ["a3","b2", "c1"],
      ]

    def find_winner(x_moves, y_moves)
      return "No winner" if x_moves.size < 3 
      3.upto(x_moves.size) do |i|
        if (w = win?(x_moves.first(i)))
          return "X wins with #{w}"
        elsif i <= y_moves.size && (w = win?(y_moves.first(i)))
          return "Y wins with #{w}"
        end
      end
      return "No winner"
    end     

    def win?(moves)     
      WM.find { |m| (m & moves).size == 3 }
    end

    puts find_winner([], [])
       # => No winner
    puts find_winner(["b1"], ["c3"])
       # => No winner
    puts find_winner(["b1", "c1", "a3", "b2"], ["c3", "b3", "a2", "a1"])
      # => X wins with ["a3", "b2", "c1"]
    puts find_winner(["b1", "c1", "a3", "b2"], ["c3", "b3", "a2"])
      # => X wins with ["a3", "b2", "c1"]
    puts find_winner(["b1", "a2", "a3", "c2", "c1"], ["c3", "b3", "a1", "b2"])
      # => Y wins with ["a1", "b2", "c3"]
    puts find_winner(["b1", "a2", "b2", "c3", "c1"], ["a1", "b3", "c2", "a3"])
      # => No winner

#1


0  

If you are playing TicTacToe you can do the next which is more effective

如果你正在玩TicTacToe,你可以做下一个更有效的

For each row/column/diagonal(only 2) save 2 values: the number of mark each played did on that row/column/diagonal

对于每行/列/对角线(仅2)保存2个值:每个在该行/列/对角线上播放的标记数

Each move you update the values, if one of the value reach 3 , the player won the game. if player i play on (x,y) cell, the pseudo code code look like this

每次移动都会更新值,如果其中一个值达到3,则玩家赢得游戏。如果玩家在(x,y)单元格上播放,则伪代码代码如下所示

row[x][i]++
column[y][i]++
if (x == y) then diagonalA[i]++
if ((x + y) == 2) then diagonalB[i]++


if (row[x][i] == 3 || column[y][i] == 3 || 
      diagonalA[i] == 3 || diagonalB[i] == 3) 
           then 'player i has won'

EDIT

编辑

update the code to handle both diagonal

更新代码以处理两个对角线

#2


0  

I originally approached this using sets, but after seeing @vidaica's answer, it was obvious that using array intersections would be more straightforward. The latter is equivalent to using sets (with Set#subset?, for example), but avoids the need to convert between arrays and sets.

我最初使用套装接近这个,但在看到@ vidaica的答案之后,很明显使用阵列交叉点会更直接。后者等同于使用集合(例如,使用Set#subset?),但是避免了在数组和集合之间进行转换的需要。

   WM = [
      ["a1","a2", "a3"], ["b1","b2", "b3"], ["c1","c2", "c3"],
      ["a1","b1", "c1"], ["a2","b2", "c2"], ["a3","b3", "c3"],
      ["a1","b2", "c3"], ["a3","b2", "c1"],
      ]

    def find_winner(x_moves, y_moves)
      return "No winner" if x_moves.size < 3 
      3.upto(x_moves.size) do |i|
        if (w = win?(x_moves.first(i)))
          return "X wins with #{w}"
        elsif i <= y_moves.size && (w = win?(y_moves.first(i)))
          return "Y wins with #{w}"
        end
      end
      return "No winner"
    end     

    def win?(moves)     
      WM.find { |m| (m & moves).size == 3 }
    end

    puts find_winner([], [])
       # => No winner
    puts find_winner(["b1"], ["c3"])
       # => No winner
    puts find_winner(["b1", "c1", "a3", "b2"], ["c3", "b3", "a2", "a1"])
      # => X wins with ["a3", "b2", "c1"]
    puts find_winner(["b1", "c1", "a3", "b2"], ["c3", "b3", "a2"])
      # => X wins with ["a3", "b2", "c1"]
    puts find_winner(["b1", "a2", "a3", "c2", "c1"], ["c3", "b3", "a1", "b2"])
      # => Y wins with ["a1", "b2", "c3"]
    puts find_winner(["b1", "a2", "b2", "c3", "c1"], ["a1", "b3", "c2", "a3"])
      # => No winner