第一个算法项目 | JS实现并查集迷宫算法Demo学习

简介: 本文是关于使用JavaScript实现并查集迷宫算法的中国象棋demo的学习记录,包括项目运行方法、知识点梳理、代码赏析以及相关CSS样式表文件的介绍。

0 参考链接

并查集,不就一并和一查?

520,花了一夜给女朋友写了个走迷宫游戏

点击下载并查集迷宫算法JS代码

1 JS代码修改运行方法

首先下载的文件夹如下:
在这里插入图片描述
双击打开maze.html文件。

键盘按F12快捷键。

查看代码如下,右键txt打开maze.html。

修改:

迷宫小游戏到迷宫大游戏

在这里插入图片描述
修改保存后,刷新浏览器。在这里插入图片描述
环境测试完毕!

2 用力梳理知识点

2.1 停止更新条件

游戏连续玩赢3局,就会停止更新棋盘。

这里是show()函数的代码停止条件导致。

    var aa = 14;

    // stop();
    aa=aa+2;
    if(aa==20){ rangeinsert(); stop();}

在这里插入图片描述

2.2 tree和isling傻傻分不清楚

tree和isling数组初始化一样,用途不一样,tree是并查集算法必备的数据结构。

多余的isling,是为了得到逻辑上的联通的路径。

即:判定随机的上下左右是否相连条件后,二维数组isling中相连的格子数值为1。

值为1的格子就算是迷宫中的联通路径。

var tree = [];//存放是否联通
var isling=[];//判断是否相连

在这里插入图片描述
在这里插入图片描述

2.3 doKeyDown(e)函数

doKeyDown(e)函数中,[(x-20)/30*aa+(y-20)/30]中的30是迷宫行高,20是蓝色红色格子的高或宽。

这个是在生成后的迷宫中,对红色格子的位置x和y,进行是否在联通路径中的判定。

涉及到了坐标对应转换,迷宫坐标和逻辑坐标的转换。

        if (keyID === 38 || keyID === 87) { // W键以及上键的移动方向
            if(y-30<0){}
            else if(isling[(x-20)/30*aa+(y-20)/30][((x-20)/30)*aa+(y-20)/30-1]!=1) {}
            else {
                clearCanvas();
                y = y - 30;
                Context.fillRect(x, y, 20, 20);
                e.preventDefault();
                gameover();
                show();
            }
        }

2.4 路径压缩

查找途中能不能路径压缩

每次查询,自下向上。当我们调用递归的时候,可以顺便压缩路径(将当前数组的值等于递归返回的根节点的值),我们查找一个元素只需要直接找到它的祖先,所以当它距离祖先近那么下次查询就很快。并且压缩路径的代价并不大!

试想一下,如果一个分支的深度为1000,不压缩路径那么这个分支每个节点平均查找次数为500,压缩一次下次再查找就是1次。

学会路径压缩,你基本可以秒杀大部分并查集的题。

在移动中要注意不能隔空穿墙、越界。那么怎么判断呢?很好办,移动前目标方格,我们判断其是否直接联通,注意是直接联通而不是联通(很可能绕一圈联通但不能直接越过去,所以这里并查集不能压缩路径哦),如果直接不连通,那么不进行操作,否则进行方块移动。

路径压缩代码:

public int search(int a)//返回头节点的数值
{
    if(tree[a]>0)//说明是子节点
    {
        return tree[a]=search(tree[a]);//压缩路径(将当前数组的值等于递归返回的根节点的值)
    }
    else
        return a;
}

非路径压缩代码:

function search(a)//找到根节点
{
    if(tree[parseInt(a/aa)][a%aa]>0)//说明是子节点
    {
        return search(tree[parseInt(a/aa)][a%aa]);//不能压缩路径
    }
    else
        return a;
}

2.5 某处迷宫墙随机生成

随机选取上下左右的迷宫墙代码:

ran是[0,3]中的一个。

