function - 哈斯克尔井字游戏
问题描述
我正在尝试在 haskell 中构建井字游戏,但我遇到了功能问题haswon
。True
如果对于给定的玩家p
和游戏板,该函数应该返回bs
,他已经赢得了游戏,False
否则。
这是代码:
Int -> [((Int,Int),Int)] -> Bool
haswon p [((a,d), x), ((b,e), y), ((c,f), z)] = (x == y && y == z && x == p) && ( ((a == b) && (b == c)) || ((d == e) && (e == f)) || ( (a == d) && (b == e) && (c == f) && (a /= b) && (b /= c)) || ( (a == f) && (c == d) && (b==e)&&(a/=b)&&(b/=c)) )
您能否告诉我如何将其概括为大于 3 个元素的输入列表?例如,输入可能是 : [((1,1),1), ((1,2),1), ((2,1),2), ((2,2),2), ((3,1),1), ((3,2),1), ((3,3),2)]
。谢谢你。
解决方案
这是代码:
这是我的看法:
让我们首先定义正确的数据类型:
data Player = Black | White deriving (Eq, Show)
data Position = Position Int Int deriving (Eq, Show)
data Move = Move { position :: Position, player :: Player } deriving (Eq, Show)
现在实际函数只计算有资格获胜的线
hasWon :: Player -> [Move] -> Bool
hasWon p ms = (length $ winningLines p ms) > 0
获胜线的产生是一个很大的理解:
winningLines p ms = [(x,y,z) | x <- ms,
y <- ms,
z <- ms,
oneLine (position x) (position y) (position z),
samePlayer (player x) (player y) (player z),
x /= y,
y /= z,
x /= z
]
samePlayer px py pz = px == py && py == pz
oneLine (Position x1 y1) (Position x2 y2) (Position x3 y3) = sameRow || sameCol
where
sameRow = (y1 == y2 && y2 == y3)
sameCol = (x1 == x2 && x2 == x3)
最后是一些测试:
moves = [
Move (Position 1 1) White,
Move (Position 2 1) White,
Move (Position 3 1) White
]
main :: IO ()
main = do
print $ hasWon White moves
print $ winningLines White moves
该解决方案仅使用基础知识,因此您应该能够很容易地理解它并添加自己的修复程序;它仍然缺少对角线(易于添加),并且它计算了所有行 6 次(因为它考虑了所有排列;很容易通过Ord
位置实例修复,并且只考虑“排序的三元组”)。
当然,这不是唯一的方法;一个值得注意的替代方法是将它原地放入一个数组中,然后迭代地找到解决方案。不过,我认为 Prolog 式的声明式风格更适合 Haskell。
推荐阅读
- docker - 如何在本地部署中删除 Kubernetes 资源?
- reactjs - Immer 和 Redux Starter Kit 的 findIndex 问题
- android - 安卓。应用程序进入后台后一分钟内自动关闭第二个活动
- ios - CLLocation Manager 有时会给出不正确的位置
- java - 为什么 Spring Data REST 搜索返回的页面没有页面信息?
- php - 如果只有图像,我的页面就会显示
- c# - unity 对象初始化同步
- r - 如何在不预先知道预测变量数量的情况下在 R 中进行多因素回归(一般线性模型)?
- ios - Universal url scheme on iOS
- ssh - gitlab 错误连接到主机 gitlab.com 端口 22:连接超时