所以我一直在努力解决过去几个小时打印数独游戏板的问题,我差不多完成了但是我已经陷入了最后一步。所以我所拥有的是一个数据板,表示为“列表列表”(即板= [[1,3,5,7,0,2,0,0,0],[3,4,5,... 。],...]
我已经能够使用以下功能打印出带格式的行:
line i s_board = intercalate " | " . map unwords . chunksOf 3 $ map show a
where
a = s_board!!i
所以通过像“0行”一样打电话,我会得到“1 3 5 | 7 0 2 | 0 0 0”,这是我需要的部分内容。接下来我尝试使用“do block”来输出我需要的板,看起来像这样:
print = do line 0 board
line 1 board
...
这甚至不会编译,当我做这样的事情时:
print = do
line 0 board
line 1 board
多次打印适当的列表,这是相当混乱的。我想继续努力,包括额外的格式化,比如在每三行之后打印一个字符串,例如“----------”,以完成电路板,但我甚至无法让其他东西工作对了。我很感激对这些问题的任何帮助。
答案 0 :(得分:7)
制作一个能让你的功能变得更容易,更优雅
板,制作一个大字符串,最后打印出来,而不是担心
通过do
块打印每一行。
所以,如果我们简化你的线显示函数来占用一块板:
showLine :: [Int] -> String
showLine = intercalate " | "
. map unwords
. chunksOf 3
. map show
然后,我们需要获取每一行的字符串表示并将它们全部放入
一起。这看起来非常像showLine
代码:
showBoard :: [[Int]] -> String
showBoard = intercalate "---------------------\n"
. map unlines
. chunksOf 3
. map showLine
使用示例板
-- Obviously not a valid sudoku board...
example :: [[Int]]
example = replicate 9 [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
*Main> putStrLn $ showBoard example
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
---------------------
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
---------------------
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
答案 1 :(得分:3)
您的原始尝试未编译,因为它违反了Haskell的布局规则。
第二个没有按照你的期望做,因为line n board
是一个列表,所以do
- 符号表示不确定,而不是IO动作的排序。如果您尝试输入类似
print :: IO ()
在你的函数之上(顺便提一下,print
在标准前奏中定义,你应该收到关于遮蔽它的警告),类型检查器会告诉你你的错误。如果你真的想打印出这样的电路板(虽然正如另一个答案所示,构建一个字符串然后将整个事情打印出来要好得多),你可以试试
printBoard :: IO ()
printBoard = do print $ line 0 board
print $ line 1 board
或打印整个板,
printBoard = mapM_ (print . showLine) board
其中showLine
与print
类似,但索引已被删除。