学习记录,利用canvas写扫雷游戏

记录js学习后制作的第一关小游戏。

这里的代码还不够精简,许多地方偷懒没有封装,逻辑也有许多可以优化。

<body>

    胜利条件,找出所有地雷并标记
    <form action="javaScript:createContent()">
        <div id="message" style="color: red; display: none;">地雷数量必须小于地图大小xy的平方</div>
        <br /> 
        地图大小xy :<input id="xyNum" type="number" required="true" name="points" min="1" max="50"  /> 
        booNum:<input id="booNum" type="number" required="true" name="points" min="1" max="2500"/>
        <input type="submit" value="OK" : />
        <br /> 1. 输入宽度 <br />2. 输入地雷数(地雷数小于宽*宽) <br /> 3. 单击确定  <br />
        鼠标右键:<br />
        第一次:标记您的猜测<br />
        第二次: 取消标签<br />
    </form>
    <div id= 'game'>

    </div>
    <script src="./js/MarkObs.js"></script>
    <script src="./js/Isboo.js"></script>
    <script src="./js/lei.js"></script>
    <script>
    let xy = document.getElementById('xyNum');
    let boo = document.getElementById('booNum');
    let meg = document.getElementById("message");
    let div = document.getElementById('game');

    //获取输入的宽高和地雷数
    createContent = function (){
            // console.log(xy.value);
            // console.log(boo.value);
            let xyNum = xy.value; 
            let booNum = boo.value; 
            // console.log(Math.pow(xyNum,2));
            
            //判断输入是否合法
            if(Math.pow(xyNum,2)<boo.value){
                meg.style.display = 'block';
            }
            else {//绘制地图
                div.innerHTML = '';//清除上次div里的地图
                let game = new Game('game',xyNum,booNum);
            }
        }
    </script>
</body>

 lei.js

/* 一个自定义原型数组方法  可以放到html里
二维数组查找
arr:要找数组第一第二项 找到返回下标,没有返回-1
PS:只要this数组和arr数组第一第二项的值相等,即为找到。
*/
Array.prototype.myindexOf = function(arr){
    for(let i=0;i<this.length;i++){
        
        if((this[i][0] == arr[0]) &&(this[i][1]==arr[1])){
            return i;
        }
    }
    return -1;
}
/*
初始化地雷图
id:传入绘制地图的容器id
xyNum:长||宽的格子数(地图固定正方形)
booNum:地雷数
*/ 
class Game {
    constructor(id,xyNum,booNum){
        this.xyNum = xyNum;
        this.booNum = booNum;
        this.id = id;

        this.booArrs = [];//保存雷的位置
        this.boox = -1;//地雷在x轴第几个块
        this.booy = -1;//地雷在x轴第几个块

        this.numArrs = [];//保存提醒数字的位置以及数字
        this.num = 0;//保存找到的提醒数字的个数

        this.markArrs = [];//保存标记位置的数组

        //单个块的宽高
        this.divw = 20;

        // 初始化画布
        this.initCanvas(xyNum);
        // 初始化地雷位置(地雷用-1代替,图片绘制麻烦)
        this.initBooxy(xyNum,booNum);
        // 初始化遮挡物
        this.initObs(xyNum);

        //判断是否胜利
        this.win();
    

    }
    /*初始化画布(包括网格)
    xyNum:传入需要绘制的宽格子数
    */ 
    initCanvas(xyNum){
        this.canvas = document.createElement('canvas');
        this.ctx = this.canvas.getContext('2d');
        
        //1为border
        this.canvas.width = (this.divw+1)*xyNum;
        this.canvas.height = (this.divw+1)*xyNum;

        // 绘制网格坐标
                // 获取canvas的宽高;
                let w = this.canvas.width;
                let h = this.canvas.height;
                // 绘制水平线
                for (let i = 1; i < h / 21; i++) {
                    this.ctx.beginPath();
                    this.ctx.lineTo(0,  21 * i) //起点
                    this.ctx.lineTo(w, 21 * i); //重点
                    this.ctx.stroke();
        
                }
                // h绘制垂直线
                for (let i = 1; i < w / 21; i++) {
                    this.ctx.beginPath();
                    this.ctx.lineTo(21 * i,0) //起点
                    this.ctx.lineTo(21 * i,h); //重点
                    this.ctx.stroke();
        
                }
                // ctx.stroke();

        // 放入容器
        this.div = document.getElementById(this.id);
        this.div.appendChild(this.canvas);
        
        // 绑定点击事件!!!
        this.canvas.addEventListener('mousedown',this.mouseDown.bind(this))//!!!!注意需要更改this指向,用bind
        
        // 清除鼠标右键的默认事件 “contextmenu“
        this.canvas.addEventListener("contextmenu",function(event){
            event.preventDefault()
        })
    }

