今天闲来无事看到女票在玩一个小游戏
连线达人
, 感觉蛮有意思的.
看到她过不了关满脸着急就花了点时间✍搞了个小后门🤭
咳咳~, 闲话少说!!!
程序资源下载
连线达人
到底是个啥😚
就是这么个小游戏, 从头部开始把所有的格子都连起来就算过关, 挺简单的吧😏
先分析分析!
首先要清楚几个东西:
- 地图
先这么叫着吧
中所有需要连接的格子有哪些? 坐标横向为行, 纵向为列
- 开始坐标在哪里?
结束坐标不确定
- 当前已经走过的格子是哪些?
嗯, 规则是不能交叉连线
- 当前坐标的上一步在哪里?
当然这是为了方便回退并再次尝试
- 是否已经通关
来, 看看界面!
根据以上逻辑, 做了简单界面
断点是第一次尝试失败!!! 别着急后面还有9999次
🤭
界面使用HTML
画出来
<div style="padding:15px 0;">
<input id="rowIpt" type="number" min="1" max="10" step="1" placeholder="输入行数"></input>
<input id="cellIpt" type="number" min="1" max="10" step="1" placeholder="输入列数"></input>
<input id="retryCount" value="10000" type="number" min="1" max="10000" step="1" placeholder="尝试次数"></input>
<button id="gen">生成 [Enter]</button>
</div>
<div class="container">
<div class="row">
<div class="cell road startPoint"></div>
<div class="cell road"></div>
<div class="cell road"></div>
<div class="cell road"></div>
<div class="cell road"></div>
<div class="cell road"></div>
</div>
</div>
<div class="menus">
<div data-key='49'>道路[1]</div>
<div data-key='50'>开始点[2]</div>
<div data-key='51'>开始计算[3]</div>
</div>
<dl>
<dt>结果</dt>
<dd id="result"></dd>
</dl>
<script src="https://cdn.bootcss.com/jquery/1.10.2/jquery.min.js"></script>
样式表在这里
.cell {display:inline-block;}
.container > .row div {border:1px solid #aaa;}
.container > .row {display:flex; height:50px;}
.container > .row > .cell {flex:1; cursor:pointer; color:#f00; text-align:center;}
.container > .row > .cell:hover {border-color:#f00;}
.container {width:300px;}
.road {background:#0f0;}
.startPoint {background:#00f;}
.menus > * {display:inline-block; margin:10px; padding:12px; cursor:pointer; border:1px solid #aaa; background:#eee;}
.menus > *:hover {background:#ddd;}
.menus .active {background:#1fad43;}
逻辑怎样实现的?
先绘制地形图整张地图的所有格子, 截图示例是6*6
的方格. (输入对应的行/列数量后按Enter
键).
然后按大键盘的1键
标记需要连接的方块♦有哪些, 绘制完成后再按大键盘2键
指定开始方块
是那个坐标
接着指定尝试次数, 路径越复杂
尝试次数需要越大
, 同时花费的时间越多. 上图指定尝试次数为10万
次
惭愧~, 作者试过1万次解不出来 T_T
手术刀准备好, 开始解剖
打开浏览器调试工具通常是F12
, 并将Breakpoint
设置到失败时回退上一步
的位置.
...
// 所有方向都不通
// 回到上一步, 并清除当前已通过点
var dir = $el.attr("data-from");
$el.removeAttr("data-from").text('');
var prevPath = pathArr.pop();
delete pathMap[pathKey]; // 删除无效路径
// 计算下一个开始位置(当前位置前一步)
path = prevPath;
...
你从哪里来?
程序首次运行时,当前位置就是起始位置
var $el= $('.startPoint').attr('data-from', 'startPoint');
var sps = getPoint($el); // 当前点的坐标(rowIndex/ri,cellIndex/ci)
要到哪里去(核心逻辑)?
从当前点出发到达下一个点有4个方向。同时要指出后退方向,在失败时需要回到上一个点尝试其他路径。
var dirs = {up:'↑', down:'↓', left:'←', right:'→'};// 显示走过的路
var dirsRevers = {up:'down', down:'up', left:'right', right:'left'};// 方向反转
出发之前先真理好行李
。
point
:今晚在哪落脚
fromDir
:昨晚在哪落脚,有机会回去
找老板开发票
toDir
:接下来准备去哪呢?要记得好马不吃回头草
哟
{
point:{ri:number, ci:number},
fromDir:string, // 'start' + dirs.keys
toDir:{
up:boolean, // true-已尝试, false-未尝试, null-此路不通
down:boolean,
left:boolean,
right:boolean
}
}
有句话叫不撞南墙不回头
,所以呢~走起
。我们需要在4个方向不断尝试(转角遇到爱
),直到撞墙。从dirs
各个方向前进一步。
var hasNext = false;
for (var k in dirs) {
// 跳过已尝试
switch (path.toDir[k]) {
case true:
case null: continue;
}
// 不允许走回头路
if (dirsRevers[k] == $el.attr('data-from')) {path.toDir[k]=null; continue;}
var nextSps = nextPoint(k, sps);
if (!nextSps) {path.toDir[k]=null; continue;}
var $row = $('.row:eq('+nextSps.ri+')');
if (!$row.length) {path.toDir[k]=null; continue;}
var $cell = $row.find('.cell:eq('+nextSps.ci+')');
if (!$cell.hasClass('road')) {path.toDir[k]=null; continue;}
// 不允许重复
if ($cell.attr('data-from')) {path.toDir[k]=null; continue;}
$el.text(dirs[k]);
$cell.attr('data-from',k);
sps = nextSps;
$el = $cell;
hasNext = true;
path.toDir[k] = true;
path.fromDir = k;
break;
}
找到今晚的落脚点了吗?当然~
...
$el.text(dirs[k]);
$cell.attr('data-from',k);
sps = nextSps;
$el = $cell;
hasNext = true;
path.toDir[k] = true;
path.fromDir = k;
...
一定要记得不要鬼打墙
,绕进死胡同。
// 跳过已尝试
switch (path.toDir[k]) {
case true:
case null: continue;
}
如果不小心走到悬崖峭壁
还是原路返回,去上个路口
看看有没有别的出路
// 所有方向都不通
// 回到上一步, 并清除当前已通过点
var dir = $el.attr("data-from");
$el.removeAttr("data-from").text('');
var prevPath = pathArr.pop();
delete pathMap[pathKey]; // 删除无效路径
// 计算下一个开始位置(当前位置前一步)
path = prevPath;
sps = nextPoint(dirsRevers[dir], path.point);
$el = $('.row:eq('+sps.ri + ') .cell:eq('+sps.ci+')');
$el.text('');
**哇哈环球旅游结束**,当然这一生不可能就在这里打转儿总还得找点别的事做。所以,当然要限制尝试的次数
// 获取最大尝试次数
var max = $('#retryCount').val()||0;
max = Math.max(0, max);
// 控制尝试次数防止死循环
var i = 0;
while(max > ++i) {
...
if (pathArr.length == roads.length) break;
...
}
上面这段逻辑看懂了,那么恭喜你可以去问老板涨工资啦
咳咳~当然是开玩笑😝
多尝试几次就好啦.
仅以此献给不断学习的自己!如有疑问欢迎探讨🎇