专栏首页web秀Canvas小游戏——五子棋

Canvas小游戏——五子棋

前言

Canvas API(画布)是在HTML5中新增的标签用于在网页实时生成图像,并且可以操作图像内容。 HTML5的Canvas画布功能真的很强大,与之对应的还有Svg,都是HTML5的核心之一。想了解更多,来看看Canvas和Svg的对比

HTML主体

<!--难度级别,可以不要,默认简单-->
<div class="choose">
  <img src="images/bg.jpg" alt="" width="100%">
  <div class="choose-lv">
    <div class="levl">简单</div>
    <div class="levl">中级</div>
    <div class="levl">高级</div>
  </div>
</div>
<div class="choose_shade"></div>
<!--棋盘上方的提示等,可以不要-->
<div class="player">
  <div class="baiqi"><img src="images/baiqi.png" alt=""></div>
  <div class="tips" id="tips">黑子先行</div>
  <div class="heiqi"><img src="images/heiqi.png" alt=""></div>
  <div class="clear"></div>
</div>
<!--这里才是重点,棋盘和棋子-->
<div class="checkerboard">
  <canvas id="chess" width="450px" height="450px"></canvas>
  <canvas id="chess_board" width="450px" height="450px"></canvas>
  <canvas id="chess_pointer" width="450px" height="450px"></canvas>
</div>

JS

注释很详细,不做过多介绍了,注意赢棋算法,和难易程度算法

var num = 0;//连胜次数
var gameMode = false; // 模式,默认人机
var complexity = 1; // 人机时难度级别,默认简单
layer.confirm('请选择模式?', {
  btn: ['人机', '人人'],
  closeBtn: 0,
}, function(index, layero){
  gameMode=false;
  $('.choose').animate({
    opacity:1
  },800)
  $('.choose_shade').animate({
    opacity:0.6
  },800)
  layer.close(index);
}, function(index){
  gameMode=true;
  $('.choose_shade').animate({
    opacity:0,
    'z-index':-1
  },800)
  $('.choose').animate({
    opacity:0,
    'z-index':-1
  },800)
});

$('.levl').click(function(){
  var index=$(this).index() + 1;
  complexity=index;
  $('.choose').animate({
    opacity:0,
    'z-index':-1
  })
  $('.choose_shade').animate({
    opacity:0,
    'z-index':-1
  })
})

var canWidth = Math.min( 500 , $(window).width()-30);
var canHeight=canWidth;

var chess=document.getElementById('chess');
var context=chess.getContext('2d');

var chess_board=document.getElementById('chess_board');
var context2=chess_board.getContext('2d');

var chess_pointer=document.getElementById('chess_pointer');
var context3=chess_pointer.getContext('2d');

var pointerEnd=[];

// 根据屏幕大小绘制棋盘
$('#chess_pointer').css({
  width:canWidth,
  height:canHeight
})
$('#chess').css({
  width:canWidth,
  height:canHeight
})
$('#chess_board').css({
  width:canWidth,
  height:canHeight
})
$('.checkerboard').css({
  width:canWidth,
  height:canHeight
})

var utilW=canWidth/15;
var utilH=utilW;

var me;
var chessBoard;
var over;

//赢法数组
var wins=[];

//赢法统计数组
var myWin=[];
var computerWin=[];

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++){
    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++;
  }
}


var init=function(){
  context.clearRect(0,0,450,450);
  context3.clearRect(0,0,450,450);
  me=true;
  chessBoard=[];
  over=false;
  for(var i=0;i<15;i++){
    chessBoard[i]=[];
    for(var j=0;j<15;j++){
      chessBoard[i][j]=0;
    }
  }

  for(var i=0;i<count;i++){
    myWin[i]=0;
    computerWin[i]=0;
  }

}

init()


context2.strokeStyle="#dfdfdf";
var img=new Image();
img.src="images/logo.png";
img.onload=function(){
  drawChessBoard();  
}
var drawChessBoard=function(){
  for(var i=0;i<15;i++){
    context2.moveTo(15+i*30,15);
    context2.lineTo(15+i*30,435);
    context2.stroke();

    context2.moveTo(15,15+i*30);
    context2.lineTo(435,15+i*30);
    context2.stroke();
  }
}