function getnei(a)//获得邻居号  random
{
    var x=parseInt(a/aa);//要精确成整数
    var y=a%aa;
    var mynei=new Array();//储存邻居
    if(x-1>=0){mynei.push((x-1)*aa+y);}//上节点
    if(x+1<14){mynei.push((x+1)*aa+y);}//下节点
    if(y+1<14){mynei.push(x*aa+y+1);}//有节点
    if(y-1>=0){mynei.push(x*aa+y-1);}//下节点
    var ran=parseInt(Math.random() * mynei.length );
    return mynei[ran];

}

2.6 drawline()函数

drawline()函数是绘制白色的边框线,再擦除格子线条。

        context.strokeStyle = 'white';
        context.clearRect(29+x3*30, y3*30+16,2,28);

2.7 Canvas API

Canvas API 提供了一个通过JavaScript 和 HTML的元素来绘制图形的方式。它可以用于动画、游戏画面、数据可视化、图片编辑以及实时视频处理等方面。

Canvas API

canvas提供了三种方法绘制矩形:

fillRect(x, y, width, height)

绘制一个填充的矩形

strokeRect(x, y, width, height)

绘制一个矩形的边框

clearRect(x, y, width, height)

清除指定矩形区域,让清除部分完全透明。

fillStyle = color

设置图形的填充颜色。

strokeStyle = color

设置图形轮廓的颜色。

2.8 css样式表文件

下面的a是在maze.css中定义的。

 <a href="https://blog.csdn.net/qq_40693171">女神</a>

maze.css中的a

a {
   
    text-decoration:none;
    color:#000;
}

3 代码赏析

引用文中代码—>并查集,不就一并和一查?

import java.util.Scanner;
public class DisjointSet {
   
    static int tree[]=new int[100000];//假设有500个值
    public DisjointSet()    {
   set(this.tree);}
    public DisjointSet(int tree[]) 
    {
   
        this.tree=tree;
        set(this.tree);
    }
  //初始化所有都是-1 有两个好处,这样他们指向-1说明是自己,
  //第二,-1代表当前森林有-(-1)个
    public void set(int a[])
    {
   
        int l=a.length;
        for(int i=0;i<l;i++)
        {
   
            a[i]=-1;
        }
    }
    public int search(int a)//返回头节点的数值
    {
   
        if(tree[a]>0)//说明是子节点
        {
   
            return tree[a]=search(tree[a]);//压缩路径(将当前数组的值等于递归返回的根节点的值)
        }
        else
            return a;
    }
    public int value(int a)//返回a所在树的大小(个数)
    {
   
        if(tree[a]>0)
        {
   
            return value(tree[a]);
        }
        else
            return -tree[a];
    }
    public void union(int a,int b)//表示 a,b所在的树合并
    {
   
        int a1=search(a);//a根
        int b1=search(b);//b根
        if(a1==b1) {
   System.out.println(a+"和"+b+"已经在一棵树上");}
        else {
   
        if(tree[a1]<tree[b1])//这个是负数,为了简单减少计算,不在调用value函数
        {
   
            tree[a1]+=tree[b1];//个数相加  注意是负数相加
            tree[b1]=a1;       //b树成为a的子树,直接指向a;
        }
        else
        {
   
            tree[b1]+=tree[a1];//个数相加  注意是负数相加
            tree[a1]=b1;       //b树成为a的子树,直接指向a;
        }
        }
    }
    public static void main(String[] args)
    {
          
        DisjointSet d=new DisjointSet();
        d.union(1,2);
        d.union(3,4);
        d.union(5,6);
        d.union(1,6);

        d.union(22,24);
        d.union(3,26);
        d.union(36,24);
        System.out.println(d.search(6));    //头
        System.out.println(d.value(6));     //大小
        System.out.println(d.search(22));   //头
        System.out.println(d.value(22));     //大小
    }
}

引用文中代码—>520,花了一夜给女朋友写了个走迷宫游戏


<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" type="text/css" href="css/maze.css">

