标签:
继上一篇博文,已经半年没有写过博文了
因为不想打字和语文能力比较差 所以就懒得写了
不过也不是坏事 上一篇就是一个拼图的游戏 这篇写的是这个游戏的AI [是AI不是外挂 ]
这个是智能拼图游戏http://www.cnblogs.com/magicianlyx/p/5205799.html
网上的 贪食蛇AI 俄罗斯方块AI 见得比较多并且他们的算法思路都是比较普遍我就不重复造轮子了,自己也多拼图这个游戏比较有兴趣
先来几张效果的样张
6*6的gif
556步 5秒生成
14*14的 因为时间太长 剪出来的GIF太大了 我就上传静态图片吧 如果要看的等下面我放个EXE大家可以到自己的机器上运行一下
8000+步 50秒完成
下面我先来说说AI的思路 主要用的是变形的A*算法 其他的基本都是逻辑判断了
先说一下一些名词:
主动块:当前处理的方块
空白块:就是在拼图时一直为白色的那一块 最后完成时在左上角出现的哪一个块 只有空白块的附近的方块才可以运动
先说 方块的处理顺序
以4*4为例 先处理外层(靠右靠下)的,因为空白的方块在左上角 ,这样做更加有利于后期的左上部分的方块处理, 高瞻远瞩 的策略
处理顺序如下
再来说一下 方块的当前位置和目标位置的关系
黄色是方块的当前位置
红色是方块的目标位置
方块需要从当前位置(黄色)移动到目标位置(红色)
这里一共是9种情况,我们下面分析一下9种情况存在的可能性和处理策略
情景A:目标位置在当前位置的右下方向
情景B:目标位置在当前位置的正下方向
情景C:目标位置在当前位置的左下方向
情景D:目标位置在当前位置的正左方向
情景E:目标位置在当前位置的正右方向
情景F:目标位置在当前位置的右上方向
情景G:目标位置在当前位置的正上方向
情景H:目标位置在当前位置的左上方向
还有最后一种情况在图中没有画出:就是当目标位置和当前位置是一致
更具优先处理靠右和靠下的方块
我们可以判断
{目标位置在当前位置的正左方向D} 和 {目标位置在当前位置的左上方向H} 这两种是不可能存在的 ——至于为什么?读者在脑海里YY一下方块的处理顺序的场景就自然很清晰了
{目标位置和当前位置一致} 这种是不需要处理的
再来看看 各种情景的对应的处理策略
处理策略是让当前处理的块在处理过程中不破坏已经完成(摆放好)的块
情景A:目标位置在当前位置的右下方向
情景B:目标位置在当前位置的正下方向
情景C:目标位置在当前位置的左下方向
情景D:目标位置在当前位置的正左方向(上面已经说明不可能的情况 不处理)
情景E:目标位置在当前位置的正右方向
情景F:目标位置在当前位置的右上方向
情景G:目标位置在当前位置的正上方向
情景H:目标位置在当前位置的左上方向(上面已经说明不可能的情况 不处理)
还有两种情况的块是不能用上面的办法处理的 需要特殊处理(这种比上面的更优先 这里说的优先是指当块是这两种情况的时候 优先采用这里对应的处理策略)
一种是位于最左的块 图中灰色的块
第二种是x和y相同的块 图中蓝色的块
至于有一些是属于第一种或者第二种却没有被标出来的(图中打问好的方块) 那是因为这种块的x和y都小于2,需要被另外一种特殊处理,等下后面会说到
第一种[位于最左的块]图中被灰色框框住的,他在不影响绿色框的位置的块的情况下做红色箭头的移动操作
处理方法:
第一步[以空白块为右下角相关的四个块进行顺时针旋转]
以空白块为右下角相关的四个块进行顺时针旋转 效果
第二步[以空白块为右上角相关的四个块进行顺时针旋转]
以空白块为右上角相关的四个块进行顺时针旋转 效果
第三步[以空白块为右下角相关的四个块进行逆时针旋转]
以空白块为右下角相关的四个块进行逆时针旋转 效果
第四步[以空白块为右上角相关的四个块进行逆时针旋转]
以空白块为右上角相关的四个块进行逆时针旋转 效果
所以归纳得出第一种情况及其处理方法是 设其目标位置为TargetPos
当主动块位于最左的块[即TargetPos.X==0的块]
先把主动块移动到目标位置的对上的一个位置(TargetPos.X,TargetPos.Y-1) ,
判断空白块是不是在(TargetPos.X,TargetPos.Y)是的话就把主动块下移直接完事
然后把空白块放到(TargetPos.X+1,TargetPos.Y-1)
再进行四次转换
{
以空白块为右上角相关的四个块进行顺时针旋转
以空白块为左上角相关的四个块进行顺时针旋转
以空白块为右上角相关的四个块进行逆时针旋转
以空白块为左上角相关的四个块进行逆时针旋转
}
第二种情况[目标位置X==Y的块]图中被灰色框框住的,他在不影响绿色框的位置的块的情况下做红色箭头的移动操作
我就不一一再图解了,因为和上面第一种情况有点相似,发个GIF直接归纳好了
所以归纳得出第二种情况及其处理方法是 设其目标位置为TargetPos
当位于TargetPos.X==TargetPos.Y的块
先把他移动到目标位置的对上的一个位置(TargetPos.X-1,TargetPos.Y) ,
判断空白块是不是在(TargetPos.X,TargetPos.Y)是的话就把主动块右移直接完事
然后把空白块放到(TargetPos.X-1,TargetPos.Y-1)
再进行四次转换
{
以空白块为右下角相关的四个块进行顺时针旋转
以空白块为右上角相关的四个块进行顺时针旋转
以空白块为右下角相关的四个块进行逆时针旋转
以空白块为右上角相关的四个块进行逆时针旋转
}
先写一半 已经2点了 太晚了 下星期有考试 迟点有时间&&有心情再写 ^_^
先公开源码: 估计有点难看 因为代码还没被调整和重构过
http://pan.baidu.com/s/1nvDA5PR
标签:
原文地址:http://www.cnblogs.com/magicianlyx/p/5937272.html