Строка ||оператор сравнения в Ruby - PullRequest
0 голосов
/ 04 марта 2019

Я новичок в Ruby и пытаюсь попрактиковаться, кодируя простую игру TicTacToe.

Я только что столкнулся с небольшой проблемой с оценкой, выиграл ли игрок в игре.

По сути, игра работает с доской, равной:

board = ["#",' ',' ',' ',' ',' ',' ',' ',' ',' ']

Каждый раз, когда игрок перемещает, его «маркер» (X или O) добавляется на доску, и есть функции, чтобы проверить,место занято, если это ничья или если игрок выиграл.

Так что временная доска может выглядеть примерно так:

board = ["#",' ',' ','O',' ','X',' ','O',' ',' ']

Моя проблема возникает при оценке, если кто-топобедил.Я написал для этого функцию: (первые 3 выражения проверяют горизонтальный выигрыш, следующие 3 вертикальный выигрыш и следующие 2 ищут выигрыши по диагонали.

def check_for_win(board)
  if [board[1],board[2],board[3]].uniq == [("X" || "O")] || [board[4],board[5],board[6]].uniq == [("X" || "O")] ||
    [board[7],board[8],board[9]].uniq == [("X" || "O")] || [board[1],board[4],board[7]].uniq == [("X" || "O")] ||
    [board[5],board[2],board[8]].uniq == [("X" || "O")] || [board[6],board[9],board[3]].uniq == [("X" || "O")] ||
    [board[1],board[5],board[9]].uniq == [("X" || "O")] || [board[7],board[5],board[3]].uniq == [("X" || "O")] 
    true
  else
    false
  end 
end 

Эта функция, кажется, оценивает, если естьявляется победителем с маркером "X", но для маркера "O", если не может быть оценено как true. Следует отметить, что левая часть выражения все еще оценивает то, что я хочу, например:

board = ["#",' ',' ','O',' ','O',' ','O',' ',' ']
p [board[7],board[5],board[3]].uniq 
>> ["O"]

Кажется, я не понимаю, почему, и любое направление по этому вопросу будет высоко оценено.

Ответы [ 2 ]

0 голосов
/ 04 марта 2019

@ Нейт ответил на ваш вопрос.Вот один способ, которым вы могли бы написать свой метод.

Код

def check_for_win(board)
  check_rows(board)                              ||
  check_rows(board.transpose)                    ||
  check_rows([[0,1,2].map { |i| board[i][i] }])  ||    
  check_rows([[0,1,2].map { |i| board[i][2-i] }])
end

def check_rows(rows)
  rows.find { |row| row.uniq.size == 1 && row.first != :_ }&.first
end

& в check_rows является оператором безопасной навигации ,Это приводит к игнорированию .first и возвращению nil, если блок find возвращает nil.

Примеры

check_for_win [[:O, :_, :O],
               [:O, :X, :_],
               [:X, :X, :X]]
  #=> :X

check_for_win [[:O, :_, :O],
               [:O, :X, :X],
               [:O, :X, :X]]
  #=> :O

check_for_win [[:X, :O, :X],
               [:O, :X, :O],
               [:O, :X, :X]]
  #=> :X

check_for_win [[:X, :O, :O],
               [:X, :O, :_],
               [:O, :X, :X]]
  #=> :O

check_for_win [[:X, :O, :X],
               [:X, :O, :O],
               [:O, :X, :X]]
  #=> nil

check_for_win [[:_, :_, :_],
               [:X, :O, :O],
               [:O, :X, :X]]
  #=> nil
0 голосов
/ 04 марта 2019

'X' || 'O' просто говорит X или O. И поскольку любая строка правдива, она всегда возвращает X. Поэтому в любом месте, где вы сказали [('X' || 'O')], вы действительно просто сказали ['X'].

Из-за этого вы всегда проверяете, является ли вся строка из 3 всей X.

Я не совсем понимаю, как вы пытаетесь это проверить, но я чувствую,как будто вам лучше запустить функцию дважды, сначала вручив X, а затем вручив O, если он не нашел X в качестве победителя, в отличие от попытки проверить оба сразу.

В качестве альтернативы вы могли бывместо этого сделайте так, чтобы функция возвращала 'X', 'O' или nil, и тогда вы могли бы запустить ее только один раз.Возвращенная строка будет тем, кто выиграл, и если она равна нулю, никто не выиграл.Я также рекомендовал бы сделать цикл для этого.Мне легче читать.

Вот как я бы решил эту проблему.

ROWS = [
  [1,2,3],
  [4,5,6],
  [7,8,9],

  [1,4,7],
  [2,5,8],
  [3,6,9],

  [1,5,9],
  [7,5,3],
]

def find_winner(board)
  ROWS.each do |row|
    # subtract 1 because the ROWS is 1-indexed (like a phone dial) but arrays are 0-indexed
    row_values = row.map { |v| board[v - 1] }
    return('X') if row_values.all?('X')
    return('O') if row_values.all?('O')
  end

  return(nil)
end


test1 = [
  'X', 'X', 'X',
  'O', 'X', 'O',
  'O', 'O', '',
]
puts "Winner of test1: #{find_winner(test1).inspect}"
"X"

test2 = [
  'X', '',  'X',
  'X', 'O', 'O',
  'X', 'O', 'X',
]
puts "Winner of test2: #{find_winner(test2).inspect}"
"X"

test3 = [
  'O', 'X', 'X',
  'O', 'X', 'O',
  'O', 'O', '',
]
puts "Winner of test3: #{find_winner(test3).inspect}"
"O"

test4 = [
  'O', 'X', 'O',
  'X', 'O', 'X',
  'O', 'O', 'X',
]
puts "Winner of test4: #{find_winner(test4).inspect}"
"O"

test5 = [
  'O', 'X', 'O',
  'O', 'X', 'O',
  'X', 'O', 'X',
]
puts "Winner of test5: #{find_winner(test5).inspect}"
nil
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...