patternMinor
Returning all possible player moves on a board
Viewed 0 times
movesallplayerpossiblereturningboard
Problem
Recently I started to learn Haskell. I did this by making exercises on the Internet. The problem of making these exercises is that I never know if I solved it the correct way. I currently wrote a function which I think looks really ugly, but I don't know how to improve it. I hope that someone could give me some tips to improve it.
In this exercice I need to make a tic-tac-toe-game. Wikipedia
The question of the function I wrote is as follows:
Write a function moves :: Player -> Board -> [Board] that, given the
current player and the current state of the board, returns all
possible moves that player can make expressed as a list of resulting
boards. (For now, you should continue making moves, even if one of the
players has already won.)
I wrote the following code:
I only want to improve this function: (Because the above code is part of bigger code)
```
moves :: Player -> Board -> [Board]
moves p ((a,b,c),(d,e,f), (g,h,i)) = (moves' a (((symbol p),b,c), (d,e,f), (g,h,i))) ++
(moves' b ((a,(symbol p),c), (d,e,f), (g,h,i))) ++
(moves' c ((a,b,(symbol p)), (d,e,f), (g,h,i))) ++
(moves' d ((a,b,c), ((symbol p),e,f), (g,h,i))) ++
(moves' e ((a,b,c), (d,(symbol p),f), (g,h,i))) ++
(moves' f ((a,b,c), (d,e,(symbol p)), (g,h,i))) ++
(moves' g ((a,b,c), (d,e,f), ((symbol p),h,i))) ++
(moves' h ((a,b,c), (d,e,f), (g,(symbol p),i))) ++
(moves' i ((a,b,c), (d,e,f), (g,h,(symbol p))))
moves' :
In this exercice I need to make a tic-tac-toe-game. Wikipedia
The question of the function I wrote is as follows:
Write a function moves :: Player -> Board -> [Board] that, given the
current player and the current state of the board, returns all
possible moves that player can make expressed as a list of resulting
boards. (For now, you should continue making moves, even if one of the
players has already won.)
I wrote the following code:
data Field = X | O | B
deriving (Eq, Ord)
instance Show Field where
show X = "X|" :: String
show O = "O|" :: String
show B = " |" :: String
symbol :: Player -> Field
symbol P1 = X
symbol P2 = O
type Row = (Field, Field, Field)
type Board = (Row, Row, Row)I only want to improve this function: (Because the above code is part of bigger code)
```
moves :: Player -> Board -> [Board]
moves p ((a,b,c),(d,e,f), (g,h,i)) = (moves' a (((symbol p),b,c), (d,e,f), (g,h,i))) ++
(moves' b ((a,(symbol p),c), (d,e,f), (g,h,i))) ++
(moves' c ((a,b,(symbol p)), (d,e,f), (g,h,i))) ++
(moves' d ((a,b,c), ((symbol p),e,f), (g,h,i))) ++
(moves' e ((a,b,c), (d,(symbol p),f), (g,h,i))) ++
(moves' f ((a,b,c), (d,e,(symbol p)), (g,h,i))) ++
(moves' g ((a,b,c), (d,e,f), ((symbol p),h,i))) ++
(moves' h ((a,b,c), (d,e,f), (g,(symbol p),i))) ++
(moves' i ((a,b,c), (d,e,f), (g,h,(symbol p))))
moves' :
Solution
Your function suffer from the retained structure (tuples of tuples). Tuples were not thought to be searched in or to be examined using recursion.
By converting it to a List on the fly, you may work with recursion and all the functions working on Lists (map, fold, etc.).
Here’s an example:
By converting it to a List on the fly, you may work with recursion and all the functions working on Lists (map, fold, etc.).
Here’s an example:
import Data.Maybe (catMaybes)
boardToList :: Board -> [Field]
boardToList ((a,b,c), (d,e,f), (g,h,i)) = [a,b,c,d,e,f,g,h,i]
ListToBoard :: [Field] -> Board
ListToBoard [a,b,c,d,e,f,g,h,i] = ((a,b,c), (d,e,f), (g,h,i))
ListToBoard _ = undefined
moves :: Player -> Board -> [Board]
moves player board = map ListToBoard $ catMaybes [boardSet i | i Just (start ++ [new] ++ end)
_ -> NothingCode Snippets
import Data.Maybe (catMaybes)
boardToList :: Board -> [Field]
boardToList ((a,b,c), (d,e,f), (g,h,i)) = [a,b,c,d,e,f,g,h,i]
ListToBoard :: [Field] -> Board
ListToBoard [a,b,c,d,e,f,g,h,i] = ((a,b,c), (d,e,f), (g,h,i))
ListToBoard _ = undefined
moves :: Player -> Board -> [Board]
moves player board = map ListToBoard $ catMaybes [boardSet i | i <- [0..8]]
where (new, lboard) = (symbol player, boardToList board)
boardSet i = case splitAt i lboard of
(start, B:end) -> Just (start ++ [new] ++ end)
_ -> NothingContext
StackExchange Code Review Q#98676, answer score: 2
Revisions (0)
No revisions yet.