首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell在特定的单元格中构建带有#s的“正方形”映射,并计算空单元。

Haskell在特定的单元格中构建带有#s的“正方形”映射,并计算空单元。
EN

Stack Overflow用户
提问于 2016-10-20 16:51:46
回答 1查看 97关注 0票数 1

我正在为一个类做一个游戏,在一个任务中,我需要做一个正方形(这是‘地图’),我所知道的只是维度(两边的大小),然后我想用‘值’来计算我需要替换的单元格。

例如,维数为9的正方形如下所示:

代码语言:javascript
复制
 # # # # # # # # #

 # _ _ 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 _ _ #

 # # # # # # # # #
  • 第一行和最后一行都充满了# (墙壁)
  • 第二行和倒数第二行: allways以#和两个空空格_开头。
  • 第三行和倒数第二行:第二列和最后一列之前的空位,第二列的#
  • 然后,我总是在中间有一行没有#,在每两个空格中有一行#

因此,我需要构建一个计算vs的函数。我在地图上只接收到Dimension :: Int (在本例中是9,函数calcV (函数的名称示例)将返回28)。

下面是我尝试过的代码。这个方格总是有奇数维,等于或高于5,所以我做了5的情况,然后一个函数,我期望它会计算出我想要的所有其他可能的值。

但它给了我:

异常: ghci中的堆栈溢出

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

代码语言:javascript
复制
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
EN

回答 1

Stack Overflow用户

发布于 2016-10-20 21:18:08

当遇到这样的问题时,试着把它分解成更小的部分,并在编写递归函数之前看看如何用Haskell的现有工具(比如列表理解、mapfilterfoldr)来表示它。

首先,要生成长度为n的列表的平方列表,其中每个单元格都是行和列索引的一些函数:

代码语言:javascript
复制
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的实现在特定位置定义单元格。

代码语言:javascript
复制
  where
    cellAt :: Int -> Int -> Char

我不会列举所有的案例,因为这是一个家庭作业问题,但是这里有几个要让您开始:

代码语言:javascript
复制
    -- 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.
      | ...

然后,看起来您想要计算v单元格的数量,可以通过遍历映射来实现:

代码语言:javascript
复制
countV :: [[Char]] -> Int
countV rows = sum [sum [1 | 'v' <- row] | row <- rows]

calcV :: Int -> Int
calcV n = countV (makeMap n)

如果您的老师想要一个单一的功能,一个很好的练习就是手动将countVmakeMap的定义内联到calcV中。但是,通常编写小的、简单的函数更容易,可以组合这些函数来解决更大的问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40160181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档