[ 逻辑锻炼] 用 JavaScript 做一个小游戏 ——2048 (初级版)

news/2024/5/17 16:50:15

前言

前段时间发现网上有很多收费或公开课都有教用 js 做 2048 小游戏的,然后自己就也想动手做一个,做这个小游戏主要是为了锻炼自己的逻辑能力,也算是对之前一些学习的总结吧

注:

  1. 实现方法完全是自己边玩 2048 边想的,所有些乱还请见谅
  2. 另外配色方案是在某个 2048 游戏截屏,然后用 ps 吸取的,非本人原创
  3. 代码中有很多都可以使用数组相关的方法来代替,这里是为了自己理解数组方法是什么原理
  4. 由于时间关系本次不做详解

游戏逻辑

  1. 随机位置生成数字 2 或 4
  2. 按方向键,有挨着的相同的数字就合并成新的数字
  3. 按方向键,数字会移动到对应方向的最边上(按左,数字全部移动到左边)
  4. 每次按方向键,合并完成后,会在没有数字的随机位置都会生成新的数字 2 或 4
  5. 当前分数等于当前所有数字相加
  6. 当有数字达到 2048 游戏结束

项目相关

这个版本是用原生 ES6 写的,只实现了游戏逻辑中的 1,2,3,4;
第一版地址:https://github.com/yhtx1997/S...

之后是打算用 vue 重新写一遍,并且完善下,因为长时间用原生,导致 vue 有些生疏,借此机会重新温习下

项目代码

采用二维数组进行数据的管理,默认全部为零

let arr = [
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0],
    [0, 0, 0, 0]
];

随机创建数字

let s = 0;
let create = () => {
    let x = Math.floor(Math.random() * 4);
    let y = Math.floor(Math.random() * 4);

    // console.log(s)
    if (s > 100) {
        s = 0;
        return;
    }
    if (arr[x][y] == 0) {
        if (Math.floor(Math.random() * 10) % 2 == 0) {
            arr[x][y] = 2;
        } else {
            arr[x][y] = 4;
        }
        s = 0;
        return;
    } else {
        s++;
        return create();
    }
}

渲染页面

let updateHtml = () => {
    //获取元素
    let warp = document.getElementById('warp');
    let html = '';
    //将数据转换为 HTML 
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr[i].length; j++) {
            html += `<div class='c c-${arr[i][j]}'>${arr[i][j]==0?'':arr[i][j]}</div>`;
        }
    }
    //将 数据转换的 HTML 渲染到页面
    warp.innerHTML = html;
}

事件监听

window.onkeydown = (e) => {
    switch (e.keyCode) {
        case 37:
            // ←
            console.log('←');
            arr = new move(arr).moveLeft();
            create(); //随机位置新建
            updateHtml(); //更新数据到页面
            break;
        case 38:
            // ↑
            console.log('↑');
            arr = new move(arr).moveUp();
            create(); //随机位置新建
            updateHtml(); //更新数据到页面
            break;
        case 39:
            // →
            console.log('→');
            arr = new move(arr).moveRight();
            create(); //随机位置新建
            updateHtml(); //更新数据到页面
            break;
        case 40:
            // ↓
            console.log('↓');
            arr = new move(arr).moveDown();
            create(); //随机位置新建
            updateHtml(); //更新数据到页面
            break;
    }
}

具体处理函数

先提取非零数字

export default function ClearZero (arr){//去零
    let clearZero = [[],[],[],[]];
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            if (arr[i][j] != 0) {
                clearZero[i].push(arr[i][j])
            }
        }
    }
    return clearZero;
}

将挨着的相等数字分组并相加

分组

import Deduplication from './deduplication';//将相邻且相同的数字相加

export default class Grouping{//将相邻的相同数字分组
    constructor(clearZero){
        this.clearZero = clearZero;
    }
    left(){
        let newarr = [[],[],[],[]];
        for (let j = 0; j < this.clearZero.length; j++) {
            let grouping = [];
            let i = 0;
            //将重复的 分到一组
            while (i < this.clearZero[j].length) {
                if (this.clearZero[j][i] == this.clearZero[j][i + 1]) {
                    grouping.push([this.clearZero[j][i], this.clearZero[j][i + 1]]);
                    i += 2;
                } else {
                    grouping.push(this.clearZero[j][i]);
                    i++;
                }
            }
            //去重复
            newarr[j] = Deduplication(grouping);
        }
        return newarr;
    }
    right(){
        let newarr = [[],[],[],[]];
        for (let i = 0; i < this.clearZero.length; i++) {
            let grouping = [];
            let j = this.clearZero[i].length - 1;
            //将重复的 分到一组
            while (j >= 0) {
                if (this.clearZero[i][j] == this.clearZero[i][j - 1]) {
                    grouping.unshift([this.clearZero[i][j], this.clearZero[i][j - 1]]);
                    j -= 2;
                } else {
                    grouping.unshift(this.clearZero[i][j]);
                    j--;
                }
            }
            //将重复的进行计算
            newarr[i] = Deduplication(grouping);

        }
        return newarr;
    }


}

