js实现动漫拼图2.0版

news2024/12/23 22:21:34

比较与1.0版,2.0版就更像与华容道类似的拼图游戏,从头到尾都只能控制白色块移动,而且打乱拼图和求助的实现与1.0都不相同

文章目录

  • 1 实现效果
  • 2 实现思路
    • 2.1 打乱拼图
    • 2.2 求助功能
    • 2.3 判赢
  • 3 代码实现

js实现动漫拼图1.0版
https://blog.csdn.net/m0_58730471/article/details/135891948?spm=1001.2014.3001.5501

1 实现效果

在这里插入图片描述

拼图2.0

2 实现思路

思路相同的就不在重复赘述,直说我感觉比较难的点或不同的点。

2.1 打乱拼图

这里的打乱不同于1.0版本的,1.0版本的打乱是随机产生x,y两个索引值,然后将该索引值对应元素与x0,y0对应的位置元素交换, 但是有可能产生无解的情况(就直接跨好几格,直接两者交换那种),一步一步就无法还原,而1.0版是可以手动选择原点的,所以就变成了有解。
而这里2.0版本,原点只有一个,无法手动更改,只能一步一步走,那么如果仍是随机产生x,y两个索引值,就可能产生无解的情况所以这里改为随机产生0-3,代表四个方向,让白块在随机的方向上走动n次(n<difficulty,因为有可能随机产生的某个方向走不了已经到边界了),这样一定是有解的,至少原路后退就是一种解。 通过这种交换n次实现打乱的效果。

/*
   
        */
        // 打乱图片
        // 随机产生0-3 代表四个方向 0-左,1-上 2-右 3-下 
        function shuffle() {
            for (let i = 0; i < difficulty; i++) {
                let x = parseInt(Math.random() * 4);
                if (x == 0) {
                    direction = 'left';
                } else if (x == 1) {
                    direction = 'up';
                } else if (x == 2) {
                    direction = 'right';
                } else if (x == 3) {
                    direction = 'down';
                }
                move(direction);
            }
        }

2.2 求助功能

这里通过定义trace,规定0-3代表的方向[0-左 1-上 2-右 3-下],在打乱图片和玩家移动的时候记录下所走的顺序,最后倒着走(从尾部取元素pop,根据值,做反向操作),就可以实现求助(这里的求助并不完美)
在这里插入图片描述
在move里面去记录顺序(trace里面添值)
在这里插入图片描述

 // 求助按钮
        // 通过trace的记录情况,进行后退,就可以还原最终的拼图
        function helpBake() {
            // 调用trace去重函数
            distinctTrace();
            // 从trace数组中取出最后一个元素
            let lastDir = trace.pop();
            // 判断方向,反方向移动(回退)
            if (lastDir == 0) {
                direction = 'right';
            } else if (lastDir == 1) {
                direction = 'down';
            } else if (lastDir == 2) {
                direction = 'left';
            } else if (lastDir == 3) {
                direction = 'up';
            }
            // 调用移动函数(移动函数中,每正确交换一次,都会trace.push()这次记录)
            move(direction);
            // trace.push()在这里是无用的,所以需要在pop一次
            trace.pop();
        }

问题:
trace里面记录的数据都是有用的吗?
会不会产生左右,左左右右,上下,上上下下等原地踏步的情况,答案是肯定的(至少在打乱图片时,随机产生的索引就会有这种情况),所以我们还需要对trace数组进行一个无效步骤去除的操作

// 但是,上面直接通过后退trace,里面存放的元素可能会导致多余步骤:
        /*  0 向左,1向上,2向右,3向下
        比如:trace[2 0 3 1 1 3 0 2]  模拟后退情况
        就先左走,又右走(原地),又向上再向下(原地),又向下再向上(原地),又右走再左走(原地),最终后退这么多步,最后就是呆在原地
        所以,需要对trace进行去重处理
        */
        function distinctTrace() {
            let index = findDistinctIndex();

            // 有重复的,删除
            while (index != -1) {
                trace.splice(index, 2);
                index = findDistinctIndex();
            }
        }
        // 查找相邻的矛盾无用索引
        function findDistinctIndex() {
            let index = -1;
            // trace 是一维数组,相邻两个比较,比较次数就是数组长度-1
            // 例如: arr[1 2 3 4] 四个元素,相邻的元素比较 1和2比一次,2和3比一次,3和4比一次,所以比较次数就是3次
            for (let i = 0; i < trace.length - 1; i++) {
                let front = trace[i];
                let behind = trace[i + 1];
                // 情况:(左右)(右左)(上下)(下上)都是原地,需要去重
                if ((front == 0 && behind == 2) || (front == 2 && behind == 0) || (front == 1 && behind == 3) || (
                        front == 3 && behind == 1)) {
                    index = i;
                    break;
                }
            }
            return index;
        }

