Haskell在特定单元格中使用'#'构建“正方形”地图并计算空单元格

时间:2016-10-20 16:51:47

标签: haskell

我正在为一个班级做一个游戏,在一个任务中我需要做一个正方形(它是'地图')我所知道的是尺寸(每一边的大小)然后我想计算细胞我需要用'值'代替。

例如,尺寸为9的正方形将如下所示:

 # # # # # # # # #

 # _ _ v v v _ _ #

 # _ # V # v # _ #

 # v v v v v v v #

 # v # v # v # v #

 # v v v v v v v #

 # _ # v # v # _ #

 # _ _ v v v _ _ #

 # # # # # # # # #
  • 第一行和最后一行完全使用#(墙壁)
  • 第二行和倒数第二行:始终以#和两个空格_开头。
  • 第三行和倒数第三行:第二列和最后一列之前的空格,以及每第二列的#
  • 然后,我总是有一行,中间没有#,每2个空格有一行#

所以,我需要构建一个计算v s的函数。我在那张地图上,只收到Dimension :: Int(在这种情况下为9,函数calcV(函数的名称示例)将返回28)..

下面是我尝试过的代码。方块总是有奇数尺寸,等于或高于5,所以我做了5个案例,然后我预期的函数将计算我想要的所有其他可能的值。
但它给了我:

  

异常:ghci中的堆栈溢出

有谁知道我在这段代码中做错了什么?

calcv :: Int -> Int -> Int -> Int

calcv 5 _ _ = 0

calcv d l c    -- the l and c will be given has 1(first line/first column) (d will be the dimension)

        | (l==1) = 0 + calcv d (l+1) 1
        | (l==(d-1)) || (l==2) && (c==1) || (c==2) || (c==3) || (c==(d-2)) || (c==(d-1)) = 0 + calcv d l (c+1)
        | (l==(d-1)) || (l==2) && (c>3) && (c<(d-2)) = if even c then 1 + calcv d l (c+1) else calcv d l (c+1) 
        | (l==(d-1)) || (l==2) && (c==d) = calcv d (l+1) 1
        | (l==3) || (l==(d-2)) && (c==1) || (c==2) || (c==3) || (c==(d-2)) || (c==(d-1)) = calcv d l (c+1)
        | (l==3) || (l==(d-2)) && (c>3) && (c<(d-2)) = if even c then 1 + calcv d l (c+1) else calcv d l (c+1)
        | (l==3) || (l==(d-2)) && (c==d) = calcv d (l+1) 1
        | (l==d) = 0

1 个答案:

答案 0 :(得分:0)

当遇到这样的问题时,请尝试将其分解为更小的部分,并了解如何使用Haskell的现有工具(如列表推导,DateTime day = new DateTime(2016, 1, 15); // Friday List<dynamic> collection = new List<dynamic> { new { CustomerOnboardingId = "Item1", StartDate = new DateTime(2016,1,1) }, // Friday new { CustomerOnboardingId = "Item2", StartDate = new DateTime(2016,1,2) }, new { CustomerOnboardingId = "Item3", StartDate = new DateTime(2016,1,8) }, // Friday }; var result = (from item in collection where item.StartDate.DayOfWeek == day.DayOfWeek select item.CustomerOnboardingId).ToList(); // result = Item1, Item3 map和{{}来表达它。 1}})在编写递归函数之前。

首先,您要生成长度为filter的列表的正方形列表,其中每个单元格都是行和列索引的函数:

foldr

如果您不关心分隔行,或者您希望在整个地图中使用单个索引,也可以使用类型n定义它。您也可以使用makeMap :: Int -> [[Char]] makeMap n | even n || n < 5 = error "makeMap: invalid size" | otherwise = [[cellAt row col | col <- [1 .. n]] | row <- [1 .. n]] 而不是列表推导来定义它。我会留下这些作为练习。

现在,您可以通过提供Int -> [Char]

的实现来定义特定位置的单元格
map

我不会列举所有案例,因为这是一个家庭作业问题,但这里有一对可以让你开始:

cellAt

然后看起来你想要计算 where cellAt :: Int -> Int -> Char 个单元格的数量,你可以通过在地图上迭代来完成:

    -- Produce a border whenever row=1, col=1, row=n, or col=n.
    cellAt 1 _ = '#'
    cellAt _ 1 = '#'
    cellAt row col
      | row == n || col == n
      = '#'

    -- Handle other cases here.
      | ...

如果您的教师想要一个功能,那么一个好的练习就是将vcountV :: [[Char]] -> Int countV rows = sum [sum [1 | 'v' <- row] | row <- rows] calcV :: Int -> Int calcV n = countV (makeMap n) 的定义手动内联到countV。但是编写小而简单的函数通常更容易,你可以编写这些函数来解决更大的问题。