</head>
<body>
<nav class="navbar">
    <div class="navbar-content-1">
        <a href="https://blog.csdn.net/qq_40693171">&nbsp;&nbsp;&nbsp;</a>
    </div>
    <div class=" container navbar-content">
        <a href="https://blog.csdn.net/qq_40693171">女神</a>
        <a href="https://juejin.im/user/5c944a8bf265da6102098c31">520</a>
        <a href="https://github.com/javasmall">快乐</a>
        <a href="https://github.com/javasmall">bigsai的祝福</a>

    </div>
    <div class="navbar-content-2">
        <a >66</a>
    </div>
</nav>

<div class="container">
    <h1>迷宫小游戏</h1>
    <h4></h4>

    <div class="news-list">
        <div class="news-list-left">
            <canvas id="mycanvas" width="600px" height="600px"></canvas>

        </div>

        <div class="news-list-right">
            <div class="about">
                <h4>关于我们</h4>
                <div class="about-des">
                    <span id="mytime"></span>
                    <button  onclick="start()" >开始游戏</button>
                    <button onclick="stop()">暂停</button>
                    <button onclick="range()">排行榜</button>
                    <button onclick="renovates()">重新开始</button>

                </div>
                <br>
                <img src="image/nushen.jpg" width="100%" height="35%">
            </div>
        </div>
        <footer class="copyright">
            Copyright 2018  All rights reserved.
            <div class="col-xs-12">本站总访问量:666</div>
            <a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=1315426911&site=qq&menu=yes">联系我们&nbsp;&nbsp;&nbsp;</a>
            <div><a href=http://www.miitbeian.gov.cn></a>苏ICP备18027982</div>
        </footer>
    </div>
</div>

