zoukankan      html  css  js  c++  java
  • Mooc--五子棋(js)小结

    1. canvas是块级元素吗??

    2. css3 box-shadow属性

    语法:box-shadow: h-shadow v-shadow blur spread color inset;

    注释:box-shadow 向框添加一个或多个阴影。该属性是由逗号分隔的阴影列表,每个阴影由 2-4 个长度值、可选的颜色值以及可选的 inset 关键词来规定。省略长度的值是 0。

     
    描述
    h-shadow 必需;水平阴影的位置;允许负值。
    v-shadow 必需;垂直阴影的位置;允许负值。
    blur 可选;模糊距离。
    spread 可选;阴影的尺寸。
    color 可选;阴影的颜色。
    inset 可选;将外部阴影(outset)改为内部阴影。

    3.

    代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>五子棋</title>
        <link rel="stylesheet" type="text/css" href="css/style.css">
    </head>
    <body>
    <canvas id="chess" width="450px" height="450px"></canvas>
    <script type="text/javascript" src="js/sc.js"></script>>
    </body>
    </html>
    

    CSS

    canvas{
        display: block;
        margin: 50px auto;
        box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #B9B9B9;
    }
    

    js部分:

    1)双人轮流下棋(赢需要人为判断)

    //定义二维数组存储棋盘上落子的情况
    var chessBoard = [];
    var me = true; //代表黑子
    
    for(var i=0; i<15; i++){
    	chessBoard[i] = [];
    	for(var j=0; j<15; j++){
    		chessBoard[i][j] = 0; //代表没有落子,空的
    	}
    }
    
    
    var chess = document.getElementById('chess');
    var context = chess.getContext('2d');
    
    context.strokeStyle = "#BFBFBF";
    
    var logo = new Image();
    logo.src = "images/deer.png";
    //图片加载完成后调用drawImage()
    logo.onload = function() {
    context.drawImage(logo, 0, 0, 450, 450);
    drawChessBoard(); //保证棋盘在水印图片的上层
    }
    
    /*canvas为450px*450px,棋盘内边距留白15px,每行每列均为15条线,14个方格,每个方格30px*/
    var drawChessBoard = function() {
    	for(var i=0; i<15; i++){
    		// 画横线
    		context.moveTo(15 + i*30, 15);
    		context.lineTo(15 + i*30, 435);
    		context.stroke(); //用于描边
    		// 画竖线
    		context.moveTo(15, 15 + i*30);
    		context.lineTo(435, 15 + i*30);
    		context.stroke();
    	}
    }
    
    //i,j代表棋子在棋盘的索引,而me(Boolean)表示走的是黑棋还是白棋
    var oneStep = function(i, j, me) {
    	context.beginPath();
    	//可以画扇型,圆心,半径,扇型的起止弧度和终止弧度
    	context.arc(15 + i*30, 15 + j*30, 13, 0, 2 * Math.PI);
    	context.closePath();
    	//6个参数
    	var gradient = context.createRadialGradient(15 + i*30 + 2, 15 + j*30 - 2, 13, 15 + i*30 + 2, 15 + j*30 - 2, 0); //圆心偏移右上角
    	if(me) {
    	gradient.addColorStop(0, "#0A0A0A"); //0、1代表百分比
    	gradient.addColorStop(1, "#636766")
    } else{
    	gradient.addColorStop(0, "#D1D1D1");
    	gradient.addColorStop(1, "#F9F9F9")
    }
    	context.fillStyle = gradient;
    	context.fill(); //用于填充
    }
    
    chess.onclick = function(e) {
    	//相对与canvas左上角计算的坐标
    	var x = e.offsetX;
    	var y = e.offsetY;
    	var i = Math.floor(x / 30);
    	var j = Math.floor(y / 30); 
    	if(chessBoard[i][j] == 0) {
    		oneStep(i, j, me)
    		if(me) {
    			chessBoard[i][j] = 1;
    		} else {
    			chessBoard[i][j] = 2;
    		}
    		me = !me;
    	}
    	
    }
    

    2)人机模式

    window.onload=function(){
    var me=true;
    var over=false;//表示棋局有没有结束
    
    //定义二维数组存储棋盘上落子的情况
    var chessBord=[];
    //初始化chessBord数组
    for(var i=0; i<15;i++){
    chessBord[i]=[];
    for(var j=0;j<15;j++){
    chessBord[i][j]=0; //代表没有落子,空的
    }
    }
    
    //赢法数组(三维数组)
    var wins=[];
    //赢法的统计数组(一维数组)
    var myWin=[];
    var computerWin=[];
    //初始化3维赢法数组
    for(var i=0; i<15; i++){
    wins[i]=[];
    for(var j=0; j<15; j++){
    wins[i][j]=[];
    }
    }
    
    var count=0;//定义赢法种类的索引
    //所有横线的赢法
     for(var i=0;i<15;i++){
      for(var j=0;j<11;j++){
          //wins[0][0][0] = true;
          //wins[0][1][0] = true;
          //wins[0][2][0] = true;
          //wins[0][3][0] = true;
          //wins[0][4][0] = true;
    
          //wins[0][1][1] = true;
          //wins[0][2][1] = true;
          //wins[0][3][1] = true;
          //wins[0][4][1] = true;
          //wins[0][5][1] = true;
      for(var k=0;k<5;k++){
      wins[i][j+k][count]=true;
      }
      count++;
      }
     }
     //所有竖线的赢法
     for(var i=0;i<15;i++){
      for(var j=0;j<11;j++){
      for(var k=0;k<5;k++){
      wins[j+k][i][count]=true;
      }
      count++;
      }
     }
    //所有斜线的赢法
     for(var i=0;i<11;i++){
      for(var j=0;j<11;j++){
      for(var k=0;k<5;k++){
      wins[i+k][j+k][count]=true;
      }
      count++;
      }
     }
    //所有反斜线的赢法
     for(var i=0;i<11;i++){
      for(var j=14;j>3;j--){
      for(var k=0;k<5;k++){
      wins[i+k][j-k][count]=true;
      }
      count++;
      }
     }
    
     console.log(count);
    //初始化赢法的统计数组
     for(var i=0; i<count; i++){
      myWin[i]=0;
      computerWin[i]=0;
      }
       
    /**/
    var chess=document.getElementById('chess');
    var context=chess.getContext('2d');
    
    context.strokeStyle="#BFBFBF";
    var logo=new Image();
    logo.src="images/deer.png";
     /**/
      logo.onload=function(){
    context.drawImage(logo,0,0,450,450);
          drawChessBoard();
    /**/
     
       }
     /**/
      function drawChessBoard (){
        for(var i=0; i<15; i++){
    context.moveTo(15+i*30,15);
        context.lineTo(15+i*30,430);
        context.stroke();
        context.moveTo(15,15+i*30);
        context.lineTo(435,15+i*30);
        context.stroke();
        } 
      }  
    
    /**//*定义onesStep函数来绘制棋子*/
     var oneStep=function(i,j,me){
        context.beginPath();
    //可以画扇型,圆心,半径,扇型的起止弧度和终止弧度
        context.arc(15+i*30,15+j*30,13,0,2*Math.PI);
        context.closePath();
    
     var gradient=context.createRadialGradient(15+i*30+2,15+j*30-2,13,15+i*30+2,15+j*30-2,0);
    if(me){
    gradient.addColorStop(0,"#0A0A0A");
    gradient.addColorStop(1,"#636766");
      }
      else{
      gradient.addColorStop(0,"#D1D1D1");
       gradient.addColorStop(1,"#F9F9F9");
      }
    context.fillStyle=gradient;
    context.fill();//填充
      }  
     
     /**/ 
     chess.onclick=function(e){
       //棋局结束
       if(over){
        return;
       }
       if(!me){
        return;
       }
       var x=e.offsetX;
       var y=e.offsetY;
       var i=Math.floor(x/30);
       var j=Math.floor(y/30);
       if(chessBord[i][j]==0){
          oneStep(i,j,me);
          chessBord[i][j]=1;
           for(var k=0;k<count;k++){
             if(wins[i][j][k]){
              myWin[k]++; //向着胜利前进一步
              computerWin[k]=6; //黑棋落子,白棋在k种赢法下不成立,异常数据,不可能大于5
               if(myWin[k]==5){
                window.alert("你赢了");
                over=true;
               }
             }
           }
           if(!over){
             me=!me;
             computerAI();
           }
        }
      }
    
      //定义computerAI函数
     var computerAI=function(){
        var myScore=[]; //计算我方得分(二维数组)
        var computerScore=[]; //计算计算机得分(二维数组)
        var max=0; //保存最高分数
        var u=0, v=0; //保存最高分数的点的坐标
    
        for(var i=0;i<15;i++){
        myScore[i]=[];
        computerScore[i]=[];
        for(var j=0;j<15;j++){
        myScore[i][j]=0;
        computerScore[i][j]=0;
        }
        }
    
        for(var i=0;i<15;i++){
        for(var j=0; j<15;j++){
        if(chessBord[i][j]==0){
            //如果i,j出现在多种赢法上,会进行累加
        for(var k=0; k<count;k++){
        if(wins[i][j][k]){
        if(myWin[k]==1){
        myScore[i][j]+=200;
        } else if(myWin[k]==2){
        myScore[i][j]+=400;
        } else if(myWin[k]==3){
        myScore[i][j]+=2000;
        } else if(myWin[k]==4){
        myScore[i][j]+=10000;
        }
        if(computerWin[k]==1){
        computerScore[i][j]+=200;
        } else if(computerWin[k]==2){
        computerScore[i][j]+=400;
        } else if(computerWin[k]==3){
        computerScore[i][j]+=2000;
        } else if(computerWin[k]==4){
        computerScore[i][j]+=10000;
        }
        }
        }
        if(myScore[i][j]>max){
        max=myScore[i][j];
        u=i;
        v=j;
        } else if(myScore[i][j]==max){
        if(computerScore[i][j]>computerScore[u][v]){
        u=i;
        v=j;
        }
        }
        if(computerScore[i][j]>max){
        max=computerScore[i][j];
        u=i;
        v=j;
        } else if(computerScore[i][j]==max){
        if(myScore[i][j]>myScore[u][v]){
        u=i;
        v=j;
        }
        }
        }
        }
        }
        oneStep(u,v,false);
        chessBord[u][v]=2;
        //
         for(var k=0;k<count;k++){
             if(wins[u][v][k]){
              computerWin[k]++;
              myWin[k]=6;
               if(computerWin[k]==5){
                   setTimeout(function(){
                window.alert("计算机赢了");},0.5);
                over=true;
               }
             }
           }
           if(!over){
             me=!me;
              
           }
      }
    }
    

    注:此AI算法侧重于防守;

    几个小问题:

    1)Chrome浏览器中,在落下第五个棋子(赢),会先弹出‘赢了’的对话框,用setTimeout改进;

    后续改进:

    1)添加悔棋功能 

    如果是要悔棋的功能的话可以用一个变量存储上次落子坐标,重新绘制背景以及坐标位置的十字;

    2)添加重置功能

    3)落子得分的计算

    4)重复部分的封装 

      

     

      

  • 相关阅读:
    Linux数据链路层的包解析
    Nmap的活跃主机探测常见方法
    甲方安全建设推进思路
    重新学习python类
    python装饰器
    记录一次奇葩渗透中的点点滴滴
    安全情报总结
    机器学习基础
    tensorflow学习笔记(四十五):sess.run(tf.global_variables_initializer()) 做了什么?
    tensorflow学习笔记(二十五):ConfigProto&GPU
  • 原文地址:https://www.cnblogs.com/Amy-world/p/9786964.html
Copyright © 2011-2022 走看看