2.3 判赢

这里有所不同的是,最后的一个值不在是16,而是0(因为0.png是白色背景块,在初始化时,将16换成了0,在ui里面动态拼接时,就是白色背景块了)

// 判断是否胜利,
        function judgeVictory() {
            let right = true;
            print.forEach((subArr, i) => {
                subArr.forEach((data, j) => {
                    if (i == 3 && j == 3) {
                        if (print[i][j] != 0) {
                            right = false;
                        }
                    } else {
                        let index = i * 4 + j;
                        if (print[i][j] != index + 1) {
                            right = false;
                        }
                    }

                })
            })
            return right;
        }

3 代码实现

代码下载:https://www.alipan.com/s/WrkusEaP8Uq

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            background-image: url('./images/background.png');
        }

        .first {
            text-align: center;
            margin-top: 20px;
            margin-bottom: 20px;
        }

        td {
            width: 100px;
            height: 100px;
            background-image: url('./images/1.png');
            background-size: 100% 100%;
            background-repeat: no-repeat;
        }

        .second {
            width: 60%;
            margin: 0 auto;
            display: flex;
        }

        .second_right {
            margin-left: 200px;
        }

        .third {
            margin-top: 20px;
            text-align: center;
        }

        #step {
            font-size: 30px;
            color: red;
            display: inline-block;
            width: 80px;
            box-sizing: border-box;
            text-align: center;
        }

        .change {
            width: 100px;
            height: 40px;
            font-size: 20px;
            background-color: #da3c24;
            border-radius: 10px;
            color: #fedcdc;
        }

        #look {
            width: 200px;
            height: 200px;
            background-repeat: no-repeat;
            background-size: 100% 100%;
            border: 4px solid white;
        }
    </style>
</head>

