通过canvas+js实现五子棋游戏

1.首先五子棋会有棋盘,先创建一个HTML页面,在元素中添加一个canvas标签,同时设置了canvas画布的宽、高都为800px,给canvas画布添加了样式,代码如下

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>五子棋游戏</title>
</head>
<style>
    canvas {
        background-color: rgb(221, 210, 182);
        display: block;
        margin: 0 auto;
    }
    .tip{
        width: 100%;
        text-align: center;
        font-size: 30px;
        color: red;
    }
</style>
<body>
<!--展示获胜提示-->
<div class="tip"></div>
<canvas width="800" height="800" id="box"></canvas>
</body>
</html>

2.这里我们开始绘制棋盘,五子棋的棋盘是 15行15列的直线组成,我们定义每格的宽高都为50,那么棋盘高度和宽度都为700

<script>
	//获取canvas节点
	let myCanvas = document.getElementById('box');
	//获取我们的canvas画笔
	let context = myCanvas.getContext('2d');
	//绘制棋盘15行15列
	for(let i = 1; i < = 15; i++){
	  //先画横线,让棋盘预留50px的边界,我们从x轴为50,y轴为50的位置作为起点
	  //起点x轴坐标为50,保持不变,y轴每一行从上到下为50的倍数增加
	  context.moveTo(50, 50*i);
	  //终点x轴坐标为750,保持不变,y轴每一行从上到下为50的倍数增加
	  context.lineTo(750, 50*i);
	  cotext.stroke();
	  
	  //竖线同理
	  //起点y轴坐标为50,保持不变,x轴每一行从左到右为50的倍数增加
	  context.moveTo(50*i, 50);
	  //终点y轴坐标为750,保持不变,x轴每一行从左到右为50的倍数增加
	  context.lineTo(50*i, 750);
	  cotext.stroke();
	}
	
</script>

绘制完成后的效果在这里插入图片描述
3.添加在棋盘上点击就落子的逻辑,五子棋有黑白两种棋子颜色,我们默认先落子的为黑子,为了让棋子能准确的落在交叉点上,我们需要对鼠标点击的位置进行判断,我们把棋盘的每个交叉点对应二维数组里的占位(如图中的红圈占位就是array[4][4]),红圈的半径为网格的宽度的50%也就是25,当鼠标点击在红圈区域时,我们就把棋子视为要落在红圈中的交叉点上
在这里插入图片描述

let isWhite = false; //添加是否到白棋下子的标识,初始为false
let circles = []; //设置保存棋子位置的二维数组
let isEnd= false; //判断是否结束的标识
//为棋盘注册点击事件
myCanvas.addEventListener('click',(e)=>{
  //获取鼠标点击位置的坐标
  let {offsetX,offsetY} = e;
  //判断游戏是否结束
  if(isEnd){ return; }
  //判断棋子落在棋盘外的位置,不允许落子
  if(offsetX < 25 || offsetY < 25 || offsetX > 775 || offsetY >775)  {
    return false;
  }
  
  //
  let i = Math.floor(offsetX+25/50); //获取点击位置在第几根竖线的区域中,即二维数组的行
  let j = Math.floor(offsetY+25/50); //获取点击位置在第几根横线的区域中,即二维数组的列
  let x = i*50; //获取x轴坐标位置
  let y = j*50; //获取y轴坐标位置
  //识别不能重复落子
  if( circles[i][j] ){
   alert('当前位置已有棋子,不能重复落子!');
   return ;
  }
  //判断当前棋子的颜色,并存入二维数组中
  let circles[i][j] = isWhite ? 'white':'black';
  let color = isWhite ? '#fff':'#000';
  //绘制棋子
  context.beginPath();
  //在当前坐标位置为圆心,绘制一个半径为20的圆
  context.arc(x,y,20,0,2*Math.PI);
  //为棋子设置环形渐变的颜色,让棋子看起来有光泽
  let gradient = context.createRadialGradient(x-10,y-10,x,y,20);
  gradient.addColor(0,'#ccc'); //棋子上光泽色
  gradient.addColor(0,color); //棋子颜色
  //为棋子加上阴影
  context.shadowColor = '#333';
  context.shawdowBlur = 20;
  context.shawdowOffsetX = 5;
  context.shadowOffsetY = 5;
  //填充颜色
  context.fillStyle = gradient;
  context.fill();
  context.closePath();
  //在这里添加当前颜色的棋子是否胜出的逻辑,获胜函数如下方4、5、6
  if(verticalWin(i,j) || horizontalWin(i,j) || obliqueWin(i,j)) {
      isEnd = true; //有获胜者游戏结束
      tip[0].innerHTML = `${isWhite? '白':'黑'}子获胜`;
      return;
  }
  //最后把棋子颜色的标识切换
  isWhite = !isWhite
})

4.接下来我们来先纵向获胜的逻辑函数,接收当前棋子所在的位置代的行列数,从当前位置出发纵向寻找是否同色棋子连续出现了4次,则获胜,代码如下

function verticalWin(x,y){
   let up = 0; //记录当前位置往上棋子出现的次数
   let down = 0; //记录当前位置往下棋子出现的次数
   let target = isWhite ? 'white':'black'; //获取当前棋子的颜色
   //循环4次,若有相同颜色的棋子出现次数+1
   for(let i = 1; i < 5; i++){
     //纵向x轴保持不变
     //向下找出现相同颜色的棋子,次数+1 
    if(circles[x][y-i] && circles[x][y-i] === target) down++;
    //向上找出现相同颜色的棋子,次数+1
    if(circles[x][y+i] && circles[x][y+i] === target) up++;
   }
   //4次都出现了相同颜色则返回true,及获胜
   return up+down >= 4;
}

5.横向逻辑同理,代码如下

function horizontalWin(x,y){
  let left = 0; //记录当前位置往左棋子出现的次数
  let right = 0; //记录当前位置往右棋子出现的次数
  let target = isWhite ? 'white':'black'; //获取当前棋子的颜色
  //循环4次,若有相同颜色的棋子出现次数+1
  for(let i = 1; i < 5; i++){
    //横向y轴保持不变
    //向左找出现相同颜色的棋子,次数+1 
   if(circles[x-i][y] && circles[x-i][y] === target) left++;
   //向右找出现相同颜色的棋子,次数+1
   if(circles[x+i][y] && circles[x+i][y] === target) right++;
  }
  //当4次都出现了相同颜色则返回true,及获胜
  return left+right >= 4;
}

6.判断斜向获胜,我们也分为左方和右方出现的次数想加来判断,
如果当前棋子位置前4列的位置时,是没办法实现左斜上方或左斜下方连出4子的情况,右边也同理,当前棋子位置后4列的位置时,不可能出现连续4子的情况,因此要先排除这类情况

 function obliqueWin(x,y) {
   let left = 0; //记录当前位置斜上方棋子出现的次数
   let right= 0; //记录当前位置斜下方棋子出现的次数
   let target = isWhite ? 'white':'black';
   for (let i = 1; i < 5; i++) {
     //判断左边斜上方和左边斜下方是否出现同色棋子
       if (x > 4 && ((circles[x - i][y + i] && circles[x - i][y + i])  || (circles[x - i][y - i] && circles[x - i][y - i]))=== target) left++;
        //判断右边斜上方和右边斜下方是否出现同色棋子
       if (x < 10 && ((circles[x + i][y-i] && circles[x+i][y-i]) || (circles[x + i][y+i] && circles[x + i][y+i])) === target) right++;
   }
        return left + right >= 4;
    }

以上就是我实现五子棋游戏交互的一个思路了,谢谢大家的观看!

  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值