字符串 || Ruby 中的比较运算符
String || comparison operator in Ruby
我是 Ruby 的新手,正在尝试编写一个简单的 TicTacToe 游戏来练习。
我刚刚 运行 遇到一个关于玩家是否赢得比赛的评价的小问题。
本质上,该游戏的棋盘等于:
board = ["#",' ',' ',' ',' ',' ',' ',' ',' ',' ']
每次玩家移动时,他们的 "marker"(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" 标记 if 不能评估为真。应该注意的是,表达式的左侧仍然计算为我想要的值,例如:
board = ["#",' ',' ','O',' ','O',' ','O',' ',' ']
p [board[7],board[5],board[3]].uniq
>> ["O"]
我似乎无法理解为什么,对此任何指导都将不胜感激。
'X' || 'O'
只是说 X 或 O。因为任何字符串都是真实的,所以它总是 returns X。所以你说的任何地方 [('X' || 'O')]
,你真的刚才说了['X']
。
正因为如此,你只会检查整行 3 是否全是 X。
我真的不明白你是如何尝试测试这个的,但我觉得你最好 运行 将函数设置两次,先提交 X,然后再提交 O,如果它没有找到 X 作为赢家,而不是尝试同时检查两者。
或者您可以使用 return 'X'、'O' 或 nil 函数,然后您可以只使用 运行 函数一次。字符串 returned 表示谁赢了,如果为 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
@Nate 已经回答了你的问题。这是您编写方法的一种方式。
代码
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
就是safe navigation operator。如果 find
的块 returns nil
.
,它会导致忽略 .first
并返回 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
我是 Ruby 的新手,正在尝试编写一个简单的 TicTacToe 游戏来练习。
我刚刚 运行 遇到一个关于玩家是否赢得比赛的评价的小问题。
本质上,该游戏的棋盘等于:
board = ["#",' ',' ',' ',' ',' ',' ',' ',' ',' ']
每次玩家移动时,他们的 "marker"(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" 标记 if 不能评估为真。应该注意的是,表达式的左侧仍然计算为我想要的值,例如:
board = ["#",' ',' ','O',' ','O',' ','O',' ',' ']
p [board[7],board[5],board[3]].uniq
>> ["O"]
我似乎无法理解为什么,对此任何指导都将不胜感激。
'X' || 'O'
只是说 X 或 O。因为任何字符串都是真实的,所以它总是 returns X。所以你说的任何地方 [('X' || 'O')]
,你真的刚才说了['X']
。
正因为如此,你只会检查整行 3 是否全是 X。
我真的不明白你是如何尝试测试这个的,但我觉得你最好 运行 将函数设置两次,先提交 X,然后再提交 O,如果它没有找到 X 作为赢家,而不是尝试同时检查两者。
或者您可以使用 return 'X'、'O' 或 nil 函数,然后您可以只使用 运行 函数一次。字符串 returned 表示谁赢了,如果为 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
@Nate 已经回答了你的问题。这是您编写方法的一种方式。
代码
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
就是safe navigation operator。如果 find
的块 returns nil
.
.first
并返回 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