俄罗斯方块清除整行

时间:2018-10-20 17:57:47

标签: haskell functional-programming

所以我正在使用haskell制作俄罗斯方块游戏,但在实现最后一个功能时遇到了麻烦,清除了全部行并减少了它上面的每个元组。

作为bord,我正在使用带有[[xcoord,ycoord)]的列表,其中仅包含坐标。

我正在考虑检查列表中是否有15个(俄罗斯方块游戏的宽度)具有相同ycoord的元组,因此,如果是这种情况,则该行已满,并且该行上方的所有内容的ycoord都减1。

removeFullRow :: [(Int,Int)] -> [(Int,Int)]
removeFullRow list = ?

在haskell中最好的方法是什么?

寻求帮助

2 个答案:

答案 0 :(得分:2)

给定使用的数据结构[(Int, Int)],这是一件相当复杂的事情。我建议一个更合适的。

话虽如此,有几个阶段。这是一种可行的方法:

  1. 按(y,x)值对输入列表进行排序(您可以Data.Tuple.swap元组从(x,y)进行转换),以便每一行上的所有元素都彼此相邻,从而使较低的行在列表的前面。
  2. 按y值对输入列表进行分组,以便所有行都位于不同的子列表中。
  3. 将元组转换为x个值。
  4. 过滤掉包含15个元素的所有子列表。
  5. 通过添加每个子列表的索引作为元素的y值来重构元组。

答案 1 :(得分:1)

这是我们将使用的方法:

  1. 我们翻遍列表,计算每行有多少项
  2. 我们是否有任何行已满
  3. 我们过滤出整行中项目的坐标

简介

import Data.Map as M

第1步

countInRows :: [(Int,Int)] -> M.Map Int Int
countInRows items =
  M.fromListWith (+) [(row,1) | (col,row) <- items]

此方法的工作原理:

  1. 将列表元素转换为“我知道行 n 中有1个完整正方形”的内容。
  2. 通过将每行的全平方数相加来将它们合并在一起
  3. 将结果放入地图中,将行与行的满度相关联

第2步

isFull :: Int -> M.Map Int Int -> Int -> Bool
isFull width counts row =
  M.findWithDefault 0 row counts >= width

这将查找一行的完整程度(如果它不在地图中,则必须有0个完整的正方形)。如果实心正方形与木板的宽度一样多,则该行必须是完整的。

第3步(将它们放在一起)

import Data.Map as M
removeFullRows :: Int -> [(Int,Int)] -> [(Int,Int)]
removeFullRows items =
  filter (not . isFull . row) items where
  counts = M.fromListWith (+) [(row,1) | (col,row) <- items]
  isFull row =
    M.findWithDefault 0 row counts >= width
  row (x,y) = y

我们通过获取行,查看行是否已满来过滤出项目,如果没有,则保留该项目。