相加

export default function Deduplication (grouping){//将相邻且相同的数字相加
    for (let i = 0; i < grouping.length; i++) {
        if (typeof grouping[i] == 'object') {
    
            grouping[i] = grouping[i][0] + grouping[i][1];
        }
    }
    return grouping;
}

添加占位用的零

export default function AddZero (newarr,w){//加零
    for (let i = 0; i < newarr.length; i++) {
        while (newarr[i].length != 4) {
            if(w == 'l'){
                newarr[i].push(0);
            }else if(w == 'r'){

                newarr[i].unshift(0);
            }
        }
    }
    return newarr;
}

上下的处理

将 Y 轴的处理转换成 X 轴的处理

export default function turn(arr) {//将数组转一下
    let clearZero = [[],[],[],[]];
    for (let i = 0; i < 4; i++) {
        for (let j = 0; j < 4; j++) {
            clearZero[i][j] = arr[j][i]
        }
    }
    return clearZero;
}

等处理完成后再调用上边的函数,将 X 轴的处理结果转换回 Y 轴的表现方式


http://www.niftyadmin.cn/n/4223547.html

相关文章

网络带宽和延迟测试

网络带宽和延迟测试 Linux 下使用 qperf命令来测试网络带宽和网络延迟 若是没有安装 qperf命令&#xff0c;请使用 yum 命令安装即可 测试步骤 找两台机器&#xff0c;一个作为qperf的服务端&#xff0c;一台作为客户端测试 服务端 [rootlocalhost ~]# qperf------- 系统…

模拟实现 JS 引擎:深入了解 JS机制 以及 Microtask and Macrotask

如果JavaScript是单线程的&#xff0c;那么我们如何像在Java中那样创建和运行线程&#xff1f; 很简单&#xff0c;我们使用events或设定一段代码在给定时间执行&#xff0c;这种异步性在 JavaScript 中称为 event loop。 在这篇文章中&#xff0c;主要想分析两个点&#xff1a…

centos 中文man手册安装

中文man手册安装包地址https://src.fedoraproject.org/repo/pkgs/man-pages-zh-CN/ wget https://src.fedoraproject.org/repo/pkgs/man-pages-zh-CN/manpages-zh-1.5.1.tar.gz/13275fd039de8788b15151c896150bc4/manpages-zh-1.5.1.tar.gz tar fx manpages-zh-1.5.1.tar.gz …

nexus学习 一、nexus介绍及手动安装

一、Neuxs介绍 ​ Nexus是一个强大的Maven仓库管理器&#xff0c;它极大的简化了本地内部仓库的维护和外部仓库的访问。 ​ Nexus是一个强大的Maven仓库管理器&#xff0c;它极大的简化了本地内部仓库的维护和外部仓库的访问。 ​ 如果使用了公共的Maven仓库服务器&#xff0c…

python-web自动化环境安装

web自动化环境安装 1、安装selenium 命令行使用以下命令安装selenium&#xff1a;pip install -U selenium 2、安装chrome浏览器 3、chromedriver的下载 &#xff1a; chromedriver放到python安装根目录下面即可 chromedriver下载地址&#xff1a;http://npm.taobao.org/…

GlobeControl 做鹰眼图

之前在网上看的都是mapcontrol做鹰眼的例子&#xff0c;还一个是globe作为主视图&#xff0c;mapcontrol作为鹰眼的例子&#xff0c;自己根据鹰眼的原理&#xff0c;写了一个&#xff0c;大致说下我的思路&#xff1a;1、添加mapcontrol的OnExtentUpdated方法2、在globecontrol…

1.5.1 Python函数初识

一、为什么要使用函数&#xff1f; 1,避免代码重用 2,提高代码的可读性 二、函数的定义与调用 1,函数定义: def func(): 函数注释print&#xff08;函数体&#xff09;return 返回值 复制代码 定义&#xff1a;def关键字开头&#xff0c;空格之后接函数名和圆括号&#xff0c;…

k8s介绍性文章索引

2019独角兽企业重金招聘Python工程师标准>>> containered替代了docker engine吗&#xff1f; - Kubernetes Containerd集成进入GA阶段转载于:https://my.oschina.net/u/2475751/blog/3003690