<body>
    <audio src="./audio/bg.mp3" id="bgMusic"></audio>
    <div class="first">
        <button class="change">更换图片</button>
        <img src="./images/title.png" alt="">
    </div>
    <div class="second">
        <div class="second_left">
            <table>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
                <tr>
                    <td></td>
                    <td></td>
                    <td></td>
                    <td></td>
                </tr>
            </table>
        </div>
        <div class="second_right">
            <div style="margin-bottom: 40px;">
                <img src="" id="look">
            </div>
            <div style="margin-bottom: 30px; font-size: 25px; color:aliceblue">
                已经走了
                <span id="step">0</span></div>
            <div>
                <div style="text-align: center;">
                    <img src="./images/shang.png" id="up">
                </div>
                <div style="text-align: center;">
                    <img src="./images/zuo.png" id="left">
                    <img src="./images/xia.png" id="down">
                    <img src="./images/you.png" id="right">
                </div>
            </div>
        </div>
    </div>
    <div class="third">
        <img src="./images/chongzhi.png" id="rest">
        <img src="./images/qiuzhu.png" id="help">
        <div style="color: aliceblue;">点击重置按钮(开始游戏或者重新打乱顺序)</div>
    </div>
    <script>
        let print = [
            [1, 2, 3, 4],
            [5, 6, 7, 8],
            [9, 10, 11, 12],
            [13, 14, 15, 16]
        ];
        let tds = document.querySelectorAll('td');
        let isStart = false;
        let isRest = false;
        // 记录特殊格子坐标(白色格)
        let x0, y0;
        // 记录移动方向
        let direction = '';
        // 随机交换的次数
        let difficulty = 40;
        // 记录已经走的路径,方便后面实现帮助功能
        // 0-左 1-上 2-右 3-下
        let trace = [];
        // 移动步子
        let step = 0;
        // 更换背景拼图
        let photo = 'images_1';
        // 获取对应html元素
        let leftBtn = document.getElementById('left'); //左键
        let rightBtn = document.getElementById('right'); //右键
        let upBtn = document.getElementById('up'); //上键
        let downBtn = document.getElementById('down'); //下键
        let stepSpan = document.getElementById('step'); //移动步数
        let helpBtn = document.getElementById('help'); //求助按钮
        let changeBtn = document.querySelector('.change'); //更换背景拼图按钮
        let look = document.getElementById('look'); //显示背景拼图的图片
        let restBtn = document.getElementById('rest'); //重新开始按钮
        // 初始化背景拼图(默认显示)
        look.src = './images/images_1/canzhaotu.png';
        let bgMusic = document.getElementById('bgMusic');
        // 初始化游戏界面
        updateUI();
        // 监听按钮点击事件
        window.onkeyup = function (e) {
            if (isStart) {
                if (e.keyCode == 37) {
                    direction = 'left';
                    move(direction);
                } else if (e.keyCode == 38) {
                    direction = 'up';
                    move(direction);
                } else if (e.keyCode == 39) {
                    direction = 'right';
                    move(direction);
                } else if (e.keyCode == 40) {
                    direction = 'down';
                    move(direction);
                }
            }
        }
        // 开始或重置
        restBtn.onclick = function () {
            // 初始化
            step = 0;
            bgMusic.play();
            print = [
                [1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12],
                [13, 14, 15, 16]
            ]
            //初始化白格
            print[3][3] = 0;
            trace = [];
            //记录原始位置
            x0 = 3;
            y0 = 3;
            // 点击重置不判断输赢
            isRest = true;
            // 打乱图片
            shuffle();
            // 更新ui
            updateUI();
            // 游戏开始
            isStart = true;
            isRest = false;
            // 给求助按钮添加事件
            helpBtn.onclick = helpBake;
        }
        // 控制移动(游戏开始可以移动)
        leftBtn.onclick = function () {
            if (isStart) {
                direction = 'left';
                move(direction);
            }
        }
        rightBtn.onclick = function () {
            if (isStart) {
                direction = 'right';
                move(direction);
            }
        }
        upBtn.onclick = function () {
            if (isStart) {
                direction = 'up';
                move(direction);
            }
        }
        downBtn.onclick = function () {
            if (isStart) {
                direction = 'down';
                move(direction);
            }
        }
        // 更换拼图图片
        changeBtn.onclick = function () {
            isStart = false;
            print = [
                [1, 2, 3, 4],
                [5, 6, 7, 8],
                [9, 10, 11, 12],
                [13, 14, 15, 16]
            ]
            trace = [];
            step = 0;
            // 随机产生1-4的索引值
            let index = parseInt(Math.random() * 4) + 1;
            let photo_id = look.src.split('/')[look.src.split('/').length - 2].split('_')[1];
            // 确保新的索引值和原来的不是一个,确保图片更换
            while (index == photo_id) {
                index = parseInt(Math.random() * 4) + 1;
            }
            photo = 'images_' + index;
            look.src = "./images/" + photo + "/canzhaotu.png";
            updateUI();
        }

        // 更新UI
        function updateUI() {
            print.forEach((subArr, i) => {
                subArr.forEach((item, j) => {
                    tds[i * 4 + j].style.backgroundImage = "url(./images/" + photo + "/" + item +
                        ".png)";
                })
            })
            stepSpan.innerHTML = step;
            if (isStart && judgeVictory() && !isRest) {
                alert("恭喜你,成功通关!");
                isStart = false;
                setTimeout(() => {
                    print[3][3] = 16;
                    updateUI();
                }, 100)
            }
        }

        /*
            这里的打乱不同于1.0版本的,
            1.0版本的打乱是随机产生x,y两个索引值,然后将该索引值对应元素与x0,y0对应的位置元素交换,
            但是有可能产生无解的情况(就直接跨好几格,直接两者交换那种),一步一步就无法还原,而1.0版是可以手动选择原点的,所以就变成了有解。
            而这里2.0版本,原点只有一个,无法手动更改,只能一步一步走,那么如果仍是随机产生x,y两个索引值,就可能产生无解的情况
            所以这里改为随机产生0-3,代表四个方向,让白块在随机的方向上走动n次(n<difficulty,因为有可能随机产生的某个方向走不了已经到边界了),
            这样一定是有解的,至少原路后退就是一种解。
        */
        // 打乱图片
        // 随机产生0-3 代表四个方向 0-左,1-上 2-右 3-下 
        function shuffle() {
            for (let i = 0; i < difficulty; i++) {
                let x = parseInt(Math.random() * 4);
                if (x == 0) {
                    direction = 'left';
                } else if (x == 1) {
                    direction = 'up';
                } else if (x == 2) {
                    direction = 'right';
                } else if (x == 3) {
                    direction = 'down';
                }
                move(direction);
            }
        }

        // 移动交换图片
        function move(direction) {
            let x, y;
            let dir = -1;
            if (direction == 'left') {
                if (y0 - 1 < 0) {
                    console.log("左边到边界了");
                    return;
                } else {
                    x = x0;
                    y = y0 - 1;
                    dir = 0;
                }
            } else if (direction == 'right') {
                if (y0 + 1 > 3) {
                    console.log("右边到边界了");
                    return;
                } else {
                    x = x0;
                    y = y0 + 1;
                    dir = 2;
                }
            } else if (direction == 'up') {
                if (x0 - 1 < 0) {
                    console.log("上边到边界了");
                    return;
                } else {
                    x = x0 - 1;
                    y = y0;
                    dir = 1;
                }
            } else if (direction == 'down') {
                if (x0 + 1 > 3) {
                    console.log("下边到边界了");
                    return;
                } else {
                    x = x0 + 1;
                    y = y0;
                    dir = 3;
                }
            }
            // 这里就是记录走的情况(包括了打乱的顺序和玩家点击走的顺序)
            trace.push(dir);
            // 不是打乱顺序时,开始记录步数
            if (!isRest) {
                step++;
            }
            let temp = print[x][y];
            print[x][y] = print[x0][y0];
            print[x0][y0] = temp;
            // 更新坐标位置
            x0 = x;
            y0 = y;
            updateUI();
        }
        // 判断是否胜利,
        function judgeVictory() {
            let right = true;
            print.forEach((subArr, i) => {
                subArr.forEach((data, j) => {
                    if (i == 3 && j == 3) {
                        if (print[i][j] != 0) {
                            right = false;
                        }
                    } else {
                        let index = i * 4 + j;
                        if (print[i][j] != index + 1) {
                            right = false;
                        }
                    }

                })
            })
            return right;
        }
        // 求助按钮
        // 通过trace的记录情况,进行后退,就可以还原最终的拼图
        function helpBake() {
            // 调用trace去重函数
            distinctTrace();
            // 从trace数组中取出最后一个元素
            let lastDir = trace.pop();
            // 判断方向,反方向移动(回退)
            if (lastDir == 0) {
                direction = 'right';
            } else if (lastDir == 1) {
                direction = 'down';
            } else if (lastDir == 2) {
                direction = 'left';
            } else if (lastDir == 3) {
                direction = 'up';
            }
            // 调用移动函数(移动函数中,没正确交换一次,都会trace.push()这次记录)
            move(direction);
            // trace.push()在这里是无用的,所以需要在pop一次
            trace.pop();
        }
        // 但是,上面直接通过后退trace,里面存放的元素可能会导致多余步骤:
        /*  0 向左,1向上,2向右,3向下
        比如:trace[2 0 3 1 1 3 0 2]  模拟后退情况
        就先左走,又右走(原地),又向上再向下(原地),又向下再向上(原地),又右走再左走(原地),最终后退这么多步,最后就是呆在原地
        所以,需要对trace进行去重处理
        */
        function distinctTrace() {
            let index = findDistinctIndex();

            // 有重复的,删除
            while (index != -1) {
                trace.splice(index, 2);
                index = findDistinctIndex();
            }
        }
        // 查找相邻的矛盾无用索引
        function findDistinctIndex() {
            let index = -1;
            // trace 是一维数组,相邻两个比较,比较次数就是数组长度-1
            // 例如: arr[1 2 3 4] 四个元素,相邻的元素比较 1和2比一次,2和3比一次,3和4比一次,所以比较次数就是3次
            for (let i = 0; i < trace.length - 1; i++) {
                let front = trace[i];
                let behind = trace[i + 1];
                // 情况:(左右)(右左)(上下)(下上)都是原地,需要去重
                if ((front == 0 && behind == 2) || (front == 2 && behind == 0) || (front == 1 && behind == 3) || (
                        front == 3 && behind == 1)) {
                    index = i;
                    break;
                }
            }
            return index;
        }
    </script>