var oneStep=function(i,j,me){
  context3.clearRect(0,0,450,450);

  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,"#C7C7C7");
    gradient.addColorStop(1,"#f9f9f9");
  }
  context.fillStyle=gradient;
  context.fill();

  context3.beginPath();
  context3.arc(15+i*30,15+j*30,15,0, 2*Math.PI);
  context3.closePath();
  context3.fillStyle="#FF3366";
  context3.fill(); 
}
chess.onclick=function(e){
  e.preventDefault();
  var x=e.offsetX;
  var y=e.offsetY;
  moveLater(x,y);

}
var moveLater=function(x,y){
  if(over){
    return;
  }
  var i=Math.floor(x/utilW);
  var j=Math.floor(y/utilW);
  if(chessBoard[i][j]==0){
    oneStep(i,j,me);
    if(gameMode){
      if (me) {
        chessBoard[i][j] = 1;
        for (var k = 0; k < count; k++) {
          if (wins[i][j][k]) {
            myWin[k]++;
            computerWin[k] = 6;
            if (myWin[k] == 5) {
              over = true;
              layer.open({
                title: '黑子赢了',
                content: '亲,再来一局试试!',
                btn: ['嗯', '不要'],
                yes: function(index){
                  init();
                  layer.close(index);
                }
              });
            }
          }
        }
      } else {
        chessBoard[i][j] = 2;
        for (var k = 0; k < count; k++) {
          if (wins[i][j][k]) {
            computerWin[k]++;
            myWin[k] = 6;
            if (computerWin[k] == 5) {
              over = true;
              layer.open({
                title: '白子赢了',
                content: '亲,再来一局试试!',
                btn: ['嗯', '不要'],
                yes: function(index){
                  // location.reload();
                  init();
                  layer.close(index);
                }
              });
            }
          }
        }
      }
      me = !me;
    }else{
      chessBoard[i][j]=1;

      for(var k=0;k<count;k++){
        if(wins[i][j][k]){
          myWin[k]++;
          computerWin[k]=6;
          if(myWin[k]==5){
            over=true;
            $('.black').css({'z-index':2})
            layer.open({
              title: '你赢了',
              content: '亲,人家是你的了!',
              btn: ['要', '不要'],
              yes: function(index){
                // location.reload();
                num++;
                if(num>=3){
                  $('#tips').html('常胜将军,已连胜'+num+'局');
                }else{
                  $('#tips').html('你已连胜'+num+'局');
                }
                init();
                layer.close(index);
              }
            });
          }
        }
      }
      if(!over){
        $('#tips').html('电脑走棋,走着瞧');
        me=!me;
        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(chessBoard[i][j]==0){
        for(var k=0;k<count;k++){
          if(wins[i][j][k]){
            if(complexity==1){
              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]+=100;
              }else if(computerWin[k]==2){
                computerScore[i][j]+=300;
              }else if(computerWin[k]==3){
                computerScore[i][j]+=600;
              }else if(computerWin[k]==4){
                computerScore[i][j]+=14000;
              }
            }else if(complexity==2){
              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]+=300;
              }else if(computerWin[k]==2){
                computerScore[i][j]+=500;
              }else if(computerWin[k]==3){
                computerScore[i][j]+=2100;
              }else if(computerWin[k]==4){
                computerScore[i][j]+=15000;
              }
            }else if(complexity==3){

              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]+=210;
              }else if(computerWin[k]==2){
                computerScore[i][j]+=850;
              }else if(computerWin[k]==3){
                computerScore[i][j]+=3000;
              }else if(computerWin[k]==4){
                computerScore[i][j]+=80000;
              }
            }

          }
        }
        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);
  chessBoard[u][v]=2;
  for(var k=0;k<count;k++){
    if(wins[u][v][k]){
      computerWin[k]++;
      myWin[k]=6;
      if(computerWin[k]==5){
        over=true;
        layer.open({
          title: '你输了',
          content: '不要放弃,再来一局吧!',
          btn: ['嗯', '不要'],
          yes: function(index){
            // location.reload();
            num=0;
            init();
            layer.close(index);
          }
        });
      }
    }
  }
  if(!over){
    me=!me;
    if(num==0){
      $('#tips').html('该你走棋了,我看好你');
    }
  }
}

CSS

css都是可有可无的,不影响功能,都是为了美化页面

