连连看算法js实现解析(降维改进版)--附自制小程序「五十音连连看」助记平假名/片假名

结果预览:

link000
其他预览

写小程序的原因

毕业之后(其实也不是), 不知道从什么时候开始, 不想把所有自由的时间用来肝游戏了, 还有总是有一些"不得不闲着"的时间, 于是今年年初就开始计划怎么度过这些时间, 除了游戏/看番, 还是多出来很多闲着的时间, 于是刷了一段时间leetcode
在这里插入图片描述
顺便在网上报了一个n4日语的课程, 就在这期间同学推荐了一个英语练习发音的小程序(明明是日语班学英语的还不少)…这样突然想到我为什么不也写一个日语主题的小程序, 于是就放弃了刷leetcode, 开始了小程序计划
一开始只是为了收集阴阳师式神台词语音以及同学们的录音, 后来才想到实现一个五十音主题的连连看, 或许可以帮助同学们记忆平假名和片假名
只是发布时大家都已经N4毕业了, 有点残念…
min00

正题

为了方便理解我特地写了一个浏览器实验版本:
连连看-实验版
index00
本文将围绕这个实验版带大家理解连连看算法, 顺便说明JS实现细节
有疑问可以到知乎上留言:
知乎的同篇文章

JavaScript实现源码:
连连看源码
内容:
sou00
如果你有耐心的话, 可以继续完善写一个属于自己的连连看!


那么, 分析开始

方块类型:

000
111
333
可以将以上方块类型分类:
按位置分类:

  • 在直线上
  • 不在直线上

按折点分类:

  • 0折点
  • 1折点
  • 2折点

连线折点不超过2

每一个分类对应算法的一个分支(if), 同时也要考虑连接方向, 于是这样实现下来之后分支会变得异常的多!!!
开始我就是尝试这样实现, 写到2折点的时候我发现…
what the f**k (╯°Д°)╯︵ ┻━┻ 我在写什么鬼东西? 就没有更优雅的写法!?

改进的算法:

(你可能想到写一个暴力的递归!emm…你可以Fork尝试改写实现)
抑制住砸键盘的冲动以及经过一番思想的碰撞之后,发现了一个比较有趣的实现思路:
a-b
假设从A连接B

  1. 把B点往四个方向无阻挡延伸的点称为目标点
  2. 从A点顺时针(右-下-左-上)寻路
  • 有交点:
    ta000
  • 无交点
    ta111
    这时候再分类的话, 只有两类:
  1. AB点的延伸有交点
  2. AB点的延伸无交点

与折点分类比较的话, 就是把0折和1折合并了, 并且简化了实现, 或者说对原算法进行了降维

算法实现:

概括:

  • 计算目标点:
  • (右-下-左-上)寻路
  • 无交点时进行二次寻路

====================================
JavaScript实现

计算目标点:
//二维数组--储存方块的状态(true有效/false空白)
var fields = []
//定义储存目标点的数组
var this_lefts = []
var this_rights = []
var this_ups = []
var this_downs = []

//计算目标点
function initTargetPoint(this_row, this_col){
   
    this_lefts = []
    this_rights = []
    this_ups = []
    this_downs = []

    var step_col = this_col
    //计算左边
    while (step_col > 0){
   
        step_col -= 1
        //非空白方块退出
        if (fields[this_row][step_col]) break
        this_lefts.push(this_row+","+step_col)
        //例:this_lefts = ["2,2", "2,1", "2,0"]
    }
    step_col = this_col
    while (step_col < max_col){
   
        step_col += 1
        if (fields[this_row][step_col]) break
        this_rights.push(this_row+","+step_col)
    }
    var step_row = this_row
    while (step_row > 0){
   
        step_row -= 1
        if (fields[step_row][this_col]) break
        this_ups.push(step_row+","+this_col)
    }
    step_row = this_row
    while (step_row < max_row){
   
        step_row += 1
        if (fields[step_row][this_col]) break
        this_downs.push(step_row+","+this_col)
    }
}

====================================

向右寻路:
//A点(row, col)-->B点(row, col):
//begin_col = A.col  end_col = B.col
//fixed_row = A.row
function rightLink(begin_col, end_col, fixed_row){
   
    console.log("----右")
    var steps = [] //存储经过的路径方块点(row, col)
    var step_col = begin_col
    while (step_col < end_col){
   
        step_col += 1
        if (fields[fixed_row][step_col]) break
        var row_col = fixed_row+","+step_col
        steps.push(row_col)
        //判断是否与(左目标点)有交点
        var idx = this_lefts.indexOf(row_col)
        if (idx != -1){
   
        	//(经过路径+交点到B点) = 全部路径
            steps = steps.concat(this_lefts.slice(0, idx).reverse()) //为了路径有序进行reverse()
            return steps
        }
        idx = this_ups.indexOf(row_col)
        if (idx != -1){
   
            steps = steps.concat(this_ups.slice(0, idx).reverse(
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值