</body>

</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1419179.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【千亿生意】一张眼底图,浮现你未来十年身体1000多种疾病风险

【千亿生意】一张眼底图&#xff0c;浮现你未来十年身体1000多种疾病风险 一眼看全身鹰瞳思路眼底看全身论文眼底成像技术眼底看肝脏眼底看多囊卵巢综合征眼底看肺部眼底看贫血眼底看少肌症眼底看神经退行眼底看心血管眼底看肾脏 鹰瞳视网膜论文 一眼看全身 眼病&#xff0c;是…

Redisson分布式锁介绍及实战应用(防止缓存击穿)

本地锁 浏览器把100w请求由网关随机往下传&#xff0c;在集群情况下&#xff0c;每台服务都放行10w请求过来&#xff0c;这时候每台服务都用的是本地锁是跨JVM的&#xff0c; 列如这些服务都没有49企业&#xff0c;此时有几个服务进行回原了打击在DB上面&#xff0c;那后期把这…

fastapi报错

初始化报错&#xff0c;非常低级错&#xff0c;扇自己10八张 app FastApi()

如何在Shopee越南站点进行有效的选品

在如今的电商市场中&#xff0c;选品是卖家们取得成功的关键之一。在Shopee越南站点进行选品时&#xff0c;卖家可以采取一些策略来提高产品的竞争力和销售业绩。本文将介绍一些有效的选品策略&#xff0c;帮助卖家在Shopee越南站点取得成功。 先给大家推荐一款shopee知虾数据…

