我可以在集合上使用模式匹配吗?
我有一个代表一个井字棋盘的网格。
如何使用模式匹配来识别“X”或“O”的条纹?
到目前为止,我构建了一个这样的网格:
// ----------------
// 0 | 1 | 2 |
// ----------------
// 3 | 4 | 5 |
// ----------------
// 6 | 7 | 8 |
// ----------------
type Marker =
| X = 0
| O = 1
| NULL = 3
let cells = [0..8]
let grid = [for cell in cells -> (cell, Marker.NULL)]
let streakExists =
match grid with
| ???
| ???
所以我想使用模式匹配来识别如下所示的条纹:
//如果网格。[.. 2]都有X
//或grid。[3..5]都有X
//或grid。[6..8]都有X
//返回true
// -----------------
//如果grid。[0; 3; 6;]都有X
//或grid。[1; 4; 5]都有X
//或grid。[2; 5; 8]都有X
//返回true
// ------------------
//如果grid。[0; 4; 8;]都有X
//返回true
注意:
我正在学习F#的基础知识。 如果这个问题显而易见,请原谅我。
答案 0 :(得分:4)
你可以在集合上使用模式匹配,但是在很多情况下你必须覆盖tic-tac-toe,因此它可能不是最好的选择。
如果我稍微简化你的代码(使用一个有区别的联合而不是enum并只使用一个有区别的联合的值列表),它将如下所示:
type Marker =
| X
| O
| NULL
let grid = [ for cell in 0 .. 8 -> NULL ]
let streakExists =
match grid with
| [X;X;X;_;_;_;_;_;_]
| [_;_;_;X;X;X;_;_;_]
| [_;_;_;_;_;_;X;X;X] -> "X wins"
| _ -> "Not sure"
这样可行,但您可以看到覆盖所有案例的难度。如果我想解决同样的问题,我可能会以不同的方式写出来。您可以创建一个列表,列出网格中所有可能的条纹:
let streaks =
[ for row in [0;3;6] do // Generate one streak for each row
yield [row;row+1;row+2]
for col in [0;1;2] do // Generate one streak for each column
yield [col;col+3;col+6]
yield [0;4;8] // Explicitly add two
yield [2;4;6] ] // diagonal streaks
现在,您可以通过测试是否存在任何条纹(来自grid
)来检查streaks
是否包含连胜,以便所有指定索引的值均为X
或{{1 }}。这应该很容易与O
和List.forall
。
答案 1 :(得分:2)
正如Tomas所写,将SELECT names
FROM Workers
WHERE names LIKE (??r -------The name can have 22 characters though.
类型简化为歧视联盟会更容易:
Marker
此外,由于电路板太小,您可以将其保存为八个值的列表:
type Marker = X | O | NULL
我同意Tomas的看法,模式匹配可能不是解决这个问题的最佳方法,但为了完整起见,你可以制作有点明显地传达他们匹配的模式的匹配: / p>
let grid = List.init 8 (fun _ -> NULL)
答案 2 :(得分:1)
如果您直接将模式匹配到网格,我不确定语法是否会非常好,您的选项是:
let streakExists grid =
match grid with
|[Marker.X; Marker.X; Marker.X; _; _; _; _; _; _] -> true
|[_; _; _; Marker.X; Marker.X; Marker.X; _; _; _] -> true
|[_; _; _; _; _; _; Marker.X; Marker.X; Marker.X] -> true
...
| _ -> false
或
let streakExists grid =
match grid with
|Marker.X :: Marker.X :: Marker.X :: _ -> true
| _ :: _ :: _ :: Marker.X :: Marker.X :: Marker.X :: _ -> true
| _ :: _ :: _ :: _ :: _ :: _ :: Marker.X :: Marker.X :: Marker.X :: [] -> true
...
| _ -> false
(这个选项并不理想,因为它可能会在大小不正确的网格上返回true,所以不要使用它,我只想演示语法。)
您可以创建一个函数来模式匹配3个集合中的列表:
let streakExists grid =
let checkListOf3 list =
match list with
|[Marker.X; Marker.X; Marker.X] -> true
|_ -> false
if grid.[0..2] |> checkListOf3 then true
elif grid.[3..5] |> checkListOf3 then true
elif grid.[6..8] |> checkListOf3 then true
...
else false
修改
你可以将最后一种方法与Tomas使用他的streaks
建议的方法结合起来:
let streakExists grid =
let checkListOf3 list =
match list with
|[Marker.X; Marker.X; Marker.X] -> true
|_ -> false
streaks |> List.exists (List.map (fun i -> List.item i grid) >> checkListOf3)