java拼图游戏ai_拼图游戏和它的AI算法

本文介绍了如何使用Java实现一个拼图游戏,并探讨了实现游戏AI的三种算法:广度优先搜索、双向广度优先搜索和A*搜索。游戏允许用户自定义图片、选择难度,并支持自动复原。文章详细阐述了每种算法的工作原理,以及在不同难度下算法的性能表现。A*搜索算法在高难度下仍能有效找到拼图复原路径。
摘要由CSDN通过智能技术生成

写了个拼图游戏,探讨一下相关的AI算法。拼图游戏的复原问题也叫做N数码问题。

拼图游戏

N数码问题

广度优先搜索

双向广度优先搜索

A*搜索

游戏设定

实现一个拼图游戏,使它具备以下功能:

自由选取喜欢的图片来游戏

自由选定空格位置

空格邻近的方块可移动,其它方块不允许移动

能识别图片是否复原完成,游戏胜利时给出反馈

一键洗牌,打乱图片方块

支持重新开始游戏

难度分级:高、中、低

具备人工智能,自动完成拼图复原

实现几种人工智能算法:广度优先搜索、双向广度优先搜索、A*搜索

保存游戏进度

读取游戏进度

10a6d02616ad?from=singlemessage

Puzzle Game.png

自动完成拼图复原

先看看完成后的效果。点自动按钮后,游戏将会把当前的拼图一步一步移动直到复原图片。

10a6d02616ad?from=singlemessage

自动复原.gif

图片与方块

图片的选取可通过拍照、从相册选,或者使用内置默认图片。

由于游戏是在正方形区域内进行的,所以若想有最好的游戏效果,我们需要一张裁剪成正方形的图片。

10a6d02616ad?from=singlemessage

截取正方形区域.png

选好图片后,需要把图片切割成n x n块。这里每一个方块PuzzlePiece都是一个UIButton。

由于图片是会被打散打乱的,所以每个方块应该记住它自己在原图上的初始位置,这里给方块添加一个属性ID,用于保存。

@interface PuzzlePiece : UIButton

/// 本方块在原图上的位置,从0开始编号

@property (nonatomic, assign) NSInteger ID;

/// 创建实例

+ (instancetype)pieceWithID:(NSInteger)ID image:(UIImage *)image;

@end

难度选择

切割后的图片块组成了一个n x n矩阵,亦即n阶方阵。而想要改变游戏难度,我们只需要改变方阵的阶数即可。

设计三档难度,从低到高分别对应3 x 3、4 x 4、5 x 5的方阵。

10a6d02616ad?from=singlemessage

难度选择.gif

假如我们把游戏中某个时刻的方块排列顺序称为一个状态,那么当阶数为n时,游戏的总状态数就是n²的阶乘。

在不同难度下进行游戏将会有非常大的差异,无论是手动游戏还是AI进行游戏。

在低难度下,拼图共有(3*3)! = 362880个状态,并不多,即便是最慢的广搜算法也可以在短时间内搜出复原路径。

10a6d02616ad?from=singlemessage

3阶方阵的搜索空间.png

在中难度下,拼图变成了4阶方阵,拼图状态数飙升到(4*4)! = 20922789888000,二十万亿。广搜算法已基本不能搜出结果,直到爆内存。

10a6d02616ad?from=singlemessage

广搜算法占用的巨量内存.gif

在高难度下,拼图变成了5阶方阵,状态数是个天文数字(5*5)! = 1.551121004333098e25,10的25次方。此时无论是广搜亦或是双向广搜都已无能为力,而A*尚可一战。

10a6d02616ad?from=singlemessage

高难度下的5阶方阵.png

方块移动

在选取完图片后,拼图是完整无缺的,此时让第一个被触击的方块成为空格。

从第二次触击开始,将会对所触击的方块进行移动,但只允许空格附近的方块发生移动。

每一次移动方块,实质上是让方块的位置与空格的位置进行交换。在这里思维需要转个小弯,空格并不空,它也是一个对象,只不过表示出来是一块空白而已。那么我们移动了方块,是否可以反过来想,其实是移动了空格?答案是肯定的,并且思维这样转过来后,更方便代码实现。

10a6d02616ad?from=singlemessage

方块移动.gif

打乱方块顺序

这里为了让打乱顺序后的拼图有解,采用随机移动一定步数的方法来实现洗牌。

对于n阶方阵,可设计随机的步数为:n * n * 10。在实际测试当中,这个随机移动的步数已足够让拼图完全乱序,即使让随机的步数再加大10倍,其复原所需的移动步数也变化不大。复原步数与方阵的阶数有关,无论打乱多少次,复原步数都是趋于一个稳定的范围。

10a6d02616ad?from=singlemessage

打乱方块顺序.gif

10a6d02616ad?from=singlemessage

随机移动一定步数.png

拼图状态

我们需要定义一个类来表示拼图在某个时刻的状态。

一个状态应持有以下几个属性:

矩阵阶数

方块数组,以数组的顺序来表示本状态下方块的排列顺序

空格所在的位置,其值指向方块数组中显示成空

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值