body,html {
    margin: 0;
    padding: 0;
    position: relative;
    width: 100%;
    height: 100%;
}

.chess-content {
    padding-top: 48px;
}

canvas {
    display: block;
    margin: 0px auto;
    box-shadow: -2px -2px 2px #efefef,5px 5px 5px #b9b9b9;
}

h3 {
    margin: 0;
}

.clear {
    clear: both;
}

.checkerboard {
    margin: 0 auto;
}

#chess {
    position: absolute;
    z-index: 2;
}

#chess_board {
    position: absolute;
    z-index: 1;
}

#chess_pointer {
    position: absolute;
    z-index: 0;
}

.player {
    max-width: 500px;
    margin: 0 auto;
}

.player .baiqi {
    float: left;
}

.player .baiqi {
    width: 15%;
}

.player .tips {
    float: left;
    width: 70%;
    text-align: center;
    font-size: 18px;
}

.player .heiqi {
    width: 15%;
    float: right;
}

.player div img {
    width: 100%;
}

.choose {
    position: absolute;
    z-index: 10;
    width: 80%;
    max-width: 500px;
    left: 50%;
    border: 1px solid #dfdfdf;
    border-radius: 5px;
    opacity: 0;
    top: 50%;
    transform: translateY(-50%);
    overflow: hidden;
}

.choose img {
    width: 100%;
}

.choose_shade {
    width: 100%;
    height: 100%;
    position: absolute;
    z-index: 9;
    background: #000;
    opacity: 0.6;
    margin: 0;
}

.choose-lv {
    position: absolute;
    top: 28%;
    width: 100%;
}

.choose-lv div {
    margin: 19px 0px 10px 52%;
    width: 40%;
    text-align: center;
    border-radius: 5px;
    border: 1px solid #F2F2F2;
    color: #fff;
    text-shadow: 10px 7px 17px;
    font-weight: bold;
    line-height: 35px;
    z-index: 1;
    position: relative;
    background: rgba(0, 0, 0, 0.18);
    cursor: pointer;
}

.black {
    float: right;
    position: absolute;
    z-index: 1;
    width: 40%;
    max-width: 400px;
    bottom: 0;
}

.black img {
    width: 100%;
}

.b_img3,.b_img4 {
    right: 0;
}

.tips {
    line-height: 75px;
}

演示程序:演示代码 下载源码:下载源码

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • CSS实用技巧第二讲:布局处理

    在日常项目开发中,在布局方面有遇到哪些问题了?今天来一起看看CSS布局有哪些小技巧,后续开发更轻松。本文主要通过简单的示例,讲述开发中遇到的布局等问题,但不仅限...

    Javanx
  • CSS3径向渐变实现优惠券波浪造型

    很多人看到左右的波浪边框,第一想法,应该是用图片实现。现在我们就打破这一想法,用CSS搞定这个效果。

    Javanx
  • CSS3 box-shadow实现背景动画

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

    Javanx
  • 小游戏——js+h5[canvas]+cs3制作【五子棋】小游戏

    xing.org1^
  • 源码阅读--xutil3

    提莫队长
  • canvas实现拖动页面时显示窗口视频

    简介   当前主流的视频网站目前有不少新鲜好玩的功能,最明显的莫过于小视频的显示--当视频不在当前视口范围 时,会在右下角用一个小窗口来显示当前的视频,而且可以...

    欲休
  • 透过源码学习设计模式2—Spring ProxyFactory和代理模式

    代理就像我们生活中的房产中介,你不直接与房主,银行接触,而是通过中介与他们沟通联系。 代理的结构如图所示:

    java达人
  • JavaScript版的简单动画

    Google+中有一个特效:拖拽用户头像至分组内,用户头像会有一个特效(绕着圆圈转一圈)。写了个简单的示例,效果如下图所示:

    meteoric
  • 谈拾取摄像机拍摄景物的颜色转化为指定颜色Demo心得

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明...

    bering
  • Mybatis分页插件PageHelper的使用详解

    如果你也在用Mybatis,建议尝试该分页插件,个人感觉这个是最方便,超好用的分页插件。 该插件目前支持Oracle,Mysql,MariaDB,SQLite...

    麦克劳林

扫码关注云+社区

领取腾讯云代金券