Search code examples
arrayshaskelltic-tac-toe

Check if a player wins in a tic tac toe game


As a Haskell beginner, I have programmed a tic tac toe game. In first version of the game, I used 9 tuple to represent game board. I used to check winning conditions like this;

checkWinner :: Board -> Maybe Player
checkWinner (X,X,X,_,_,_,_,_,_) = Just Player1
checkWinner (_,_,_,X,X,X,_,_,_) = Just Player1
... same thing continues

Now I am trying to change my code to use arrays instead, but I can't figure out how to check for winning conditions. Lack of loops in haskell makes it hard for me to formulate an algorithm for this.

Here is my current code;

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 = 

How can I implement tileWins function in haskell?


Solution

  • 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]
    

    Explanation: for t to win one of the following must apply

    • there must exist a row such that in all column positions we find t
    • there must exist a column such that in all row positions we find t
    • in the main diagonal we find three ts
    • in the other diagonal we find three ts