You can also use Ruby's Matrix class to see if player p
wins. In the following, square[i][j]
is the player in row i
, column j
.
Code
require 'matrix'
def win?(square,p)
n = square.size
m = Matrix[*square]
pvec = Matrix.build(1,n){p}.row(0)
m.row_vectors.any? { |r| r == pvec } ||
m.column_vectors.any? { |c| c == pvec } ||
Matrix.rows([mVector[*m.each(:diagonal).to_a]).row(0) == pvec ||
n.times.all? { |i| square[i][n-i-1] == p }
end
Example
square = [[1,3,2],
[4,2,6],
[2,8,9]]
win?(square, 2) #=> true
win?([[1,3,2],[4,3,6],[2,3,9]], 3) #=> true
win?([[1,3,2],[3,3,3],[2,7,9]], 3) #=> true
win?([[1,3,2],[4,5,6],[7,8,9]], 1) #=> false
Explanation
pvec = Matrix.build(1,n){p}.row(0)
creates a vector for which every element is the value of the player argument p
(e.g., pvec # => Vector[2,2,2]
).
m.row_vectors.any? { |r| r == pvec }
determines if player p
wins in any row,
m.column_vectors.any? { |c| c == pvec }
determines if player p
wins in any column,
Matrix.rows([mVector[*m.each(:diagonal).to_a]).row(0) == pvec
determines if player p
wins on the main diagonal, and
(0...n).all? { |i| square[i][n-i-1] == p }
determines if player p
wins on the minor diagonal (top right to bottom left).
I was unable to find a way to check the minor diagonal using Matrix
class methods.