算法沉淀——二分查找(leetcode真题剖析)

算法沉淀——二分查找 01.二分查找02.在排序数组中查找元素的第一个和最后一个位置03.搜索插入位置04.x 的平方根05.山脉数组的峰顶索引06.寻找峰值07.寻找旋转排序数组中的最小值08.LCR 173. 点名 二分查找&#xff08;Binary Search&#xff09;是一种在有序数组中查找特定元…

【服务器APP】利用HBuilder X把网页打包成APP

目录 &#x1f33a;1. 概述 &#x1f33c;1.1 新建项目 &#x1f33c;1.2 基础配置 &#x1f33c;1.3 图标配置 &#x1f33c;1.4 启动界面配置 &#x1f33c;1.5 模块配置 &#x1f33c;1.6 打包成APP &#x1f33a;1. 概述 探讨如何将网页转化为APP&#xff0c;这似乎…

【大厂AI课学习笔记】1.3 人工智能产业发展(1)

我国人工智能政策&#xff0c;分为5个阶段。从探索期&#xff0c;到后面的4个阶段。 MORE:&#xff08;以下为文心一言4.0的参考内容&#xff0c;和腾讯课程资料的分阶段&#xff0c;略有不同&#xff09; 我国的人工智能政策发展可以大致分为以下几个阶段&#xff0c;每个阶段…

网络防御安全知识(第三版)

配置黑洞路由 --- 黑洞路由即空接口路由&#xff0c;在NAT地址池中的地址&#xff0c;建议配置达到这个地址指 向空接口的路由&#xff0c;不然&#xff0c;在特定环境下会出现环路。&#xff08;主要针对地址池中的地址和出接口地址 不再同一个网段中的场景。&#xff09; …

一文解锁——那些你不太了解的AI!

ChatGPT现象级走红&#xff0c;国内也有文心一言等模型紧随其后&#xff0c;彻底将大语言模型送上大热门。 不管是你是否深度应用过这些模型&#xff0c;不可否认的是&#xff0c;AI已经彻底地融入我们的生活&#xff0c;甚至成为赚钱利器。除了ChatGPT和百度的文心一言&#…

力扣712. 两个字符串的最小ASCII删除和

动态规划 思路&#xff1a; 假设 dp[i][j] 是 s1 长度 i 和 s2 长度 j 两个字符串的最小 ASCII 删除和&#xff1b;dp[i][j] 可以由&#xff1a; 如果 s1 的第 i 个字符&#xff08;s1[i - 1]&#xff09;和 s2 的第 j 个字符&#xff08;s2[j - 1]&#xff09;不相等&#xf…

