我一直在寻找这个问题的答案,但无济于事。我试图弄清楚如何将它映射到bs后,从checkconsec中的行传递第一个数组。我试图使用xs但它不起作用。谁能看到我做错了什么?
import Data.Maybe
import Data.List
data Piece = Yellow | Red deriving Eq
type Column = [Piece]
type Board = [Column]
data BoardState = BS {
theBoard :: Board,
lastMove :: Piece,
numColumns :: Int,
numRows :: Int,
numToConnect :: Int}
---------- Make Move -----------
-- This function makes a move on a Boardstate, first checks if the column is full or if the column exists or not.
-- If true returns just a boardstate, if false returns nothing
makeMove :: BoardState -> Int -> Maybe BoardState
makeMove bs n = case ((checkLegal bs n) && (checkNotFull bs (columns bs !! (n-1)))) of
True -> Just (updateBoard bs n)
False -> Nothing
-- Checks if the move is legal, i.e. if the column to be moved into exists
checkLegal :: BoardState -> Int -> Bool
checkLegal bs i = case (i <= (numColumns bs) && (i /= 0)) of
True -> True
False -> False
-- Checks if the desired column is not full.
checkNotFull :: BoardState -> [Maybe Piece] ->Bool
checkNotFull bs a = case (length (catMaybes a)< (numRows bs)) of
True ->True
False -> False
-----------Parts of Board-----------
-- This function repeats nothing over and over.
repeatNothing :: Int -> [Maybe a]
repeatNothing m = replicate m Nothing
-- This function pads a list so that the resulting list is of the appropriate length
padN :: [a] -> Int -> [Maybe a]
padN xs n = (map Just xs) ++ repeatNothing (n - (length xs))
-- This function finds all of the columns of the board
columns :: BoardState -> [[Maybe Piece]]
columns bs = map (\col -> padN col (numRows bs)) (theBoard bs)
-- This function finds all the rows of the board
rows :: BoardState -> [[Maybe Piece]]
rows bs = map (\col -> padN col (numRows bs)) (transpose(theBoard bs))
-- This function will find the forward diagonals, but first gets the rows and the calls diagonals on the already padded
-- rows
diagonalsForward :: BoardState -> [[Maybe Piece]]
diagonalsForward bs = (diagonals (rows(bs)))
-- This function will find the backward diagonals, but first the rows are found, then the resulting grid is rotated
-- 90 degrees, followed by calling diagonals, which will then return the backwards diagonals, however in the wrong order
-- so then reverse is called on each list in order to get the correct order of the diagonals
diagonalsBackward :: BoardState -> [[Maybe Piece]]
diagonalsBackward bs = map reverse (diagonals((map reverse.transpose)(rows(bs))))
-- Because this section of code is cited above, the detailed axplanation of how it works is attached in another document
diagonals :: [[t]] -> [[t]]
diagonals [] = []
diagonals ([]:xss) = xss
diagonals xss = zipWith (++) (map ((:[]).head) xss ++ repeat[])
([] : (diagonals (map tail xss)))
-----------Check Win ---------------
checkWin :: BoardState -> [[Maybe Piece]]
checkWin bs = map (checkConsec bs) (rows bs)
checkConsec :: BoardState -> [[Maybe Piece]] -> [Maybe Piece]
checkConsec bs (x:xs) = helper (numToConnect bs) 1 (lastMove bs) x
helper :: Int -> Int -> Piece -> [Maybe Piece] -> [Maybe Piece]
helper = undefined
{-
helper numToCon cntr color (x:xs) = [];
helper numToCon cntr color (x:xs) = if cntr 0 then Nothing -- cntr initialized to 1
else case (color, x) of
(Just Yellow, Just Yellow) -> helper numToCon (cntr+1) color
(Just Yellow, Nothing) -> helper numToCon(cntr=1) color
(Just Yellow, Just Red) -> helper numToCon(cntr=1) color
(Just Red, Just Red) -> helper numToCon(cntr+1) color
(Just Red, Nothing) -> helper numToCon(cntr=1) color
(Just Red, Just Yellow) -> helper numToCon(cntr=1) color
-}
---------Update Board------------
-- This function splits a list into three separate pieces, the position of the split is determined by the parameter n
split3:: Int -> [Column] -> ([Column], Column, [Column])
split3 n xs = let (ys,(z:zs)) = (take (n-1) xs, drop (n-1) xs) in (ys, z, zs)
-- Calls split3 on the board
splitBoard :: BoardState -> Int -> [Column]
splitBoard bs n = addPiece bs (split3 n (theBoard bs))
-- Adds a piece to the desired column of the board
addPiece :: BoardState -> ([Column], Column, [Column]) -> [Column]
addPiece bs (x,y,z) = x ++ (y ++ [lastMove bs]):z
-- Updates the board to the new state, after adding a piece (or not) and updating the lastMove
updateBoard :: BoardState -> Int -> BoardState
updateBoard bs n = case (lastMove bs) of
Yellow -> BS {theBoard = splitBoard bs n,
lastMove = Red,
numColumns = numColumns bs,
numRows = numRows bs,
numToConnect = numToConnect bs}
Red -> BS {theBoard = splitBoard bs n,
lastMove = Yellow,
numColumns = numColumns bs,
numRows = numRows bs,
numToConnect = numToConnect bs}
**编辑:我已对此进行了编辑,以包含我的所有代码,希望这样可以更轻松地理解我的问题。我还修复了(据我所知)checkconsec和helper的类型。我现在唯一的错误是:
Couldn't match type ‘Maybe Piece’ with ‘[Maybe Piece]’
Expected type: [[[Maybe Piece]]]
Actual type: [[Maybe Piece]]
In the second argument of ‘map’, namely ‘(rows bs)’
In the expression: map (checkConsec bs) (rows bs)
Failed, modules loaded: none.
答案 0 :(得分:2)
函数的参数由空格分隔。 foo a b c
将三个参数应用于foo
,foo (a b) c
将两个参数应用于foo。函数应用程序具有最高优先级。我没有你剩下的代码,但我猜你的意思如下。
checkWin :: BoardState -> [[Maybe Piece]]
checkWin bs = map (checkConsec bs) (rows bs)
checkConsec :: BoardState -> [Maybe Piece] -> [Maybe Piece]
checkConsec bs = helper (numToConnect bs) 1 (lastMove bs) xs
helper :: Int -> Int -> Maybe Piece -> [Maybe Piece] -> [Maybe Piece]
helper = undefined