You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Haskell技术问题:如何将指定字符串转换为[[Cell]]类型的Board

问题:将特定格式字符串转换为Haskell的Board类型结构

输入字符串格式如下:

",w84,w41,w56,w170,w56,w41,w84,/,,w24,w40,w17,w40,w48,,/ ,,,w16,w16,w16,,,/,,,,,,,,/,,,,,,,,/,,,,,,,,/,,,b1,b1,b1,,,/ ,,b3,b130,b17,b130,b129,,/,b69,b146,b131,b170,b131,b146,b69,"

需要转换为[[Cell]]类型的Board结构,目标格式示例:

[[Empty,Piece White 84,Piece White 41,Piece White 56,Piece White 170,Piece White 56,Piece White 41,Piece White 84,Empty],[Empty,Empty,Piece White 24,Piece White 40,Piece White 17,Piece White 40,Piece White 48,Empty,Empty],[Empty,Empty,Empty,Piece White 16,Piece White 16,Piece White 16,Empty,Empty,Empty],[Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty],[Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty],[Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty],[Empty,Empty,Empty,Piece Black 1,Piece Black 1,Piece Black 1,Empty,Empty,Empty],[Empty,Empty,Piece Black 3,Piece Black 130,Piece Black 17,Piece Black 130,Piece Black 129,Empty,Empty],[Empty,Piece Black 69,Piece Black 146,Piece Black 131,Piece Black 170,Piece Black 131,Piece Black 146,Piece Black 69,Empty]]

已定义的数据类型:

data Player = Black | White deriving Show
data Cell = Piece Player Int | Empty deriving Show
data Pos = Pos { col :: Char, row :: Int } deriving Show
type Board = [[Cell]]

当前问题:生成的是包含带引号字符串的列表,而非实际的Cell实例,示例如下:

[["Empty,Piece White 84,Piece White 41,Piece White 56,Piece White 170,Piece White 56,Piece White 41,Piece White 84,Empty"],
["Empty,Empty,Piece White 24,Piece White 40,Piece White 17,Piece White 40,Piece White 48,Empty,Empty"],
["Empty,Empty,Empty,Piece White 16,Piece White 16,Piece White 16,Empty,Empty,Empty"],
["Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty,Empty"]]


解决方案

核心思路是把字符串拆分为单个单元格的标记,再逐个转换为Cell类型,最后组合成二维的Board结构。

1. 单个单元格标记转Cell类型

编写解析函数,将单个标记(如w84、b1、空字符串)转换为对应的Cell:

parseCell :: String -> Cell
parseCell "" = Empty
parseCell (c:cs)
  | c == 'w' = Piece White (read cs)
  | c == 'b' = Piece Black (read cs)
  | otherwise = Empty  -- 处理异常输入

2. 分割输入字符串为行和单元格

输入字符串用/分隔每行,用逗号分隔每行内的单元格。先清理首尾引号,再完成分割:

splitOn :: Eq a => a -> [a] -> [[a]]
splitOn sep str = case break (== sep) str of
  (a, _:b) -> a : splitOn sep b
  (a, "") -> [a]

splitRows :: String -> [[String]]
splitRows s = map (splitOn ',') $ splitOn '/' $ filter (/= '"') s

如果允许引入外部库,也可以直接使用Data.List.Split中的splitOn函数简化代码。

3. 构建完整的Board

将每行的单元格标记列表转换为Cell列表,最终组合成Board:

buildBoard :: String -> Board
buildBoard = map (map parseCell) . splitRows

完整示例代码

data Player = Black | White deriving Show
data Cell = Piece Player Int | Empty deriving Show
data Pos = Pos { col :: Char, row :: Int } deriving Show
type Board = [[Cell]]

parseCell :: String -> Cell
parseCell "" = Empty
parseCell (c:cs)
  | c == 'w' = Piece White (read cs)
  | c == 'b' = Piece Black (read cs)
  | otherwise = Empty

splitOn :: Eq a => a -> [a] -> [[a]]
splitOn sep str = case break (== sep) str of
  (a, _:b) -> a : splitOn sep b
  (a, "") -> [a]

splitRows :: String -> [[String]]
splitRows s = map (splitOn ',') $ splitOn '/' $ filter (/= '"') s

buildBoard :: String -> Board
buildBoard = map (map parseCell) . splitRows

-- 测试用例
input :: String
input = ",w84,w41,w56,w170,w56,w41,w84,/,,w24,w40,w17,w40,w48,,/ ,,,w16,w16,w16,,,/,,,,,,,,/,,,,,,,,/,,,,,,,,/,,,b1,b1,b1,,,/ ,,b3,b130,b17,b130,b129,,/,b69,b146,b131,b170,b131,b146,b69,"

main :: IO ()
main = print $ buildBoard input

运行上述代码后,输出的就是符合要求的Board结构,每个元素都是实际的Cell实例,而非字符串。


内容的提问来源于stack exchange,提问作者Snusqx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 19:20:33