    /*初始化地雷(包括提醒数字)
    xyNum:传入地图的宽的格子数
    booNum:传入地雷数
    */ 
    initBooxy (xyNum,booNum){

        // 随机地雷位置 并保存起来
        for(let i=0;i<booNum;i++){

            // x,y为地雷所在格子坐标,从0开始
            this.boox = parseInt(Math.random()*xyNum);
            this.booy = parseInt(Math.random()*xyNum);

            //避免雷的位置重复
            while(this.booArrs.myindexOf([this.boox,this.booy])!=-1){
                this.boox = parseInt(Math.random()*xyNum);
                this.booy = parseInt(Math.random()*xyNum);
            }

            this.booArrs.push([this.boox,this.booy])//!!!保存地雷的位置
            console.log(i,'x:'+this.boox,'y:'+this.booy);

            //绘制地雷
            this.ctx.beginPath();//不清楚可不可以删
            this.ctx.rect(this.boox*21,this.booy*21,20,20);
            this.ctx.fillStyle = 'red';
            this.ctx.fill();
        }

        // 绘制地雷位置周围提醒数字
            // 这里的逻辑可以优化,不提前绘制数字,在点击清除障碍物后再判断绘制。  

        /*
            想法一:在每个雷周围添加数字1,如果在多个雷交集处累加
            想法二:所有块依次判断周围是否有雷,有几个雷,就fillText()多少
            想法三:(一二结合)先找每个雷,该雷周围的8个块依次 判断周围有几个雷
        */ 
            // 这里为法二
       for(let i=0;i<xyNum;i++){
           for(let j=0;j<xyNum;j++){
               let num = 0;//提醒数字 ,每次重置为0
            
                if(this.booArrs.myindexOf([i-1,j-1]) !=-1){
                    num++;
                }
                if(this.booArrs.myindexOf([i-1,j]) !=-1){
                    num++;
                }
                if(this.booArrs.myindexOf([i-1,j+1]) !=-1){
                    num++;
                }
                if(this.booArrs.myindexOf([i,j-1]) !=-1){
                    num++;
                }
                if(this.booArrs.myindexOf([i,j+1]) !=-1){
                    num++;
                }
                if(this.booArrs.myindexOf([i+1,j-1]) !=-1){
                    num++;
                }
                if(this.booArrs.myindexOf([i+1,j]) !=-1){
                    num++;
                }
                if(this.booArrs.myindexOf([i+1,j+1]) !=-1){
                    num++;
                }
               
                //绘制提醒数字  
                if(num!=0 && (this.booArrs.myindexOf([i,j]) ==-1 )){//(this.booArrs.myindexOf([i,j]) ==-1)地雷不标注提示数字若。要标注需要+1(本身)

                this.ctx.font = '18px fasdg'
                this.ctx.fillStyle = '#000'
                this.ctx.fillText(num,i*(this.divw+1)+2,(j+1)*(this.divw+1)-2);//加1和j+1为测试结果,-+2是为了文本在格子里居中//y为文本中线坐标
                
                this.numArrs.push([i,j,num]);//i,j为提醒数字的块坐标,num为装数组里的值(myindexOf来判断)
                }
                // this.NUM = num;
           }
       }
        

        
    }

