javascript 解 一笔画游戏

来源:互联网 发布:eplan软件价格 编辑:程序博客网 时间:2024/06/11 18:01

偶然玩到这个游戏,十几关过去后就比较头疼了,于是写了个解题程序。。。

分析游戏:

游戏由 点、线(点与点之间的关系)构成。规则:不能走重复路径;所有线走完则过关。

解题方式是递归遍历所有路径,暴力破解一样。

思路:

两个类 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.


0 0
原创粉丝点击