我不确定我们的作业是否以最具功能性的方式呈现,但我必须使用它。我有一张"地图"这代表了一个pacman游戏状态:
B B B B
B P _ B
B . . B
B B B B
其中B
是边框图块,P
是pacman,_
是空格,.
是食品芯块。移动pacman时有很多规则,但请考虑一个:
当pacman进入由食物颗粒占据的瓷砖时,用空的空间替换pacman瓷砖,用pacman替换食物颗粒。这个函数有定义:
move:: [[Char]] -> [[Char]]
现在我已经有了函数,它给了我pacman的(x,y)
坐标元组和他的新位置,我打算使用!!
函数来"覆盖&# 34;瓷砖。但是,我知道一些列表操作,例如:
。我可以使用:
来完成这项任务吗?
答案 0 :(得分:2)
我不是修改字符串,而是定义类型函数:
type Position = (Int, Int)
type Board = [[Char]]
renderBoard :: Position -> Board
然后我会修改pacman的位置并重新渲染董事会:
move :: Position -> Position
编辑:要回答您的具体问题,您可以使用lens
库轻松完成此操作:
import Control.Lens
move :: Position -> Position -> Board -> Board
move (oldX, oldY) (newX, newY) = (ix oldX.ix oldY .~ '_') . (ix newX.ix newY .~ 'P')
答案 1 :(得分:0)
这是一种不依赖于库的简单方法。首先,我们定义一个函数.~
,允许您设置列表的索引 -
set n x xs = take n xs ++ (x : drop (n+1) xs)
并给它一个方便的别名,以便我们可以使用中缀形式。
n .~ x = \xs -> set n x xs
这允许您执行
之类的操作>> let list = [1,2,3,4]
>> 1 .~ 10 $ list
[1,10,3,4]
现在将它扩展到修改二维列表的函数
是一件简单的事情(n,m) .= x = \xs -> n .~ (m .~ x $ xs!!n) $ xs
以便您可以执行
之类的操作>> let listOfList = [[1,2,3],[4,5,6],[7,8,9]]
>> (1,1) .= 100 $ listOfList
[[1,2,3],[4,100,6],[7,8,9]]
现在您可以轻松编写一个函数move
,它可以获取旧位置,新位置和当前电路板,并以您希望的方式修改电路板
type Pos = (Int,Int)
type Board = [[Char]]
move :: Pos -> Pos -> Board -> Board
move (x,y) (x',y') board = board''
where
board' = (x, y ) .= '_' $ board
board'' = (x',y') .= 'P' $ board'
也就是说,where
子句中的第一行修改了电路板以用空的空间替换PacMan的旧位置,第二行修改了已经重新形成的电路板,将PacMan置于新位置。
答案 2 :(得分:0)
下面是一个replace
函数,可用于替换二维数组[[Char]]
中的特定位置字符
replace :: [[Char]] -> (Int,Int) -> Char -> [[Char]]
replace chars (x',y') c = do
(x,row) <- zip [0..] chars
return [if x == x' && y == y' then c else r | (y,r) <- zip [0..] row]
第二个参数是需要使用第3个位置的Char值更新的位置。
使用此功能,您应该能够实现移动功能。