javascript 解 一笔画游戏
2014-01-08 22:20
351 查看
偶然玩到这个游戏,十几关过去后就比较头疼了,于是写了个解题程序。。。
分析游戏:
游戏由 点、线(点与点之间的关系)构成。规则:不能走重复路径;所有线走完则过关。
解题方式是递归遍历所有路径,暴力破解一样。
思路:
两个类 Pointer、Line。
Pointer属性:no编号,orientations方向(数组,所有与点连接的点编号),equals()比较节点是否为同一个节点。
Line属性:p1编号小的点,p2编号大的点。
使用多线程以每个节点为初始点开始递归遍历,走一步删除走过的线,某节点遍历完仍无解则还原被删除的线。解题成功则修改全局变量PATH,如果有其它线程解题成功(PATH非空)则直接returne,直至退出当前线程。
代码:
如果分支很多,第一个节点就错误的话耗时相当长,所以遍历时使用了多线程,引入Concurrent.Thread框架,使用方式请百度,我也第一次用。本来直接用setTimeout,因为js多线程是模拟的,setTimeout执行的函数如果很吃CPU的话,后面的setTimeout照样阻塞,还是大神写的框架好用,一下就解决了。为什么初始节点下无解会那么慢(无敌版几个小时),初始节点下有解那么快(<1s)?我也没搞懂,差距也太大了吧。。。断点看了简单版所有流程,没啥异常。有大神看破了的话,请指点迷津。
界面、输入校验还不够完善,懒得搞了,喜欢折腾的自己去弄吧。
算法或实现方式有建议的请赐教。
图:
请使用chrome/firefox,使用低版本ie需注释console.info().
游戏地址:http://www.4399.com/flash/97076.htm。无敌版最后关卡已通过测试。
下载地址:http://download.csdn.net/detail/lj745280746/6826219.
分析游戏:
游戏由 点、线(点与点之间的关系)构成。规则:不能走重复路径;所有线走完则过关。
解题方式是递归遍历所有路径,暴力破解一样。
思路:
两个类 Pointer、Line。
Pointer属性:no编号,orientations方向(数组,所有与点连接的点编号),equals()比较节点是否为同一个节点。
Line属性:p1编号小的点,p2编号大的点。
使用多线程以每个节点为初始点开始递归遍历,走一步删除走过的线,某节点遍历完仍无解则还原被删除的线。解题成功则修改全局变量PATH,如果有其它线程解题成功(PATH非空)则直接returne,直至退出当前线程。
代码:
//点 function Pointer(no, orientation) { if (isNaN(no) || typeof orientation != 'string' || orientation == "") { console.info("no:" + no + " orientation:" + orientation); throw new Error("非法参数"); }; this.no = no; this.orientations = orientation.split(',').sort(function(a, b) { if (parseInt(a) > parseInt(b)) { return 1; } else if (parseInt(a) < parseInt(b)) { return -1; } else { return 0; } }); this.oriStr = this.orientations.toString(); this.equals = function(obj) { if (!(obj instanceof Pointer)) { return false; } if (this.no == obj.no && this.oriStr == obj.oriStr) { return true; } else { return false; } }; }
//线 function Line(p1, p2) { //参数为点,且不能为同一个点 if (!(p1 instanceof Pointer) || !(p2 instanceof Pointer) || p1.equals(p2)) { console.info("p1:" + p1.no + " p2:" + p2.no); throw new Error("错误,节点不能指向自身!节点编号:" + p1.no); }; //线的属性两个点 p1,p2赋值 p1.no > p2.no ? (this.p1 = p2, this.p2 = p1) : (this.p1 = p1, this.p2 = p2); this.equals = function(obj) { if (!(obj instanceof Line)) { return false; } if (this.p1.equals(obj.p1) && this.p2.equals(obj.p2)) { return true; } else { return false; } }; }
如果分支很多,第一个节点就错误的话耗时相当长,所以遍历时使用了多线程,引入Concurrent.Thread框架,使用方式请百度,我也第一次用。本来直接用setTimeout,因为js多线程是模拟的,setTimeout执行的函数如果很吃CPU的话,后面的setTimeout照样阻塞,还是大神写的框架好用,一下就解决了。为什么初始节点下无解会那么慢(无敌版几个小时),初始节点下有解那么快(<1s)?我也没搞懂,差距也太大了吧。。。断点看了简单版所有流程,没啥异常。有大神看破了的话,请指点迷津。
//计算求解 function calculate(ptrArr, lineArr) { for (var i = 0; i < ptrArr.length; i ++) { Concurrent.Thread.create(pathFinding, ptrArr[i], ptrArr, lineArr.slice(0)); } return ""; }
//寻路 function pathFinding(p, ptrArr, lineArr) { var rs = p.no + "->"; // console.info(rs); var orientations = p.orientations; //临时路径,寻路错误时还原 var tmpLineArr = lineArr.slice(0); for (var i = 0; i < orientations.length; i ++) { var p2 = getPointerInArray(orientations[i], ptrArr); if (p2 == null) { return ""; } var l = new Line(p, p2); var index = lineIndexOf(l, tmpLineArr); //线不存在 已被走过 if (index == -1) { continue; } // console.info(tmpLineArr[index]); //经过的线段删除 tmpLineArr.splice(index, 1); //如果线 全部走完 则解题成功 if (tmpLineArr.length == 0) { return rs + p2.no + "|"; } //递归 下一个点的所有分支 var tmpRs = pathFinding(p2, ptrArr, tmpLineArr); if (tmpRs.substr(-1) == "|") { //如果数组长度等于初始长度 说明这是递归最外一层 解题成功 if (lineArr.length == LINE_COUNT) { PATH = rs + tmpRs; // document.write(PATH); } return rs + tmpRs; } else if (tmpRs == "*") { return "*"; } //其他线程解题成功 该线程终止 if (PATH != "") { return "*"; } //如果是节点最后一个分支 不做无谓的还原 if (tmpLineArr.length < lineArr.length && i < orientations.length - 1) { //还原点 // console.info("r2: tmpArrLength=" + tmpLineArr.length + "; lineArrLength=" + lineArr.length); tmpLineArr = lineArr.slice(0); } } return ""; }注释还是很详细滴~
界面、输入校验还不够完善,懒得搞了,喜欢折腾的自己去弄吧。
算法或实现方式有建议的请赐教。
图:
请使用chrome/firefox,使用低版本ie需注释console.info().
游戏地址:http://www.4399.com/flash/97076.htm。无敌版最后关卡已通过测试。
下载地址:http://download.csdn.net/detail/lj745280746/6826219.
相关文章推荐
- javascript
- 好用的在线 JSON 编辑器
- 【D3中文api文档制作小组英雄帖】
- 超实用的JavaScript技巧及最佳实践(下)
- javascript按钮倒计时,然后“下一步”按钮可点
- 45本免费的JavaScript书籍资源
- javascript中的创建自定义对象的六种方式详解
- 快速上手RaphaelJS--Instant RaphaelJS Starter翻译(三)
- JSP中java代码与js之间的传值
- JS:For-In
- cas sso ajax的jsonp实现方案总结(新浪微薄、淘宝案例分析)
- JavaScript运算符优先级引起的bug
- JS:private variables
- 超实用的JavaScript技巧及最佳实践(下)
- 超实用的JavaScript技巧及最佳实践(下)
- JavaScript与函数式编程
- jsoneditor显示Json data
- JavaScript运算符优先级引起的bug
- EXT JS 学习
- Javascript中this的用法