检查玩家是否在井字游戏中获胜
Check if a player wins in a tic tac toe game
作为 Haskell 初学者,我编写了一款井字游戏。在游戏的第一个版本中,我使用 9 元组来表示游戏板。我曾经这样检查获胜条件;
checkWinner :: Board -> Maybe Player
checkWinner (X,X,X,_,_,_,_,_,_) = Just Player1
checkWinner (_,_,_,X,X,X,_,_,_) = Just Player1
... same thing continues
现在我正在尝试更改我的代码以改为使用数组,但我不知道如何检查获胜条件。 haskell 中缺少循环让我很难为此制定算法。
这是我当前的代码;
import Data.Array
data Tile = EmptyTile | X | O
data Player = Player1 | Player2
showTile :: Tile -> String
showTile EmptyTile = " "
showTile X = "X"
showTile O = "O"
type Board = Array (Int,Int) Tile
emptyBoard :: Board
emptyBoard = array ((1,1),(3,3)) [((x,y), EmptyTile) | x <- [1,2,3], y <- [1,2,3]]
put :: Board -> Tile -> Int -> Int -> Maybe Board
put b t x y = case b!(x,y) of
EmptyTile -> Just (b // [((x,y), t)])
_ -> Nothing
p1wins, p2wins :: Board -> Bool
p1wins b = tileWins b X
p2wins b = tileWins b O
-- will be called with a board and either x or o
-- and it will tell whether that tile wins
tileWins :: Board -> Tile -> Bool
tileWins b t =
如何在 haskell 中实现 tileWins
功能?
如果你想对元组做同样的事情,你会做:
if ((b ! 0 ! 0) == t
&& (b ! 0 ! 1) == t
&& (b ! 0 ! 2) == t)
|| ((b ! 1 ! 0) == t
&& (b ! 1 ! 1) == t
...
您可以使用获胜指数列表并对其进行处理,从而节省几行代码。
此外,正如@chi 指出的(我的猜测),tileWins
、p1wins
和 p2wins
应该 return 和 Bool
.
data Tile = EmptyTile | X | O deriving Eq
tileWins :: Board -> Tile -> Bool
tileWins b t =
any (\row -> all (\col -> b!(row,col) == t) [1..3]) [1..3] ||
any (\col -> all (\row -> b!(row,col) == t) [1..3]) [1..3] ||
all (\rc -> b!(rc,rc) == t) [1..3] ||
all (\rc -> b!(rc,4-rc) == t) [1..3]
说明:要t
赢得以下其中一项必须申请
- 必须存在一个
row
使得在所有 col
umn 个位置我们找到 t
- 必须存在一个
col
umn 使得在所有 row
个位置我们找到 t
- 在主对角线上我们找到三个
t
s
- 在另一条对角线上我们找到三个
t
s
作为 Haskell 初学者,我编写了一款井字游戏。在游戏的第一个版本中,我使用 9 元组来表示游戏板。我曾经这样检查获胜条件;
checkWinner :: Board -> Maybe Player
checkWinner (X,X,X,_,_,_,_,_,_) = Just Player1
checkWinner (_,_,_,X,X,X,_,_,_) = Just Player1
... same thing continues
现在我正在尝试更改我的代码以改为使用数组,但我不知道如何检查获胜条件。 haskell 中缺少循环让我很难为此制定算法。
这是我当前的代码;
import Data.Array
data Tile = EmptyTile | X | O
data Player = Player1 | Player2
showTile :: Tile -> String
showTile EmptyTile = " "
showTile X = "X"
showTile O = "O"
type Board = Array (Int,Int) Tile
emptyBoard :: Board
emptyBoard = array ((1,1),(3,3)) [((x,y), EmptyTile) | x <- [1,2,3], y <- [1,2,3]]
put :: Board -> Tile -> Int -> Int -> Maybe Board
put b t x y = case b!(x,y) of
EmptyTile -> Just (b // [((x,y), t)])
_ -> Nothing
p1wins, p2wins :: Board -> Bool
p1wins b = tileWins b X
p2wins b = tileWins b O
-- will be called with a board and either x or o
-- and it will tell whether that tile wins
tileWins :: Board -> Tile -> Bool
tileWins b t =
如何在 haskell 中实现 tileWins
功能?
如果你想对元组做同样的事情,你会做:
if ((b ! 0 ! 0) == t
&& (b ! 0 ! 1) == t
&& (b ! 0 ! 2) == t)
|| ((b ! 1 ! 0) == t
&& (b ! 1 ! 1) == t
...
您可以使用获胜指数列表并对其进行处理,从而节省几行代码。
此外,正如@chi 指出的(我的猜测),tileWins
、p1wins
和 p2wins
应该 return 和 Bool
.
data Tile = EmptyTile | X | O deriving Eq
tileWins :: Board -> Tile -> Bool
tileWins b t =
any (\row -> all (\col -> b!(row,col) == t) [1..3]) [1..3] ||
any (\col -> all (\row -> b!(row,col) == t) [1..3]) [1..3] ||
all (\rc -> b!(rc,rc) == t) [1..3] ||
all (\rc -> b!(rc,4-rc) == t) [1..3]
说明:要t
赢得以下其中一项必须申请
- 必须存在一个
row
使得在所有col
umn 个位置我们找到t
- 必须存在一个
col
umn 使得在所有row
个位置我们找到t
- 在主对角线上我们找到三个
t
s - 在另一条对角线上我们找到三个
t
s