    /*初始化遮挡物
     xyNum:传入地图的宽的格子数
    */ 
   initObs(xyNum){
    for(let i=0;i<xyNum;i++){
        for(let j=0;j<xyNum;j++){

            this.ctx.beginPath();
            this.ctx.rect(i*21,j*21,20,20);
            // this.ctx.fillStyle = 'rgb(155,25,205,0.7)';//设置障碍物透明度可以方便查看雷的位置
            this.ctx.fillStyle = 'rgb(155,25,205,1)';//正常游戏时透明度为’1‘
            this.ctx.fill();
        }
    }
   }


/*点击事件在initCanvas中绑定*/  
   mouseDown(){
 
    //这里使用preventDefault,默认事件被没有消除,是因为触发鼠标右键的默认事件的事件类型不是mousedown,是contextmenu
    // event.preventDefault(); //ie9以下不兼容 
    
    this.clix = Math.floor(event.layerX/( this.divw+1));//this.divw为20是块的宽
    this.cliy = Math.floor(event.layerY/( this.divw+1)); 


    

    // 鼠标左键
    if(event.button==0){
        this.clearObs(this.clix,this.cliy);


    }
    
    // 鼠标右键
    else if(event.button==2){
        
        
        this.markObs(this.clix,this.cliy);
    }
   
   }


   /*扫雷*/  //这里的代码可以封装一下 为了方便此处没有封装
   clearObs(x,y){
    // console.log(x,y);点击坐标

    this.ctx.clearRect(x*21,y*21,20,20);//清除指定块
    
    // 点击到标记,点击到提醒数字,点击到地雷,点击到空白,
    if(this.markArrs.myindexOf([x,y])!=-1){  //点击到标记,重新覆盖
        this.ctx.rect(x*21,y*21,20,20);
        this.ctx.fillStyle = 'rgb(155,25,205,1)';
        this.ctx.fill();
        
        this.ctx.beginPath();
        this.ctx.fillStyle = 'red';
        this.ctx.fillText('?',x*(this.divw+1)+2,(y+1)*(this.divw+1)-2);
        this.ctx.fill();

    }
    else if(this.numArrs.myindexOf([x,y])!=-1){//点击到提醒数字
        let index = this.numArrs.myindexOf([x,y]);//下标
        let num = this.numArrs[index][2];//提醒数字
        this.ctx.fillText(num,x*(this.divw+1)+2,(y+1)*(this.divw+1)-2);//加1和j+1为测试结果,-+2是为了文本在格子里居中//y为文本中线坐标
        this.num++;
    }
    else if(this.booArrs.myindexOf([x,y])!=-1){//,点击到地雷,全部绘制
        console.log(this.booArrs.myindexOf([x,y]));
            //绘制全图
            // 绘制提醒数字
            for(let i=0;i<this.xyNum;i++){
                for(let j=0;j<this.xyNum;j++){
                    let num = 0;//提醒数字 ,每次重置为0
                     // if(booArrs.indexof([i-1,j-1]) != -1){//数组是对象这样永远-1
                     this.ctx.clearRect(i*21,j*21,20,20);
                     if(this.booArrs.myindexOf([i-1,j-1]) !=-1){
                         num++;
                     }
                     if(this.booArrs.myindexOf([i-1,j]) !=-1){
                         num++;
                     }
                     if(this.booArrs.myindexOf([i-1,j+1]) !=-1){
                         num++;
                     }
                     if(this.booArrs.myindexOf([i,j-1]) !=-1){
                         num++;
                     }
                     if(this.booArrs.myindexOf([i,j+1]) !=-1){
                         num++;
                     }
                     if(this.booArrs.myindexOf([i+1,j-1]) !=-1){
                         num++;
                     }
                     if(this.booArrs.myindexOf([i+1,j]) !=-1){
                         num++;
                     }
                     if(this.booArrs.myindexOf([i+1,j+1]) !=-1){
                         num++;
                     }
                     
     
                    
                     //绘制提醒数字
                     if(num!=0 && (this.booArrs.myindexOf([i,j]) ==-1 )){//(this.booArrs.myindexOf([i,j]) ==-1)地雷不标注提示数字若要标注需要+1(本身)
     
                     this.ctx.font = '18px fasdg'
                     this.ctx.fillStyle = '#000'
                     this.ctx.fillText(num,i*(this.divw+1)+2,(j+1)*(this.divw+1)-2);//加1和j+1为测试结果,-+2是为了文本在格子里居中//y为文本中线坐标
                     
                     this.numArrs.push([i,j,num]);//i,j为提醒数字的块坐标,num为装数组里的值(myindexOf来判断)
                     }
                     // this.NUM = num;
                }
            }
            // 绘制地雷
            for(let i=0;i<this.booArrs.length;i++){
                this.ctx.fillStyle = 'red';
                this.ctx.rect(this.booArrs[i][0]*21,this.booArrs[i][1]*21,20,20);
                this.ctx.fill(); 
            }
            this.ctx.clearRect((this.xyNum-1)*21,(this.xyNum-1)*21,20,20);//每次最后一个都会变红,不知道原因,此处专门删除。
           
            alert('你惊动了雷雷');

            
    }

    else {

        this.isboo(this.ctx,x,y,this.booArrs,this.numArrs,this.markArrs,this.xyNum);


    } 
   }

