写这个程序是因为在看《Java并发编程实战》书的时候,提到过用多线程来解决推箱子游戏,感觉挺好玩的,于是就开始写啦!!
准备阶段
先介绍一个推箱子网站(主页):http://sokoban.cn/
在这个网站你在它的规则(格式)下,也可以轻松获得推箱子地图、验证答案。
规则、格式:http://sokoban.cn/xsb_lurd.php
推箱子地图获取、答案验证:http://sokoban.cn/sokoplayer/SokoPlayer_HTML5.php
详细使用可以看下面的运行介绍
程序总结
代码
github:https://github.com/ZhongWenhui1995/SokobanSolver
csdn:http://download.csdn.net/detail/name_z/9742995
结果:
对于不复杂的图(地形不大、箱子不多或者求解比较复杂)的图,大部分可以完成任务,但对于太复杂的地图,时间很长,而且最终有可能会导致OutOfMemory异常,而解不出来。(后面有几个解决的想法)
多线程比单线程速度快,但是多线程时间不稳定,起伏较大。
程序介绍
简介:
简单来说,就是使用深度遍历所有路径,直到找到解决的路径或者找不到退出。
其中,有多线程版本和单线程版本
程序主要分为3部分:
1.地图
2.人的移动
3.路径搜索
类总览:
地图部分
类:
功能:
保存地图信息,以及提供关于地图的基础功能:地图检查、修改地图信息
类介绍
Point:
坐标点:x,y
创建后便不可修改
MapSymble:
指定地图信息用什么字符表示:墙壁、普通地板、站在目标点上的人、目标点、箱子、人、地图行间分隔符(整个地图用一个String存储时)、在目标点上的箱子
MapDirection:
地图方向:上下左右
SokobanMap:
创建后便不可修改
保存地图及相关信息:
1.地图信息
2.人的坐标点
3.长度,宽度
4.达到当前地图信息人所走过的路径(如果解决后,最后输出的结果)
提供地图相关功能:
1.获取某坐标的字符
2.指定将某坐标的字符替换成指定字符,然后返回新的SokobanMap对象(不是返回当前对象)
MapChecker:
功能:
检查地图是否有效,标准为:
1.地图必须为长方形的规整图形
2.不能存在无效字符(不在MapSymble没有的字符)
3.WALL必须封闭
4.必须有且仅有一个人
5.不能存在无效行(整行都是GROUND)
检查WALL是否封闭方法:
采用深度搜索,选定起始墙壁(通常为第一行中出现的第一个WALL),然后沿着墙壁遍历没走过的墙壁(只走墙壁),如果最后返回起始点则表明这墙壁是封闭的。
缺点:
不能检查出是多个闭环还是只有一个闭环
。。。
人的移动部分
类:
功能:
用于执行人的上下左右的移动,提供移动后的地图。
其中移动会有两种操作:
1.普通的移动,由地板到另一个地板(目标点)
2.推动箱子的移动,移动方向上有一个箱子
其中移动有可能会有两种结果,能否移动,其中,导致不能移动的原因有:
1.遇到了墙壁
2.遇到箱子,但箱子贴着墙壁
3.遇到箱子,但是箱子又贴着另一个箱子
类介绍:
IMapMoveRule:
运行规则,决定一个字符移动后地图的变化(目的地点以及原地点的变化)
包含两个方法:
1.当字符A移动到字符B后,字符B的坐标上应该显示什么字符
2.当字符A移动后,原来字符A的坐标上应该显示什么字符
DefaultMapMoveRule:
实现IMapMoveRule
下面列举的是方法:2.当字符A移动后,原来字符A的坐标上应该显示什么字符
public Character getCharOfGoalAfterMove(char goalChar, char