基于javascript canvas实现五子棋游戏


Posted in Javascript onJuly 08, 2020

本文实例为大家分享了基于canvas的五子棋的具体代码,供大家参考,具体内容如下

第一部分:核心类Gobang

属性:

this.box = box; // 存放五子棋的容器
this.canvas = null; // 画布
this.ctx = null;
this.size = 600; // 棋盘大小
this.cellNum = 20; // 单行棋格数量
this.padding = this.size/this.cellNum; // padding值
this.cellSize = (this.size-this.padding*2)/this.cellNum; // 棋格大小
this.pieceSize = this.cellSize*3/4; // 棋子大小
this.color = ["black", "#aaa"]; // 棋子颜色
this.myPieceType = null; // 玩家棋子类型
this.aiPieceType = null; // 电脑棋子类型
this.myPieces = []; // 玩家累计棋子
this.aiPieces = []; // 电脑累计棋子
this.isMyTurn = true; // 先手
this.curPos = [this.cellNum/2-1, this.cellNum/2-1]; // 当前点击位置
this.timeId = null; // 定时器id

方法:

init// 初始化方法,获取canvas设置宽高,获取ctx
createChessboard// 创建背景棋盘
drawPiece// 画一个棋子
clearPiece// 清除棋子
registClick// 注册鼠标点击事件,主要的逻辑函数
isIn// 判断否在所下的棋子里面
isInAll// 判断是否在所有下的棋子里面
isFull// 是否下满
aiPutPiece// 电脑落子,只是简单的实现了,获取玩家落子位子周围一格的随机位置
putPiece// 实现下棋的函数
isWin// 胜利判断,个人人为比较男一点点的算法
run// 运行,类的入口函数,里面调用了,·init·/createChessBoard/registClick方法

第二部分:源代码

Gobang.js

/** 五子棋 **/