   win (){//标记数组==地雷数组
    this.tim = setInterval(()=>{
        if(this.booArrs.length ==this.markArrs.length){
            for(let i=0;i<this.booNum;i++){
                
                if( true == this.booArrs.some(()=>{
                    return this.markArrs.myindexOf(this.booArrs[i])!=-1;
                })){
                   this.booNum--;
                }
                if(this.booNum==0){
                    clearInterval(this.tim);
                    alert('you are win');
                    }
            }
        }
    },10)

   }
   isboo(ctx,x,y,booArrs,numArrs,markArrs,xyNum){
       new Isboo(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
   }


    /*标记 
    */
   markObs(x,y){  
       console.log(x,y);
    new MarkObs(this.ctx,x,y,this.booArrs,this.divw,this.markArrs);
    

   }

   
}

isboo.js

Array.prototype.myindexOf = function(arr){
    for(let i=0;i<this.length;i++){
        
        if((this[i][0] == arr[0]) &&(this[i][1]==arr[1])){
            return i;
        }
    }
    return -1;
}
/*
这里解决点击到空白格子时,把周围的空白格一起显示。此处的逻辑可以再优化.
ctx:布局
x,点击位置
y,点击位置
booArrs:炸弹的位置数组
numArrs:提示数的位置
markArrs:标记的位置
*/ 
class Isboo {
    constructor(ctx,x,y,booArrs,numArrs,markArrs,xyNum){
        this.x = x;
        this.y = y;
        
        // 判断有没有提醒数字
        this.isbool(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
        this.isboor(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
        this.isboot(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
        this.isboob(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
    }
    isbool(ctx,x,y,booArrs,numArrs,markArrs,xyNum){
        if((numArrs.myindexOf([x,y])==-1)&&(x<xyNum)&&(markArrs.myindexOf([x,y])==-1)){
            ctx.clearRect(x*21,y*21,20,20);
            x+=1;
            this.isbool(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            // this.isboor(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            this.isboot(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            this.isboob(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
        }else {
            return ;
        }
    }
    isboor(ctx,x,y,booArrs,numArrs,markArrs,xyNum){
        if((numArrs.myindexOf([x,y])==-1)&&(x>=0)&&(markArrs.myindexOf([x,y])==-1)){
            ctx.clearRect(x*21,y*21,20,20);
            x-=1;
            // this.isbool(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            this.isboor(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            this.isboot(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            this.isboob(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
        }else {
            return ;
        }
    }
    isboot(ctx,x,y,booArrs,numArrs,markArrs,xyNum){
        if((numArrs.myindexOf([x,y])==-1)&&(y<xyNum)&&(markArrs.myindexOf([x,y])==-1)){
            ctx.clearRect(x*21,y*21,20,20);
            y+=1;
            // this.isbool(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            // this.isboor(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            this.isboot(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            // this.isboob(ctx,x,y,booArrs,numArrs,markArrs,xyNum);

        }else {
            return ;
        }
    }
    isboob(ctx,x,y,booArrs,numArrs,markArrs,xyNum){
        if((numArrs.myindexOf([x,y])==-1)&&(y>=0)&&(markArrs.myindexOf([x,y])==-1)){
            ctx.clearRect(x*21,y*21,20,20);
            y-=1;
            // this.isbool(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            // this.isboor(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            // this.isboot(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
            this.isboob(ctx,x,y,booArrs,numArrs,markArrs,xyNum);
        }else {
            return ;
        }
    }

}

MarkObs.js

Array.prototype.myindexOf = function(arr){
    for(let i=0;i<this.length;i++){
        
        if((this[i][0] == arr[0]) &&(this[i][1]==arr[1])){
            return i;
        }
    }
    return -1;
}
/*
ctx:布局
x,点击位置
y,点击位置
booArrs:炸弹的位置数组
divw:各自宽度
markarrs:标记数组
*/ 
class MarkObs{
    constructor(ctx,x,y,booArrs,divw,markarrs){
        this.markObs(ctx,x,y,booArrs,divw,markarrs);
    }

    markObs(ctx,x,y,booArrs,divw,markarrs){

        if(markarrs.myindexOf([x,y])==-1){//如果标记数组里没有该地址,则标记,并添加进数组
        ctx.beginPath();
        ctx.fillStyle = 'red';
        ctx.fillText('?',x*(divw+1)+2,(y+1)*(divw+1)-2);
        markarrs.push([x,y]);
        }else {//如果标记数组里有该地址,则取消标记,并从数组中删除
            ctx.clearRect(x*(divw+1),y*(divw+1),divw,divw);
            ctx.beginPath();
            ctx.rect(x*21,y*21,20,20);
            ctx.fillStyle = 'rgb(155,25,205,1)';
            ctx.fill();
            markarrs.splice((markarrs.myindexOf([x,y])),1);
        }
    }

}

页面效果

初始化障碍物设置了透明度时

正常游戏时

这里点击右键标记后忘了把填充颜色设置回来。所以后面变红。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的HTML5 Canvas 扫雷游戏的示例代码,希望能帮到您: ```html <!DOCTYPE html> <html> <head> <title>扫雷游戏</title> <style> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="canvas" width="300" height="300"></canvas> <script> // 初始化游戏 var grid = []; var gridSize = 10; var bombCount = 10; var cellSize = 30; for (var i = 0; i < gridSize; i++) { var row = []; for (var j = 0; j < gridSize; j++) { row.push({ x: j * cellSize, y: i * cellSize, width: cellSize, height: cellSize, isBomb: false, isRevealed: false, isFlagged: false, neighborCount: 0 }); } grid.push(row); } // 随机布置炸弹 for (var i = 0; i < bombCount; i++) { var row = Math.floor(Math.random() * gridSize); var col = Math.floor(Math.random() * gridSize); var cell = grid[row][col]; if (cell.isBomb) { i--; } else { cell.isBomb = true; } } // 计算每个格子周围的炸弹数量 for (var i = 0; i < gridSize; i++) { for (var j = 0; j < gridSize; j++) { var cell = grid[i][j]; if (!cell.isBomb) { var count = 0; for (var row = i - 1; row <= i + 1; row++) { for (var col = j - 1; col <= j + 1; col++) { if (row >= 0 && row < gridSize && col >= 0 && col < gridSize) { if (grid[row][col].isBomb) { count++; } } } } cell.neighborCount = count; } } } // 绘制游戏 var canvas = document.getElementById("canvas"); var context = canvas.getContext("2d"); for (var i = 0; i < gridSize; i++) { for (var j = 0; j < gridSize; j++) { var cell = grid[i][j]; context.fillStyle = "gray"; context.fillRect(cell.x, cell.y, cell.width, cell.height); if (cell.isRevealed) { if (cell.isBomb) { context.fillStyle = "red"; context.fillRect(cell.x, cell.y, cell.width, cell.height); } else { context.fillStyle = "white"; context.fillRect(cell.x, cell.y, cell.width, cell.height); if (cell.neighborCount > 0) { context.font = "20px Arial"; context.fillStyle = "black"; context.fillText(cell.neighborCount, cell.x + cell.width / 2, cell.y + cell.height / 2); } } } else { if (cell.isFlagged) { context.font = "20px Arial"; context.fillStyle = "black"; context.fillText("F", cell.x + cell.width / 2, cell.y + cell.height / 2); } } } } // 点击格子 canvas.addEventListener("click", function(event) { var x = event.pageX - canvas.offsetLeft; var y = event.pageY - canvas.offsetTop; var cell = getCell(x, y); if (cell !== null && !cell.isRevealed && !cell.isFlagged) { if (cell.isBomb) { revealBombs(); alert("你输了!"); } else { revealCell(cell); if (checkWin()) { alert("你赢了!"); } } } }); // 右击格子 canvas.addEventListener("contextmenu", function(event) { event.preventDefault(); var x = event.pageX - canvas.offsetLeft; var y = event.pageY - canvas.offsetTop; var cell = getCell(x, y); if (cell !== null && !cell.isRevealed) { cell.isFlagged = !cell.isFlagged; drawCell(cell); } }); // 根据坐标获取格子 function getCell(x, y) { for (var i = 0; i < gridSize; i++) { for (var j = 0; j < gridSize; j++) { var cell = grid[i][j]; if (cell.x < x && x < cell.x + cell.width && cell.y < y && y < cell.y + cell.height) { return cell; } } } return null; } // 揭开格子 function revealCell(cell) { cell.isRevealed = true; drawCell(cell); if (cell.neighborCount === 0) { for (var row = cell.row - 1; row <= cell.row + 1; row++) { for (var col = cell.col - 1; col <= cell.col + 1; col++) { if (row >= 0 && row < gridSize && col >= 0 && col < gridSize) { var neighbor = grid[row][col]; if (!neighbor.isRevealed) { revealCell(neighbor); } } } } } } // 揭开所有炸弹 function revealBombs() { for (var i = 0; i < gridSize; i++) { for (var j = 0; j < gridSize; j++) { var cell = grid[i][j]; if (cell.isBomb) { cell.isRevealed = true; drawCell(cell); } } } } // 检查是否胜利 function checkWin() { for (var i = 0; i < gridSize; i++) { for (var j = 0; j < gridSize; j++) { var cell = grid[i][j]; if (!cell.isRevealed && !cell.isBomb) { return false; } } } return true; } // 绘制格子 function drawCell(cell) { context.fillStyle = "gray"; context.fillRect(cell.x, cell.y, cell.width, cell.height); if (cell.isRevealed) { if (cell.isBomb) { context.fillStyle = "red"; context.fillRect(cell.x, cell.y, cell.width, cell.height); } else { context.fillStyle = "white"; context.fillRect(cell.x, cell.y, cell.width, cell.height); if (cell.neighborCount > 0) { context.font = "20px Arial"; context.fillStyle = "black"; context.fillText(cell.neighborCount, cell.x + cell.width / 2, cell.y + cell.height / 2); } } } else { if (cell.isFlagged) { context.font = "20px Arial"; context.fillStyle = "black"; context.fillText("F", cell.x + cell.width / 2, cell.y + cell.height / 2); } } } </script> </body> </html> ``` 请注意,这只是一个简单的示例代码,您可以根据自己的需求进行修改和扩展。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值