前言:说在前面的画
可能,一进来最关心的就是,实现的到底是个啥样,那就来一张动图呗,先声明一下,关于电脑的落子算法,本文只是简单的实现了一下(在玩家周围一格随机获取位置),如果懂机器学习可以引入机器学习的相关算法,来获取电脑应该下载哪(位置)
看过我前几篇关于canvas
的相关介绍和用法,你会发现,其实绘制棋盘。在指定的位置绘制棋子都是一件容易的事情(在指定位置绘制棋子,关键是:像素位置和坐标之间的相互转换)
如果上面的程序没有太大问题的话,那么接下来,就要考虑在什么时候绘制玩家棋子,可能,你已经想到了,就是cnavas.click()
事件。在这个事件里获取点击的位置然后转换为,棋盘里面的坐标。当然,玩家也不能一直不断的下,必须是你下一下,我下一下的模式。如何实现?我是这样实现的,定义一个类属性this.isMyTurn
当这个值为true
的时候,就轮到玩家落子,玩家一落完子,就将其值设置为false
。然后,就是电脑落子,电脑落子完成后,设置this.isMyTurn
为true
允许玩家落子。(当this.isMyTurn
为false
的时候,canvas.click()
在获取了坐标后不做任何事情,这里的事情指的是:玩家和电脑的落子和胜负判断)。
下面最关键的部分来了:如何判断胜负
给一个思路:就是遍历棋盘,判断棋盘中的每一个坐标的上下/左右/左对角线/右对角线
是否是五个棋子直连
。当然这个思路问题不大,但是可以不这样做,只是判断 当前落子的位置的四个方向。因为你前面的棋子肯定不会构成胜利的判断,只有当前下的棋子才有可能。
第一部分:核心类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