点单微信小程序开_JS+canvas五子棋人机对战完成步

日期:2021-01-05 类型:行业动态 

关键词:凡科自助建站,企业网站怎么建设,智能建站系统,自己建个网站,搭建网站基本步骤

JS+canvas五子棋人机对战实现步骤详解       这篇文章主要介绍了JS+canvas五子棋人机对战实现步骤详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
var opts = opts || {}; if (opts.width opts.width%30 !== 0) throw new RangeError(opts.width+'不是30的倍数'); this.col = (opts.width opts.width/30) || 15; // 棋盘列 var oCanvas = document.createElement('canvas'); oCanvas.width = oCanvas.height = opts.width || 450; this.canvas = oCanvas; document.querySelector(opts.container || 'body').appendChild(this.canvas); this.ctx = oCanvas.getContext('2d'); }

4. 初始化棋盘

//棋盘初始化
Gobang.prototype.boardInit = function(opts){
 this.drawBoard();
// 画棋盘
Gobang.prototype.drawBoard = function(){
 this.ctx.strokeStyle = "#bfbfbf";
 for (var i = 0; i this.col; i++) {
 this.ctx.moveTo(15+ 30*i, 15);
 this.ctx.lineTo(15+ 30*i, this.col*30-15);
 this.ctx.stroke();
 this.ctx.moveTo(15, 15+ 30*i);
 this.ctx.lineTo(this.col*30-15, 15+ 30*i);
 this.ctx.stroke();
}

5. 画棋子

// 画棋子
Gobang.prototype.drawChess = function(x, y, player){
 var x = 15 + x * 30,
 y = 15 + y * 30;
 this.ctx.beginPath();
 this.ctx.arc(x, y, 13, 0, Math.PI*2);
 var grd = this.ctx.createRadialGradient(x + 2, y - 2, 13 , x + 2, y - 2, 0);
 if (player) { //我 == 黑棋 
 grd.addColorStop(0, '#0a0a0a');
 grd.addColorStop(1, '#636766');
 }else{ //电脑 == 白棋
 grd.addColorStop(0, '#d1d1d1');
 grd.addColorStop(1, '#f9f9f9');
 this.ctx.fillStyle = grd;
 this.ctx.fill()
}

6. 移动聚焦

// 鼠标移动时触发聚焦效果, 需要前面的聚焦效果消失, 所有需要重绘canvas
Gobang.prototype.mouseMove = function(){
 var that = this;
 this.canvas.addEventListener('mousemove', function (e) {
 that.ctx.clearRect(0, 0, that.col*30, that.col*30);
 var x = Math.floor((e.offsetX)/30),
 y = Math.floor((e.offsetY)/30);
 //重绘棋盘
 that.drawBoard();
 //移动聚焦效果
 that.focusChess(x, y);
 //重绘已经下好的棋子
 that.redrawedChess()
//鼠标移动聚焦
Gobang.prototype.focusChess = function(x, y){
 this.ctx.beginPath();
 this.ctx.fillStyle = '#E74343';
 this.ctx.arc(15 + x * 30, 15 + y * 30, 6, 0, Math.PI*2);
 this.ctx.fill();
//重绘当前下好的棋子
Gobang.prototype.redrawedChess = function(x, y){
 for (var i = 0; i this.existChesses.length; i++) {
 this.drawChess(this.existChesses[i].x, this.existChesses[i].y, this.existChesses[i].player);
}

7. 算法初始化

//算法初始化
Gobang.prototype.algorithmInit = function(){
 //初始化棋盘的每个位置和赢法
 for (var x = 0; x this.col; x++) {
 this.allChesses[x] = [];
 this.wins[x] = [];
 for (var y = 0; y this.col; y++) {
 this.allChesses[x][y] = false;
 this.wins[x][y] = [];
 //获取所有赢法
 putedWins();
 // 初始化电脑和我每个赢法当前拥有的棋子数
 for (var i = 0; i this.winsCount; i++) {
 this.myWins[i] = 0;
 puterWins[i] = 0;
}

8. 获取所有赢法

putedWins = function(){
 直线赢法
 以15列为准
 for (var x = 0; x this.col; x++) { //纵向所有赢法
 for (var y = 0; y this.col-4; y ++) {
 this.winsCount ++; 
 1.组成的第一种赢法
 [0,0]
 [0,1]
 [0,2]
 [0,3]
 [0,4]
 2.组成的第二种赢法
 [0,1]
 [0,2]
 [0,3]
 [0,4]
 [0,5]
 以此类推一列最多也就11种赢法, 所有纵向x有15列 每列最多11种, 所有纵向总共15 * 11种
 //以下for循环给每种赢法的位置信息储存起来
 for (var k = 0; k k ++) {
 this.wins[x][y+k][this.winsCount] = true;
 位置信息
 第一种赢法的时候:
 this.wins = [
 [1:true],
 [1:true],
 [1:true],
 [1:true],
 [1:true]
 ......
 虽然这是一个三维数组, 我们把它拆分下就好理解了
 相当于 this.wins[0][0][1], this.wins[0][4][1], this.wins[0][5][1], this.wins[0][6][1], this.wins[0][7][1]
 因为对象可以这样取值:
 var obj = {
 a: 10,
 b: 'demo'
 obj['a'] === obj.a
 所有也就相当于 this.wins[0][0].1, this.wins[0][8].1, this.wins[0][9].1, this.wins[0][10].1, this.wins[0][11].1 
 虽然数组不能这么取值,可以这么理解
 所以 this.wins[0][0].1 就可以理解为 在 x=0, y=0, 上有第一种赢法
 this.wins[0][12].1 就可以理解为 在 x=0, y=1, 上有第一种赢法
 ......
 以上this.wins[0][0],this.wins[0][13]...可以看作是 this.wins[x][y]
 所以第一种赢法的坐标就是: [0,0] [0,1] [0,2] [0,3] [0,4] 
 for (var y = 0; y this.col; y++) { //横向所有赢法, 同纵向赢法一样,也是15 * 11种
 for (var x = 0; x this.col-4; x ++) {
 this.winsCount ++;
 for (var k = 0; k k ++) {
 this.wins[x+k][y][this.winsCount] = true;
 }

交叉赢法

 交叉赢法
 for (var x = 0; x this.col-4; x++) { // 左 - 右 开始的所有交叉赢法 总共11 * 11种
 for (var y = 0; y this.col-4; y ++) {
 this.winsCount ++;
 1. [0,0]
 [1,1]
 [2,2]
 [3,3]
 [4,4]
 2. [0,1]
 [1,2]
 [2,3]
 [3,4]
 [4,5]
 3. [0,2]
 [1,3]
 [2,4]
 [3,5]
 [4,6]
 [1,0]
 [2,1]
 [3,2]
 [4,3]
 [5,5]
 相当于从左至右 一列列计算过去
 for (var k = 0; k k ++) {
 this.wins[x+k][y+k][this.winsCount] = true;
 for (var x = this.col-1; x x --) { //右 - 左 开始的所有交叉赢法 总共11 * 11种
 for (var y = 0; y this.col-4; y ++) {
 this.winsCount ++;
 for (var k = 0; k k ++) {
 this.wins[x-k][y+k][this.winsCount] = true;
}

9. 落子实现

//落子实现
Gobang.prototype.dorpChess = function(){
 var that = this;
 this.canvas.addEventListener('click', function(e) {
 // 判断是否结束
 if (that.over) return;
 var x = Math.floor((e.offsetX)/30),
 y = Math.floor((e.offsetY)/30);
 //判断该棋子是否已存在
 if (that.allChesses[x][y]) return;
 // 检查落子情况
 that.checkChess(x, y)
 if (!that.over) {
 that.player = false;
 puterDropChess();//计算机落子

//判断当前坐标赢的方法各自拥有几粒棋子 Gobang.prototype.currWinChesses = function(x, y, player){ var currObj = player this.myWins : puterWins; var enemyObj = puterWins : this.myWins; var currText = player '我' : '电脑'; for (var i = 1; i = this.winsCount; i++) { if (this.wins[x][y][i]) { //因为赢法统计是从1开始的 所以对应我的赢法需要减1 currObj[i-1] ++; // 每个经过这个点的赢法都增加一个棋子; enemyObj[i-1] = 6; //这里我下好棋了,证明电脑不可能在这种赢法上取得胜利了, 置为6就永远不会到5 if (currObj[i-1] === 5) { //当达到 5 的时候,证明我胜利了 alert(currText+'赢了') this.over = true; }

10. 计算机落子实现

// 计算机落子
puterDropChess = function(){
 var myScore = [], //玩家比分
 computerScore = [], // 电脑比分
 maxScore = 0; //最大比分

// 计算每种赢法,拥有多少棋子,获取对应分数 // 电脑起始分数需要高一些,因为现在是电脑落子, 优先权大 myScore[o.x][o.y] += formatScore(this.myWins[k-1], 10); computerScore[o.x][o.y] += puterWins[k-1], 11); //我的分数判断 if (myScore[o.x][o.y] maxScore) { //当我的分数大于最大分数时, 证明这个位置的是对我最有利的 maxScore = myScore[o.x][o.y]; x = o.x; y = o.y; }else if (myScore[o.x][o.y] === maxScore) { //当我的分数与最大分数一样时, 证明我在这两个位置下的效果一样, 所以我们应该去判断在这两个位置时,电脑方对应的分数 if (computerScore[o.x][o.y] computerScore[x][y]) { x = o.x; y = o.y; // 电脑分数判断, 因为是电脑落子, 所以优先权大 if (computerScore[o.x][o.y] maxScore) { maxScore = computerScore[o.x][o.y]; x = o.x; y = o.y; }else if (computerScore[o.x][o.y] === maxScore) { if (myScore[o.x][o.y] myScore[x][y]) { x = o.x; y = o.y; this.checkChess(x, y) if (!this.over) { this.player = true; var gobang = new Gobang(); gobang.init()


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