<script type="text/javascript">

    var aa=14;
    var chess = document.getElementById("mycanvas");
    var context = chess.getContext('2d');

    //  var context2 = chess.getContext('2d');
    //      context.strokeStyle = 'yellow';
    var tree = [];//存放是否联通
    var isling=[];//判断是否相连
    for(var i=0;i<aa;i++){
   
        tree[i]=[];
        for(var j=0;j<aa;j++){
   
            tree[i][j]=-1;//初始值为0
        }
    }  for(var i=0;i<aa*aa;i++){
   
        isling[i]=[];
        for(var j=0;j<aa*aa;j++){
   
            isling[i][j]=-1;//初始值为0
        }
    }

    function drawChessBoard(){
   //绘画
        for(var i=0;i<aa+1;i++){
   
            context.strokeStyle='gray';//可选区域
            context.moveTo(15+i*30,15);//垂直方向画15根线,相距30px;
            context.lineTo(15+i*30,15+30*aa);
            context.stroke();
            context.moveTo(15,15+i*30);//水平方向画15根线,相距30px;棋盘为14*14;
            context.lineTo(15+30*aa,15+i*30);
            context.stroke();
        }
    }
    drawChessBoard();//绘制棋盘

    //      var mymap=new Array(36);
    //      for(var i=0;i<36;i++)
    //     {mymap[i]=-1;}



    function getnei(a)//获得邻居号  random
    {
   
        var x=parseInt(a/aa);//要精确成整数
        var y=a%aa;
        var mynei=new Array();//储存邻居
        if(x-1>=0){
   mynei.push((x-1)*aa+y);}//上节点
        if(x+1<14){
   mynei.push((x+1)*aa+y);}//下节点
        if(y+1<14){
   mynei.push(x*aa+y+1);}//有节点
        if(y-1>=0){
   mynei.push(x*aa+y-1);}//下节点
        var ran=parseInt(Math.random() * mynei.length );
        return mynei[ran];

    }
    function search(a)//找到根节点
    {
   
        if(tree[parseInt(a/aa)][a%aa]>0)//说明是子节点
        {
   
            return search(tree[parseInt(a/aa)][a%aa]);//不能压缩路径路径压缩
        }
        else
            return a;
    }
    function value(a)//找到树的大小
    {
   
        if(tree[parseInt(a/aa)][a%aa]>0)//说明是子节点
        {
   
            return tree[parseInt(a/aa)][a%aa]=value(tree[parseInt(a/aa)][a%aa]);//不能路径压缩
        }
        else
            return -tree[parseInt(a/aa)][a%aa];
    }
    function union(a,b)//合并
    {
   
        var a1=search(a);//a根
        var b1=search(b);//b根
        if(a1==b1){
   }
        else
        {
   
            if(tree[parseInt(a1/aa)][a1%aa]<tree[parseInt(b1/aa)][b1%aa])//这个是负数(),为了简单减少计算,不在调用value函数
            {
   
                tree[parseInt(a1/aa)][a1%aa]+=tree[parseInt(b1/aa)][b1%aa];//个数相加  注意是负数相加
                tree[parseInt(b1/aa)][b1%aa]=a1;       //b树成为a树的子树,b的根b1直接指向a;
            }
            else
            {
   
                tree[parseInt(b1/aa)][b1%aa]+=tree[parseInt(a1/aa)][a1%aa];
                tree[parseInt(a1/aa)][a1%aa]=b1;//a所在树成为b所在树的子树
            }
        }
    }

    function drawline(a,b)//划线,要判断是上下还是左右
    {
   

        var x1=parseInt(a/aa);
        var y1=a%aa;
        var x2=parseInt(b/aa);
        var y2=b%aa;
        var x3=(x1+x2)/2;
        var y3=(y1+y2)/2;
        if(x1-x2==1||x1-x2==-1)//左右方向的点  需要上下划线
        {
   
            //alert(x1);
            //  context.beginPath();
            context.strokeStyle = 'white';
            //    context.moveTo(30+x3*30,y3*30+15);//
            //   context.lineTo(30+x3*30,y3*30+45);
            context.clearRect(29+x3*30, y3*30+16,2,28);
            //    context.stroke();
        }
        else
        {
   
            //   context.beginPath();
            context.strokeStyle = 'white';
            //  context.moveTo(x3*30+15,30+y3*30);//
            //    context.lineTo(45+x3*30,30+y3*30);
            context.clearRect(x3*30+16, 29+y3*30,28,2);
            //      context.stroke();
        }
    }

    while(search(0)!=search(aa*aa-1))//主要思路
    {
   
        var num = parseInt(Math.random() * aa*aa );//产生一个小于196的随机数
        var neihbour=getnei(num);
        if(search(num)==search(neihbour)){
   continue;}
        else//不在一个上
        {
   
            isling[num][neihbour]=1;isling[neihbour][num]=1;
            drawline(num,neihbour);//划线
            union(num,neihbour);

        }
    }
    var a=aa*30-10,b=aa*30-10;
    var x = 20, y =20;
    function load() {
   
        var canvas = document.getElementById("mycanvas");
        Context = canvas.getContext("2d");
        Context.fillStyle = "blue";
        Context.fillRect(x, y, 20, 20);
        context.fillStyle = "red";
        context.fillRect(a, b, 20, 20);
        Context.fillStyle = "blue";
        canvas.addEventListener('keydown', doKeyDown, true);
        canvas.focus();
        window.addEventListener('keydown', doKeyDown, true);
    }
    load();
    function doKeyDown(e) {
   
        //alert(x+" "+y);
        // console.log(x+" "+y);测试
        var keyID = e.keyCode ? e.keyCode : e.which;//获取按键的Unicode代码值
        if(i==1){
   
            if (keyID === 38 || keyID === 87) {
    // W键以及上键的移动方向
                if(y-30<0){
   }
                else if(isling[(x-20)/30*aa+(y-20)/30][((x-20)/30)*aa+(y-20)/30-1]!=1) {
   }
                else {
   
                    clearCanvas();
                    y = y - 30;
                    Context.fillRect(x, y, 20, 20);
                    e.preventDefault();
                    gameover();
                    show();
                }
            }
            if (keyID === 39 || keyID === 68) {
    // D键以及you键的移动方向
                if(x+30>15+30*aa){
   }
                else if(isling[(x-20)/30*aa+(y-20)/30][((x-20)/30)*aa+(y-20)/30+aa]!=1) {
   }
                else{
   
                    clearCanvas();
                    x=x+30;
                    Context.fillRect(x, y, 20, 20);
                    e.preventDefault();
                    gameover();
                    show();
                }
            }
            if (keyID === 40 || keyID === 83) {
    // S键以及下键的移动方向
                if(y+30>15+30*aa){
   }
                else if(isling[(x-20)/30*aa+(y-20)/30][((x-20)/30)*aa+(y-20)/30+1]!=1) {
   }
                else{
   
                    clearCanvas();
                    y = y + 30;
                    Context.fillRect(x, y, 20, 20);
                    e.preventDefault();
                    gameover();
                    show();
                }
            }
            if (keyID === 37 || keyID === 65) {
    // A键以及zuo向
                if(x-30<0){
   }
                else if(isling[(x-20)/30*aa+(y-20)/30][((x-20)/30)*aa+(y-20)/30-aa]!=1) {
   }
                else{
   
                    clearCanvas();
                    x = x - 30;
                    Context.fillRect(x, y, 20, 20);
                    e.preventDefault();
                    gameover();
                    show();

                }}
        }
    }
    function clearCanvas() {
   //清除之间的痕迹
        Context.clearRect(x-2, y-2, 25, 25)
    }
    var end=false;
    function gameover()
    {
   
        if(x>=a&&y>=b)
        {
   
            end=true;
        }
    }
    function show()
    {
   
        if(end==true)
        {
   
            // stop();
            aa=aa+2;
            if(aa==20){
    rangeinsert(); stop();}
            else{
   
                end=false;
                Context.clearRect(0, 0, 600, 600);

                for(var i=0;i<aa;i++){
   
                    tree[i]=[];
                    for(var j=0;j<aa;j++){
   
                        tree[i][j]=-1;//初始值为0
                    }
                }  for(var i=0;i<aa*aa;i++){
   
                    isling[i]=[];
                    for(var j=0;j<aa*aa;j++){
   
                        isling[i][j]=-1;//初始值为0
                    }
                }
                drawChessBoard();//绘制棋盘
                while(search(0)!=search(aa*aa-1))//主要思路
                {
   
                    var num = parseInt(Math.random() * aa*aa );//产生一个小于196的随机数
                    var neihbour=getnei(num);
                    if(search(num)==search(neihbour)){
   continue;}
                    else//不在一个上
                    {
   
                        isling[num][neihbour]=1;isling[neihbour][num]=1;
                        drawline(num,neihbour);//划线
                        union(num,neihbour);

                    }
                }
                a=aa*30-10,b=aa*30-10;
                x = 20, y =20;
                load();
                // start();
            }
            // alert("游戏成功!共用时:"+str);
        }
    }
    var h=m=s=ms= 0;  //定义时,分,秒,毫秒并初始化为0;
    var time=0;
    var i=0;
    function timer(){
      //定义计时函数
        ms=ms+50;         //毫秒
        if(ms>=1000){
   
            ms=0;
            s=s+1;         //秒
        }
        if(s>=60){
   
            s=0;
            m=m+1;        //分钟
        }
        if(m>=60){
   
            m=0;
            h=h+1;        //小时
        }
        str =toDub(h)+"时"+toDub(m)+"分"+toDub(s)+"秒"+toDubms(ms)+"毫秒";
        mytime = document.getElementById('mytime');
        mytime.innerHTML = str;
        // document.getElementById('mytime').innerHTML=h+"时"+m+"分"+s+"秒"+ms+"毫秒";
    }

    function reset(){
     //重置
        i=1;
        time=setInterval(timer,50);
    }

    function start(){
     //开始
        i=1;
        time=setInterval(timer,50);
    }

    function stop(){
     //暂停
        i=0;
        clearInterval(time);
    }

    function toDub(n){
     //补0操作
        if(n<10){
   
            return "0"+n;
        }
        else {
   
            return ""+n;
        }
    }

    function toDubms(n){
     //给毫秒补0操作
        if(n<10){
   
            return "00"+n;
        }
        else {
   
            return "0"+n;
        }

    }
    function renovates(){
   
        document.location.reload();
    }

    var req;//创建对象 

    function range()
    {
   

        var url = "";//ajax
        //创建一个XMLHttpRequest对象req
        if(window.XMLHttpRequest) {
   
            //IE7, Firefox, Opera支持
            req = new XMLHttpRequest();
        }else if(window.ActiveXObject) {
   
            //IE5,IE6支持
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
        req.open("GET", url, true);
        //onreadystatechange属性存有处理服务器响应的函数,有5个取值分别代表不同状态
        req.onreadystatechange = callback;
        //send函数发送请求
        req.send(null);
    }
    function rangeinsert()
    {
   

        var url = "insertrange?id=" +(m*60+ s);
        //创建一个XMLHttpRequest对象req
        if(window.XMLHttpRequest) {
   
            //IE7, Firefox, Opera支持
            req = new XMLHttpRequest();
        }else if(window.ActiveXObject) {
   
            //IE5,IE6支持
            req = new ActiveXObject("Microsoft.XMLHTTP");
        }
        req.open("GET", url, true);
        //onreadystatechange属性存有处理服务器响应的函数,有5个取值分别代表不同状态
        req.onreadystatechange = callback;
        //send函数发送请求
        req.send(null);
    }
    function callback() {
   
        if(req.readyState == 4 && req.status == 200) {
   
            var check = req.responseText;
            alert(check);
        }
    }
</script>


</body>
</html>

maze.css样式表文件:

canvas{
   
  display: block;
  margin: 50px auto;
  box-shadow: -2px -2px 2px #F3F2F2, 5px 5px 5px #6F6767;

}
body {
   
    margin: 0;
    padding: 0;
    font-family:"Microsoft YaHei", "微软雅黑", "consolas";
    /*background-image: url("");*/
    background-attachment: fixed;
}
a {
   
    text-decoration:none;
    color:#000;
}
.navbar {
   
    background-color:#000;
    width:100%;
    height:50px;
}
.container {
   
    width: 1000px;
    margin: 0 auto;
}
.navbar .navbar-content-1 a {
   
    float: left;
    color: #FFF;
    line-height: 50px;
    display: inline-block;
    width: 90px;
    white-space: nowrap;
    text-align: left;
}
.navbar .navbar-content-2 a {
   
    float: right;
    color: #FFF;
    line-height: 50px;
    display: inline-block;
    width: auto;
    white-space: nowrap;
    text-align: right;
}
.navbar .navbar-content a {
   
    float: left;
    color: #FFF;
    line-height: 50px;
    display: inline-block;
    width: 90px;
    white-space: nowrap;
    text-align: center;
}
.navbar .navbar-content a:hover {
   
    color: #CCC;
}
.news-list {
   
    margin: 50px 0;
    background-color: #FFF;
    border-radius: 15px;
    border: 1px solid #DDD;
    padding: 30px 20px;
    min-height: 300px;
}
.news-list:hover {
   
    box-shadow: 0 0 5px 3px #CCC;
}

.about .about-des {
   
    border-left: 5px solid #abc;
    margin-top: 15px;
}

.about .about-des p {
   
    padding-left: 10px;
    line-height: 28px;
    text-indent: 2em;
}

.news-list-left {
   
    float: left;
    width: 729px;
    margin-bottom: 50px;
}

.news-list-right {
   
    float: right;
    width: 229px;
}
.news-title i {
   
    display: inline-block;
    width: 47px;
    height: 43px;
    margin-right: 10px;
    /*background: url('image/54a1137bbeaa9.jpg') left center no-repeat;*/
    vertical-align: middle;
}
.news-title a {
   
    color: green;
}
.news-title a:hover {
   
    text-decoration: underline;
}
.copyright {
   
    clear: both;
    text-align: center;
    color: gray;
    border-top: 2px solid #CCC;
    margin-top: 50px;
    padding: 20px 0;
}
button {
   
    cursor: pointer;
    width: 150px;
    height: 44px;
    margin-top: 25px;
    padding: 0;
    background: #ef4300;
    -moz-border-radius: 6px;
    -webkit-border-radius: 6px;
    border-radius: 6px;
    border: 1px solid #ff730e;
    -moz-box-shadow:
            0 15px 30px 0 rgba(255,255,255,.25) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
    -webkit-box-shadow:
            0 15px 30px 0 rgba(255,255,255,.25) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
    box-shadow:
            0 15px 30px 0 rgba(255,255,255,.25) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
    font-family: 'PT Sans', Helvetica, Arial, sans-serif;
    font-size: 14px;
    font-weight: 700;
    color: #fff;
    text-shadow: 0 1px 2px rgba(0,0,0,.1);
    -o-transition: all .2s;
    -moz-transition: all .2s;
    -webkit-transition: all .2s;
    -ms-transition: all .2s;
}

button:hover {
   
    -moz-box-shadow:
            0 15px 30px 0 rgba(255,255,255,.15) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
    -webkit-box-shadow:
            0 15px 30px 0 rgba(255,255,255,.15) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
    box-shadow:
            0 15px 30px 0 rgba(255,255,255,.15) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
}

button:active {
   
    -moz-box-shadow:
            0 15px 30px 0 rgba(255,255,255,.15) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
    -webkit-box-shadow:
            0 15px 30px 0 rgba(255,255,255,.15) inset,
            0 2px 7px 0 rgba(0,0,0,.2);
    box-shadow:
            0 5px 8px 0 rgba(0,0,0,.1) inset,
            0 1px 4px 0 rgba(0,0,0,.1);

    border: 0px solid #ef4300;
}

完 谢谢观看

相关文章
|
17天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
数据结构与算法系列学习之串的定义和基本操作、串的储存结构、基本操作的实现、朴素模式匹配算法、KMP算法等代码举例及图解说明;【含常见的报错问题及其对应的解决方法】你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
2024重生之回溯数据结构与算法系列学习之串(12)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丟脸好嘛?】
|
1月前
|
缓存 算法 Java
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
这篇文章详细介绍了Java虚拟机(JVM)中的垃圾回收机制,包括垃圾的定义、垃圾回收算法、堆内存的逻辑分区、对象的内存分配和回收过程,以及不同垃圾回收器的工作原理和参数设置。
60 4
JVM知识体系学习六:JVM垃圾是什么、GC常用垃圾清除算法、堆内存逻辑分区、栈上分配、对象何时进入老年代、有关老年代新生代的两个问题、常见的垃圾回收器、CMS
|
13天前
|
机器学习/深度学习 人工智能 自然语言处理
【EMNLP2024】基于多轮课程学习的大语言模型蒸馏算法 TAPIR
阿里云人工智能平台 PAI 与复旦大学王鹏教授团队合作,在自然语言处理顶级会议 EMNLP 2024 上发表论文《Distilling Instruction-following Abilities of Large Language Models with Task-aware Curriculum Planning》。
|
1月前
|
算法
动态规划算法学习三:0-1背包问题
这篇文章是关于0-1背包问题的动态规划算法详解,包括问题描述、解决步骤、最优子结构性质、状态表示和递推方程、算法设计与分析、计算最优值、算法实现以及对算法缺点的思考。
62 2
动态规划算法学习三:0-1背包问题
|
17天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习(8)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
17天前
|
算法 安全 搜索推荐
2024重生之回溯数据结构与算法系列学习之单双链表精题详解(9)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第2.3章之IKUN和I原达人之数据结构与算法系列学习x单双链表精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
存储 Web App开发 算法
2024重生之回溯数据结构与算法系列学习之单双链表【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构之单双链表按位、值查找;[前后]插入;删除指定节点;求表长、静态链表等代码及具体思路详解步骤;举例说明、注意点及常见报错问题所对应的解决方法
|
17天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
17天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明