function Gobang(box){
  this.box = box; // 存放五子棋的容器
  this.canvas = null; // 画布
  this.ctx = null;
  this.size = 600; // 棋盘大小
  this.cellNum = 20; // 单行棋格数量
  this.padding = this.size/this.cellNum; // padding值
  this.cellSize = (this.size-this.padding*2)/this.cellNum; // 棋格大小
  this.pieceSize = this.cellSize*3/4; // 棋子大小
  this.color = ["black", "#aaa"]; // 棋子颜色
  this.myPieceType = null; // 玩家棋子类型
  this.aiPieceType = null; // 电脑棋子类型
  this.myPieces = []; // 玩家累计棋子
  this.aiPieces = []; // 电脑累计棋子
  this.isMyTurn = true; // 先手
  this.curPos = [this.cellNum/2-1, this.cellNum/2-1]; // 当前点击位置
  this.timeId = null; // 定时器id
  
  // 初始化方法
  this.init = function(){
    // 创建canvas
    this.canvas = document.createElement("canvas");
    // 设置宽高
    this.canvas.width = this.canvas.height = this.size;
    // 加入到容器中
    this.box.appendChild(this.canvas);
    // 获取ctx
    this.ctx = this.canvas.getContext("2d");
  };
  // 创建背景棋盘
  this.createChessboard = function(){
    // ----------- 边框 -----------
    this.ctx.lineWidth = 10;
    this.ctx.lineJoin = "round";
    this.ctx.strokeRect(0, 0, this.size, this.size);
    // ----------- 创建棋盘 -----------
    this.ctx.lineWidth = 1;
    for (var i = 0; i <= this.cellNum; i++) {
      // 画横线
      this.ctx.beginPath();
      this.ctx.moveTo(this.padding, this.padding+i*this.cellSize);
      this.ctx.lineTo(this.size-this.padding, this.padding+i*this.cellSize);
      this.ctx.stroke();
      // 画竖线
      this.ctx.beginPath();
      this.ctx.moveTo(this.padding+i*this.cellSize, this.padding);
      this.ctx.lineTo(this.padding+i*this.cellSize, this.size-this.padding);
      this.ctx.stroke();
    }
  };
  // 画一个棋子
  this.drawPiece = (x, y, type=0) => {
    // 根据坐标计算出图中位置
    var posX, posY;
    posX = this.padding + x * this.cellSize;
    posY = this.padding + y * this.cellSize;
    // 创建渐变色
    var grd = this.ctx.createRadialGradient(posX, posY, this.pieceSize/18, posX, posY, this.pieceSize);
    // type: 0, 黑棋 1, 白棋
    grd.addColorStop(0, this.color[1-type]);
    grd.addColorStop(0, this.color[type]);
    this.ctx.fillStyle = grd;
    // 画圆
    this.ctx.beginPath(); this.ctx.arc(posX, posY, this.pieceSize/2, 0, 2*Math.PI); this.ctx.fill();
  };
  // 清除棋子
  this.clearPiece = (x, y) => {
    // 清除棋子所在位置的像素
    var posX, posY;
    posX = this.padding + x * this.cellSize - this.pieceSize/2;
    posY = this.padding + y * this.cellSize - this.pieceSize/2;
    this.ctx.clearRect(posX, posY, this.pieceSize, this.pieceSize);
    // 补上十字架
    this.ctx.lineWidth = 1;
    // 竖线
    this.ctx.beginPath(); this.ctx.moveTo(posX+this.pieceSize/2, posY); this.ctx.lineTo(posX+this.pieceSize/2, posY+this.pieceSize); this.ctx.stroke();
    // 横线
    this.ctx.beginPath(); this.ctx.moveTo(posX, posY+this.pieceSize/2); this.ctx.lineTo(posX+this.pieceSize, posY+this.pieceSize/2); this.ctx.stroke();
  };
  // 注册鼠标点击事件
  this.registClick = function(){
    this.canvas.addEventListener("click", (ev) => {
      // 将位置坐标,转换为点
      var x = Math.round((ev.clientX - this.padding)/this.cellSize);
      x = x <= 0 ? 0 : x; x = x > this.cellNum ? this.cellNum : x;
      var y = Math.round((ev.clientY - this.padding)/this.cellSize);
      y = y <= 0 ? 0 : y; y = y > this.cellNum ? this.cellNum : y;
      // 设置当前位置
      this.curPos = [x, y];
      // 玩家落子
      if(this.isMyTurn && !this.isInAll(this.curPos)){ // 判断是否轮到玩家,并且下的位置是否重复
        this.putPiece(this.myPieces, this.curPos);
      }
      else return; // 轮到玩家的时候才能落子
      // 判断输赢
      if(this.isWin(this.myPieces)) {setTimeout(function(){alert("you win!");}, 100); return;}
      // 电脑落子
      this.aiPutPiece();
      // 判断输赢
      if(this.isWin(this.aiPieces)) {setTimeout(function(){alert("robot win!");}, 100); return;}
      this.isMyTurn = true;
    });
  };
  // 判断否在所下的棋子里面
  this.isIn = (pos, arr) => {
    var len = arr.length;
    for(var i=0; i < len; i++){
      if(pos[0] == arr[i][0] && pos[1] == arr[i][1]) return true;
    }
    return false;
  };
  // 判断是否在所有下的棋子里面
  this.isInAll = (pos) => {
    return this.isIn(pos, this.myPieces.concat(this.aiPieces));
  }
  // 是否下满
  this.isFull = () => {
    return (this.myPieces.length + this.aiPieces.length) == (this.cellNum+1) * (this.cellNum+1);
  };
  // 电脑落子
  this.aiPutPiece = ()=>{
    var x, y;
    // 目前,制作了一点功能,就是在玩家刚刚落子的周围一格落子
    // 1. 获得随机的周围的坐标
    while(1){
      x = this.curPos[0] + Math.pow(-1, parseInt(Math.random()*2));
      y = this.curPos[1] + Math.pow(-1, parseInt(Math.random()*2));
      if(x >=0 && x <=20 && y >= 0 && y <=20 && !this.isInAll([x, y])) break;
    }
    // 2. 落子
    this.putPiece(this.aiPieces, [x, y], 1);
  }
  // 实现下棋的函数
  this.putPiece = (pieces, pos, type=0) => {
    this.drawPiece(pos[0], pos[1], type);
    pieces.push(pos);
  }
  // 胜利判断
  this.isWin = (pieces) => {
    /* 
    * 这里不用遍历棋盘来判断四个方向,只需要判断当前落子位置的四个方向。
    */
    var x, y, count = 0;

    // 处在水平线上 判断 
    x = this.curPos[0]-1; y = this.curPos[1];
    while(1) if(this.isIn([x, y], pieces)) {count++; x--;} else break; // 左边
    x = this.curPos[0]+1; y = this.curPos[1];
    while(1) if(this.isIn([x, y], pieces)) {count++; x++;} else break; // 右边
    if(count >= 4) return true; else /** 左右匹配失败 **/ count = 0;
    
    // 处在垂直线上 判断 比较四次
    x = this.curPos[0]; y = this.curPos[1]-1;
    while(1) if(this.isIn([x, y], pieces)) {count++; y--;} else break; // 上边
    x = this.curPos[0]; y = this.curPos[1]+1;
    while(1) if(this.isIn([x, y], pieces)) {count++; y++;} else break; // 下边
    if(count >= 4) return true; else /** 上下匹配失败 **/ count = 0;

    // 处在左对角线上的判断
    x = this.curPos[0]-1; y = this.curPos[1]-1;
    while(1) if(this.isIn([x, y], pieces)) {count++; x--; y--;} else break; // 左上
    x = this.curPos[0]+1; y = this.curPos[1]+1;
    while(1) if(this.isIn([x, y], pieces)) {count++; x++; y++;} else break; // 右下
    if(count >= 4) return true; else /** 左对角线匹配失败 **/ count = 0;

    // 处在右对角线上的判断
    x = this.curPos[0]+1; y = this.curPos[1]-1;
    while(1) if(this.isIn([x, y], pieces)) {count++; x++; y--;} else break; // 右上
    x = this.curPos[0]-1; y = this.curPos[1]+1;
    while(1) if(this.isIn([x, y], pieces)) {count++; x--; y++;} else break; // 左下
    if(count >= 4) return true; else /** 右对角线匹配失败 **/ return false;
  };
  // 运行
  this.run = function(){
    // 初始化方法
    this.init();
    // 创建棋盘
    this.createChessboard();
    // 注册点击事件
    this.registClick();
  }
}

