1

I made a Tic-Tac-Toe game in Ruby. The method below checks for a winner in the vertical columns.

How do I make it so that this method can be applied to boards of different sizes, like 4x4, 6x6?

def vertical_check(array)

  result = nil

  if (array[0][0] == "X" && array[1][0] == "X" && array[2][0] == "X") ||
    (array[0][1] == "X" && array[1][1] == "X" && array[2][1] == "X") ||
    (array[0][2] == "X" && array[1][2] == "X" && array[2][2] == "X")

    result = "X"

  elsif (array[0][0] == "O" && array[1][0] == "O" && array[2][0] == "O") ||
    (array[0][1] == "O" && array[1][1] == "O" && array[2][1] == "O") ||
    (array[0][2] == "O" && array[1][2] == "O" && array[2][2] == "O")

    result = "O"
  else
    result = nil
  end
  return result
end

The following is a failed attempt:

def vertical_check_x(array)

  result = nil

  index = 0
  index2 = 0

  until result != nil || index == array.length

    while array[index][index2] == "X"
      index += 1
    end

    if index == array.length
      result = "X"
    else
      result = nil
      index = array.length
    end

    index2 += 1
  end

  return result
end

def vertical_check_o(array)

  result = nil

  index = 0
  index2 = 0
  until result != nil || index == array.length

    while array[index][index2] == "O"
      index += 1
    end

    if index -1 == array.length
      result = "O"
    else
      result = nil
      index = array.length
    end

    index2 += 1
  end

  return result
end

def vertical_check(array)

  result = vertical_check_x(array)

  if result == nil
    result = vertical_check_o(array)
  end

  return result
end
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Paly CS
  • 19
  • 3
  • do you notice a pattern with the array indices? – code11 Oct 03 '16 at 18:25
  • http://stackoverflow.com/questions/18548265/testing-tic-tac-toe-win-condition – Zain Zafar Oct 03 '16 at 20:42
  • Your code formatting needs help. Please put in the effort to format your questions for readability. Not only does it help us answer you, but they help those who search for similar solutions in the future, which is the primary goal of SO. – the Tin Man Oct 04 '16 at 00:39

1 Answers1

4

To quickly find a winner in given array, count the number of unique elements, confirm that there is only one unique element and if it is only X or O:

def winner arr
  return arr[0] if arr.uniq.length == 1 && ['X', 'O'].include?(arr[0])
  nil
end

The next problem is selecting the rows, columns and diagonals for an nxn array.

Rows are easy:

rows = arr.map {|row| row}

Columns are as follows - you select elements with the same index for each row:

cols = n.times.collect {|i| arr.map {|row| row[i]}}

Next are diagonals. There are two diagonals, one starts from leftmost corner and the other from the rightmost.

The leftmost diagonal has the sequence as:

(0, 0) -> (1, 1) -> (2, 2) ....

See the pattern?

diag = n.times.collect {|i| arr[i][i]}

The rightmost diagonal has pattern that goes like this (for a 3x3):

(0, 2) -> (1, 1) -> (2, 0)

For a 4x4, it's like this:

(0, 3) -> (1, 2) -> (2, 1) -> (3, 0)

So, the pattern for an nxn is:

(0, n-1-0) -> (1, n-1-1) -> (2, n-1-2) -> ... (i, n-1-i) ... -> (n-1, 0)

So:

diag = n.times.collect {|i| arr[i][n - 1 - i]}

Now, you can just do something like:

w = rows.map {|r| winner r}.compact[0]

for each array to get the winner.

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
rohit89
  • 5,745
  • 2
  • 25
  • 42