详解SpringCloud微服务技术栈:ElasticSearch实战(旅游类项目)

&#x1f468;‍&#x1f393;作者简介&#xff1a;一位大四、研0学生&#xff0c;正在努力准备大四暑假的实习 &#x1f30c;上期文章&#xff1a;详解SpringCloud微服务技术栈&#xff1a;ElasticSearch实践2——RestClient查询并处理文档 &#x1f4da;订阅专栏&#xff1a;…

【JavaScript 基础入门】01 编程语言和计算机基础

编程语言和计算机基础 目录 编程语言和计算机基础1 - 编程语言1.1 编程1.2 计算机语言1.3 编程语言1.4 翻译器1.5 编程语言和标记语言区别1.6 总结 2 - 计算机基础2.1 计算机组成2.2 数据存储2.3 数据存储单位2.4 程序运行 1 - 编程语言 1.1 编程 编程&#xff1a; 就是让计算…

运放反馈电阻上并联小电容的作用

这是一个同相比例运算放大电路&#xff0c; Rf是反馈电阻 有的电路还会在反馈电阻上并联一个小电容&#xff0c;一般在几pF到几十pF。 那么这个电容有什么作用呢&#xff1f;其实这个电容是一个相位补偿电容&#xff0c;防止运放自激振荡的。另外这个电容也有抑制高频噪声的作用…

GoogleNet Inception v2 和 Inception v3详解

1 GoogleNet Inception v2 v1具体结构&#xff1a; v2具体结构&#xff1a; 1 引入Batch Normalization&#xff08;BN&#xff09;: Inception v2在每个卷积层之后引入了BN。这有助于解决深层网络中的梯度消失问题&#xff0c;同时加快训练过程并提高模型的收敛速度。BN通过…

鸿蒙首批原生应用!无感验证已完美适配鸿蒙系统

顶象无感验证已成功适配鸿蒙系统&#xff0c;成为首批鸿蒙原生应用&#xff0c;助力鸿蒙生态的快速发展。 作为全场景分布式操作系统&#xff0c;鸿蒙系统旨在打破不同设备之间的界限&#xff0c;实现极速发现、极速连接、硬件互助、资源共享。迄今生态设备数已突破8亿台&…

[论文阅读] |RAG评估_Retrieval-Augmented Generation Benchmark

写在前面 检索增强能够有效缓解大模型存在幻觉和知识时效性不足的问题&#xff0c;RAG通常包括文本切分、向量化入库、检索召回和答案生成等基本步骤。近期组里正在探索如何对RAG完整链路进行评估&#xff0c;辅助阶段性优化工作。上周先对评估综述进行了初步的扫描&#xff0…

PAT-Apat甲级题1003(python和c++实现)下

PTA | 1003 Emergency 书接上回&#xff0c;上次我们使用了python实现无向带权图与DFS算法的设计&#xff0c;本次我们将使用C对本题进行解答&#xff0c;思路和题目分析同上一节内容&#xff0c;本次我们将在上一节的基础上继续实现。 okok现在又是激动人心的手搓代码时间&a…

JMeter性能测试实战

&#x1f525; 交流讨论&#xff1a;欢迎加入我们一起学习&#xff01; &#x1f525; 资源分享&#xff1a;耗时200小时精选的「软件测试」资料包 &#x1f525; 教程推荐&#xff1a;火遍全网的《软件测试》教程 &#x1f4e2;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1…

喝酒筛子小游戏集合源码微信小程序喝酒骰子程序带流量主版本源码酒桌玩筛子源码

2023新版酒桌小游戏喝酒小程序源码-&#xff08;流量主版本&#xff09; 修改增加了广告位 根据文档直接替换&#xff0c;原版本没有广告位 直接上传源码到开发者端即可 通过后改广告代码&#xff0c;然后关闭广告展示提交&#xff0c;通过后打开即可 无广告引流 流量主版…

Spring MVC 基本知识

知识回顾 Tomcat 是 Servlet 容器&#xff0c;会解析 Java Web 应用下的 WEB-INF/web.xml 文件&#xff0c;得到相关的 Servlet 组件。 原理解析 Spring MVC 实际是定义了一个 DispatcherSevlet 来统一管理当前 Web 应用下的 Path 路径。在 DispatchSevlet 中持有了一个 Spr…