五子棋.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>06-五子棋</title>
  <script src="../gobang.js"></script>
  <style>
    *{
      margin: 0;
      padding: 0;
    }
  </style>
</head>
<body>
  <div id="box"></div>
  <script>
    var box = document.getElementById("box");
    var gobang = new Gobang(box);
    gobang.run();
  </script>
</body>
</html>

更多有趣的经典小游戏实现专题,分享给大家:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
基于jquery实现的一个选择中国大学的弹框 (数据、步骤、代码)
Jul 26 Javascript
jquery获取焦点和失去焦点事件代码
Apr 21 Javascript
jQuery Validate验证框架经典大全
Sep 23 Javascript
javascript中checkbox使用方法简单实例演示
Nov 17 Javascript
基于javascript如何传递特殊字符
Nov 30 Javascript
jQuery事件与动画基础详解
Feb 23 Javascript
BootstrapValidator实现注册校验和登录错误提示效果
Mar 10 Javascript
H5上传本地图片并预览功能
May 08 Javascript
JS/HTML5游戏常用算法之路径搜索算法 随机迷宫算法详解【普里姆算法】
Dec 13 Javascript
node全局变量__dirname与__filename的区别
Jan 14 Javascript
微信小程序时间戳转日期的详解
Apr 30 Javascript
JavaScript大数相加相乘的实现方法实例
Oct 18 Javascript
深度解读vue-resize的具体用法
Jul 08 #Javascript
详解React 条件渲染
Jul 08 #Javascript
webpack5 联邦模块介绍详解
Jul 08 #Javascript
实例讲解React 组件
Jul 07 #Javascript
JavaScript eval()函数定义及使用方法详解
Jul 07 #Javascript
详解React 元素渲染
Jul 07 #Javascript
JS数据类型判断的几种常用方法
Jul 07 #Javascript
You might like
PHP教程 变量定义
2009/10/23 PHP
PHP采用自定义函数实现遍历目录下所有文件的方法
2014/08/19 PHP
PHP中使用localhost连接Mysql不成功的解决方法
2014/08/20 PHP
PHP页面输出搜索后跳转下一页的处理方法
2016/09/30 PHP
原生php实现excel文件读写的方法分析
2018/04/25 PHP
微信公众平台开发教程④ ThinkPHP框架下微信支付功能图文详解
2019/04/10 PHP
浅谈laravel框架sql中groupBy之后排序的问题
2019/10/17 PHP
JS 的应用开发初探(mootools)
2009/12/19 Javascript
Javascript动态绑定事件的简单实现代码
2010/12/25 Javascript
Jquery插件 easyUI属性汇总
2011/01/19 Javascript
取消选中单选框radio的三种方式示例介绍
2013/12/23 Javascript
一个简单的jquery的多选下拉框(自写)
2014/05/05 Javascript
浅谈使用MVC模式进行JavaScript程序开发
2015/11/10 Javascript
AngularJS仿苹果滑屏删除控件
2016/01/18 Javascript
jquery+css3实现会动的小圆圈效果
2016/01/27 Javascript
详解Nodejs之静态资源处理
2017/06/05 NodeJs
JS运动改变单物体透明度的方法分析
2018/01/23 Javascript
React+TypeScript+webpack4多入口配置详解
2019/08/08 Javascript
[02:50]【扭转乾坤,只此一招】DOTA2永雾林渊版本开启新篇章
2020/12/22 DOTA
python使用xauth方式登录饭否网然后发消息
2014/04/11 Python
Python中使用logging模块打印log日志详解
2015/04/05 Python
Python实现的HTTP并发测试完整示例
2020/04/23 Python
在Python的Flask中使用WTForms表单框架的基础教程
2016/06/07 Python
深入浅出分析Python装饰器用法
2017/07/28 Python
关于Python3 lambda函数的深入浅出
2019/11/27 Python
win10下opencv-python特定版本手动安装与pip自动安装教程
2020/03/05 Python
利用CSS3的transform做的动态时钟效果
2011/09/21 HTML / CSS
html5 datalist 选中option选项后的触发事件
2020/03/05 HTML / CSS
Free People中国官网:波西米亚风格女装服饰
2016/08/30 全球购物
2014年母亲节寄语
2014/05/07 职场文书
离婚协议书范文2014(夫妻感情破裂)
2014/12/14 职场文书
十岁生日答谢词
2015/01/05 职场文书
何玥事迹观后感
2015/06/16 职场文书
2016年公共机构节能宣传周活动总结
2016/04/05 职场文书
详解java如何集成swagger组件
2021/06/21 Java/Android
Python pandas求方差和标准差的方法实例
2021/08/04 Python