0

I'm building a tic tac toe game in Ruby. To determine if someone has won the game, I have a 2d array, check_array, of all of the possible sets you could use to win. I want to see if any of those arrays in check array have all the same elements. My javascript brain is having a hard time figuring out how to do this in Ruby. I'm confused without my curlies to delineate the block. I understand this sort of syntax:

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

But what if I need to use more than one line of logic for my any? logic. Could it look like this?

if check_array.any? do |row|
    row.uniq.count == 1
    <<some more code>>
  end
  @winner = @whos_turn
  winning
end 
2
  • The <<some more code>> should probably be outside of any?'s do end. Commented Nov 27, 2021 at 23:10
  • It could, but it depends on what you want to achieve. If the block passed to any? returns true, the if will be true. Since the block can contain as much code (and logic) as you want, you can do inside it what you want. Commented Nov 29, 2021 at 9:04

2 Answers 2

2

Just use a separate variable.

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

or, even better,

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

I don't know if the proposed nested do .. end syntax works, but the fact that I have no idea indicates to me that it's not very intuitive and should be refactored.

Sign up to request clarification or add additional context in comments.

1 Comment

Or with the second use check_array.any?(&method(:my_check)). Or use a lambda instead of a method and say check_array.any?(&my_check).
2

No matter how you do it, you certainly don't have to worry about the code being efficient. I therefore suggest you focus on code that is readable and easy to test, perhaps something along the following lines.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.