V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
flyPig9527
V2EX  ›  程序员

diy 制作数字华容道游戏,上班摸鱼就它了

  •  
  •   flyPig9527 · 2022-12-09 13:59:48 +08:00 · 1293 次点击
    这是一个创建于 697 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近老是抖音老是刷到一个小孩子玩数字华容道特别厉害,我感觉挺有趣的,就做了一个数字华容道,上班摸鱼可以玩,哈哈哈哈哈。

    项目预览地址
    项目地址 喜欢的话请给个 star⭐️

    整体的样式是采用了像素风格。 功能:

    • 游戏模式可以自定义选择难度,比如 3X3 、4X4 、5X5 等
    • 设置的有各个模式的排行榜,可以看到排名
    • 用户昵称是随机的,如果不满意可以更换昵称

    实现思路

    核心的部分肯定是游戏交互的部分了,这里采用的是二维数组的方式实现的。
    二维数组:主要是为了每个模式的初始化的时候,以二维数组的形式为默认值,为了后面区分行数列数。需要用到两个二维数组,一个是为了初始化的值initData,一个是当前游戏中的值curData
    如:3X3 的模式初始化 initData

    [
        [1,2,3],
        [4,5,6],
        [7,8,null]
    ]
    

    由于是用的 pixijs 去生成的方格,点击事件获取的是该方格的数值,如:1,2,3,4,5,6 等等。根据点击的方格数值判断该方格四周(上下左右)有没有null值,有的话就进行交换,得到新的curData。这里判断是有些麻烦的。

    例子:
    如果当前点击的是 3 ,当前模式的行数(rows)为 3 ,列数(columns)为 3
    当前的布局(curData)为:

    [
        [2,6,3],
        [1,null,5],
        [7,4,8]
    ]
    
    // 先获取点击数字在 curData 中的位置
    const curDataFlat = curData.flat(); // 数组扁平化处理,二维数组转成一维数组
    const index = curDataFlat.indexOf('3'); // index 为 2
    // 要移动的方向
    let direction = '';
    // 要交换的位置
    let newIndex = index;
    // 左方向的判断
    if (curDataFlat[index - 1] === null) {
      if (index % columns !== 0) {
        direction = 'left';
        newIndex = index - 1;
      }
      // 右方向的判断
    } else if (curDataFlat[index + 1] === null) {
      if (index % columns !== columns - 1) {
        direction = 'right';
        newIndex = index + 1;
      }
      // 下方向的判断
    } else if (curDataFlat[index + columns] === null) {
      direction = 'bottom';
      newIndex = index + columns;
      // 上方向的判断
    } else if (curDataFlat[index - columns] === null) {
      direction = 'top';
      newIndex = index - columns;
    }
    

    每次交换之后curData都要和initData进行对比,如果一样代表成功了,游戏结束。

    游戏怎么初始化?

    一开始我想的很简单,拿3X3的模式举例子就是拿1-8的数字随机取。
    数组: [1,2,3,4,5,6,7,8] 第一次随机拿到了3就放第一个格子里,这时候数组变成了[1,2,4,5,6,7,8]
    第二次随机拿到了5放第二个格子中,这时候数组变成了[1,2,4,6,7,8]
    ... 依次类推把格子填满了。
    本来以为这样就大功告成了。后面发现了一个很致命的问题有时候这样的随机布局根本就无法通关
    举一个最简单的例子:
    随机的布局是这样子的:

    [
        [1,2,3],
        [4,5,6],
        [8,7,null]
    ]
    

    这种是无法通关的,emm......。

    换个思路: 换个玩魔方的思路,魔方是怎么随机的,是先将一个复原好的魔方进行随机旋转打乱的。ok ,用这个思路就可以进行数字华容道的随机布局了。
    具体思路:

    1. 一开始先用完成好的布局:
    [
        [1,2,3],
        [4,5,6],
        [7,8,null]
    ]
    
    1. 随机上下左右移动 null 值,这样随机移动几十步或者上百步就可以打乱初始化的布局了,每次的随机布局也都能通关了。

    游戏昵称怎么随机?

    一开始我想的是随机拿到汉字,这里是可以通过 Unicode 编码去实现的。
    汉字的范围是 4e00-9fa5,这些编码前面加上0x就是能得到十进制的数值了,再通过toString(16)转换成十六进制4e00,最后将4e00加上\u,得到\u4e00,通过unescape方法得到该字符。

    function randomAccess(min, max) {
      return Math.floor(Math.random() * (min - max) + max);
    }
    // 解码
    function decodeUnicode(str) {
      //Unicode 显示方式是\u4e00
      str = '\\u' + str;
      str = str.replace(/\\/g, '%');
      //转换中文
      str = unescape(str);
      //将其他受影响的转换回原来
      str = str.replace(/%/g, '\\');
      return str;
    }
    
    function translateName() {
      // 中文
      let randomArr = [0x4e00, 0x9fa5];
      let unicodeNum = '';
      unicodeNum = randomAccess(randomArr[0], randomArr[1]).toString(16);
      let result = decodeUnicode(unicodeNum);
    
      return result;
    }
    
    // 获取到中文
    console.log(translateName());
    

    这样子虽然能得到中文,但是会得到很多偏僻字,比如鈠 鑙,为了防止这些偏僻字的出现,想到了可以按照中文的笔画数划分,一般来说笔画少的生僻字是会少很多的。
    cnchar这个 npm 包就是可以识别汉字的笔画数的。有了这个 npm 包,事半功倍了起来,当汉字的笔画数大于10就重新获取汉字,直到笔画数少于 10为止。
    后面我又加入了一些日文符合阿拉伯数字

    --------------END-------------------

    8 条回复    2024-11-05 11:02:00 +08:00
    zzzmh
        1
    zzzmh  
       2022-12-09 14:14:39 +08:00
    我第一个做的游戏也是这个,得有个八年前了,当年是用 java 的 swing ,特地去网盘翻出来玩了一把
    ![]( https://s2.loli.net/2022/12/09/ToGFwlUY8ZEJicS.png)
    ![]( https://s2.loli.net/2022/12/09/rdhwK3CLRP5yjVo.png)
    flyPig9527
        2
    flyPig9527  
    OP
       2022-12-09 14:51:30 +08:00
    @zzzmh 可以,帮你找回以前的快乐,那我这个文章也算是有价值的🐶
    xuelang
        3
    xuelang  
       4 天前
    厉害,google 搜数字华容道第一个就是这个。
    我最近用 cursor 也一款,支持智能给出路径,支持自定义方格数字
    欢迎来玩~
    https://gallery.selfboot.cn/zh/games/sliding
    flyPig9527
        4
    flyPig9527  
    OP
       4 天前
    @xuelang 我也挺意外的,每天玩的人有五六个,访问量不清楚,有个哥们都玩了一百多个小时了,天天玩几十把,可能他访问太频繁给我顶上去了吧,我为了他时不时更新迭代一下,哈哈哈哈
    xuelang
        5
    xuelang  
       2 天前
    @flyPig9527 竟然有人能玩 100 多小时,也是厉害啊
    flyPig9527
        6
    flyPig9527  
    OP
       1 天前
    @xuelang 我也很费解,大多时候凌晨开始玩,玩两三个小时
    xuelang
        7
    xuelang  
       7 小时 55 分钟前
    @flyPig9527 这更有点不可思议了
    flyPig9527
        8
    flyPig9527  
    OP
       5 小时 22 分钟前
    @xuelang 刚查了一些数据库,他大致玩了两百多小时了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5544 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 34ms · UTC 08:24 · PVG 16:24 · LAX 00:24 · JFK 03:24
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.