日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

JS+canvas五子棋人機對戰(zhàn)實現(xiàn)步驟詳解

瀏覽:184日期:2024-05-05 11:59:03

1. 創(chuàng)建實例

function Gobang () { this.over = false; // 是否結(jié)束 this.player = true; // true:我 false:電腦 this.allChesses = []; // 所有棋子 this.existChesses = [] // 已經(jīng)落下的棋子 this.winsCount = 0; // 贏法總數(shù) this.wins = []; // 所有贏法統(tǒng)計 this.myWins = []; //我的贏法統(tǒng)計 this.computerWins = []; //電腦贏法統(tǒng)計}

2. 初始化

//初始化Gobang.prototype.init = function(opts) { // 生成canvas棋盤 this.createCanvas(opts); //棋盤初始化 this.boardInit(); // 鼠標移動聚焦功能實現(xiàn) this.mouseMove(); //算法初始化 this.algorithmInit(); //落子功能實現(xiàn) this.dorpChess();}

3. 生成canvas棋盤

//初始化//生成canvasGobang.prototype.createCanvas = function(opts) { var opts = opts || {}; if (opts.width && opts.width%30 !== 0) throw new RangeError(opts.width+’不是30的倍數(shù)’); 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(); }}

JS+canvas五子棋人機對戰(zhàn)實現(xiàn)步驟詳解

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()}

JS+canvas五子棋人機對戰(zhàn)實現(xiàn)步驟詳解

6. 移動聚焦

// 鼠標移動時觸發(fā)聚焦效果, 需要前面的聚焦效果消失, 所有需要重繪canvasGobang.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); //重繪已經(jīng)下好的棋子 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();}//重繪當(dāng)前下好的棋子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); }}

JS+canvas五子棋人機對戰(zhàn)實現(xiàn)步驟詳解

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] = []; } } //獲取所有贏法 this.computedWins(); // 初始化電腦和我每個贏法當(dāng)前擁有的棋子數(shù) for (var i = 0; i < this.winsCount; i++) { this.myWins[i] = 0; this.computerWins[i] = 0; }}

8. 獲取所有贏法

Gobang.prototype.computedWins = 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循環(huán)給每種贏法的位置信息儲存起來 for (var k = 0; k < 5; k ++) {this.wins[x][y+k][this.winsCount] = true;/* 位置信息 第一種贏法的時候: this.wins = [ [ [1:true], [1:true], [1:true], [1:true], [1:true] ], [ ...... ] ] 雖然這是一個三維數(shù)組, 我們把它拆分下就好理解了 相當(dāng)于 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 所有也就相當(dāng)于 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 雖然數(shù)組不能這么取值,可以這么理解 所以 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 < 5; k ++) {this.wins[x+k][y][this.winsCount] = true; } } }

交叉贏法

JS+canvas五子棋人機對戰(zhàn)實現(xiàn)步驟詳解

/* 交叉贏法 */ 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] 相當(dāng)于從左至右 一列列計算過去 */ for (var k = 0; k < 5; k ++) {this.wins[x+k][y+k][this.winsCount] = true; } } } for (var x = this.col-1; x >= 4; x --) { //右 -> 左 開始的所有交叉贏法 總共11 * 11種 for (var y = 0; y < this.col-4; y ++) { this.winsCount ++; for (var k = 0; k < 5; k ++) {this.wins[x-k][y+k][this.winsCount] = true; } } }}

9. 落子實現(xiàn)

//落子實現(xiàn)Gobang.prototype.dorpChess = function(){ var that = this; this.canvas.addEventListener(’click’, function(e) { // 判斷是否結(jié)束 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; that.computerDropChess();//計算機落子 } })}//檢查落子情況Gobang.prototype.checkChess = function(x, y){ //畫棋 this.drawChess(x, y, this.player); //記錄落下的棋子 this.existChesses.push({ x: x, y: y, player: this.player }); //該位置棋子置為true,證明已經(jīng)存在 this.allChesses[x][y] = true; this.currWinChesses(x, y, this.player);}//判斷當(dāng)前坐標贏的方法各自擁有幾粒棋子Gobang.prototype.currWinChesses = function(x, y, player){ var currObj = player ? this.myWins : this.computerWins; var enemyObj = player ? this.computerWins : this.myWins; var currText = player ? ’我’ : ’電腦’; for (var i = 1; i <= this.winsCount; i++) { if (this.wins[x][y][i]) { //因為贏法統(tǒng)計是從1開始的 所以對應(yīng)我的贏法需要減1 currObj[i-1] ++; // 每個經(jīng)過這個點的贏法都增加一個棋子; enemyObj[i-1] = 6; //這里我下好棋了,證明電腦不可能在這種贏法上取得勝利了, 置為6就永遠不會到5 if (currObj[i-1] === 5) { //當(dāng)達到 5 的時候,證明我勝利了alert(currText+’贏了’)this.over = true; } } }}

10. 計算機落子實現(xiàn)

// 計算機落子Gobang.prototype.computerDropChess = function(){ var myScore = [], //玩家比分 computerScore = [], // 電腦比分 maxScore = 0; //最大比分 //比分初始化 var scoreInit = function(){ for( var x = 0; x < this.col; x ++) { myScore[x] = []; computerScore[x] = []; for (var y = 0; y < this.col; y ++) {myScore[x][y] = 0;computerScore[x][y] = 0; } } } scoreInit.call(this); //電腦待會落子的坐標 var x = 0, y = 0; // 基于我和電腦的每種贏法擁有的棋子來返回對應(yīng)的分數(shù) function formatScore(o, n) { if (o < 6 && o > 0) { var n = 10; for (var i = 0; i < o; i++) {n *= 3; } return n } return 0 } // 獲取沒有落子的棋盤區(qū)域 function existChess(arr) { var existArr = []; for (var i = 0; i < arr.length; i++) { for (var j = 0; j < arr[i].length; j++) {if (!arr[i][j]) { existArr.push({x:i, y:j})} } } return existArr; } var exceptArr = existChess(this.allChesses); // 循環(huán)未落子區(qū)域,找出分數(shù)最大的位置 for (var i = 0; i < exceptArr.length; i++) { var o = exceptArr[i]; // 循環(huán)所有贏的方法 for (var k = 0; k < this.winsCount; k++) { //判斷每個坐標對應(yīng)的贏法是否存在 if (this.wins[o.x][o.y][k]) {// 計算每種贏法,擁有多少棋子,獲取對應(yīng)分數(shù)// 電腦起始分數(shù)需要高一些,因為現(xiàn)在是電腦落子, 優(yōu)先權(quán)大myScore[o.x][o.y] += formatScore(this.myWins[k-1], 10);computerScore[o.x][o.y] += formatScore(this.computerWins[k-1], 11); } } //我的分數(shù)判斷 if (myScore[o.x][o.y] > maxScore) { //當(dāng)我的分數(shù)大于最大分數(shù)時, 證明這個位置的是對我最有利的 maxScore = myScore[o.x][o.y]; x = o.x; y = o.y; }else if (myScore[o.x][o.y] === maxScore) { //當(dāng)我的分數(shù)與最大分數(shù)一樣時, 證明我在這兩個位置下的效果一樣, 所以我們應(yīng)該去判斷在這兩個位置時,電腦方對應(yīng)的分數(shù) if (computerScore[o.x][o.y] > computerScore[x][y]) {x = o.x;y = o.y; } } // 電腦分數(shù)判斷, 因為是電腦落子, 所以優(yōu)先權(quán)大 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()

github地址

線上地址

以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持好吧啦網(wǎng)。

標簽: JavaScript
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
国产一区精品福利| 91久久久精品国产| 中文字幕一区二区精品区| 亚洲黄色影院| 丝袜美腿亚洲一区二区图片| 伊人精品一区| 亚洲专区一区| 777久久精品| av中文资源在线资源免费观看| 另类专区亚洲| 天堂网在线观看国产精品| 午夜宅男久久久| 日韩av在线免费观看不卡| 欧美国产另类| 视频福利一区| 免费成人性网站| 国产精久久久| 欧美黄色网页| 亚洲专区视频| 国产激情精品一区二区三区| 久久久久久一区二区| 1024精品久久久久久久久| 日韩有码av| 国产传媒在线观看| 蜜桃视频一区二区| 国产精品成人国产| 欧美女激情福利| 国产精品久久久久毛片大屁完整版| 欧美激情另类| 亚洲精品看片| 九九精品调教| 欧美日韩一区二区国产| 日韩在线免费| 97久久亚洲| 国产综合精品一区| 欧美久久精品| 午夜日韩av| 国产精品久久久久久久久妇女| 免费在线看一区| 麻豆国产91在线播放| 不卡中文一二三区| 国产精品多人| 亚洲欧美激情诱惑| 在线人成日本视频| 国产亚洲精aa在线看| 日韩天堂av| 日韩欧美三级| 欧美激情91| 无码日韩精品一区二区免费| 色老板在线视频一区二区| 日韩av网站在线免费观看| 蜜臀av免费一区二区三区| 精品视频自拍| 91精品在线免费视频| 日韩视频免费| 日韩毛片在线| 国产一区日韩| 国产日韩一区二区三区在线播放| 欧美日韩国产一区精品一区| 精品一二三区| 欧美亚洲三级| 综合欧美精品| 日韩午夜av在线| 日韩视频网站在线观看| 免费一级欧美在线观看视频| 午夜在线视频一区二区区别| 亚洲日本网址| 不卡福利视频| 久久精品资源| 国产伦一区二区三区| 日韩中文字幕| 蜜臀va亚洲va欧美va天堂| re久久精品视频| 91精品推荐| 精精国产xxxx视频在线播放 | 精品视频在线一区二区在线| 亚洲3区在线| 模特精品在线| 欧美午夜精彩| 欧美一级精品| 免费精品国产的网站免费观看| 亚洲国产福利| 日韩av免费大片| 精品日韩在线| 国产a亚洲精品| 国产一区一一区高清不卡| 美女视频黄 久久| 麻豆一区二区99久久久久| 国产日韩一区| 欧美精品成人| 粉嫩av一区二区三区四区五区 | 美女高潮久久久| 欧美精品第一区| 麻豆一区二区三| 精品国产一级| 国产一区二区视频在线看| 国产成人免费视频网站视频社区| 精品久久亚洲| 黑人精品一区| sm久久捆绑调教精品一区| 日韩精品欧美激情一区二区| 日韩久久精品网| 欧美日韩精品一区二区视频| 女同性一区二区三区人了人一| 欧美日韩日本国产亚洲在线| 视频一区二区三区中文字幕| 日本va欧美va瓶| 国产福利资源一区| 福利片在线一区二区| 亚洲成av人片一区二区密柚| 激情综合网五月| 免费高清在线一区| 日本午夜精品| yellow在线观看网址| 999久久久精品国产| 天堂va蜜桃一区二区三区| 一区二区电影在线观看| 久久激情五月婷婷| 中文字幕在线免费观看视频| 九色精品91| 亚洲精品黄色| 国产精品对白久久久久粗| 亚洲黄色中文字幕| 在线视频精品| 国产一卡不卡| 日韩三区免费| 亚洲制服欧美另类| 精品一区二区三区免费看| 欧美丝袜一区| 日韩国产欧美三级| 日韩欧美综合| 国产亚洲精品v| 国产探花一区| 久久高清精品| 日本久久一区| 91精品蜜臀一区二区三区在线| 亚洲男人在线| 激情亚洲影院在线观看| 亚洲精品美女91| 亚洲精品**中文毛片| 亚洲精品大全| 在线亚洲人成| 国产免费av一区二区三区| 久久国产电影| 亚洲精品国产精品粉嫩| 国产传媒av在线| 亚洲综合国产| 成人午夜毛片| 欧美日韩一视频区二区| 国产综合精品一区| 精品国内亚洲2022精品成人| 国产亚洲高清视频| 精品亚洲自拍| 亚洲精品大片| 99视频精品全国免费| 国产精品久久久久久久免费软件| 欧美日韩激情| 日韩av免费大片| 日韩精品免费一区二区夜夜嗨 | 亚洲97av| 久久精品国产www456c0m| 久久国产精品免费一区二区三区| 黄色不卡一区| 日韩欧美精品一区| 国产精品蜜月aⅴ在线| 久久都是精品| 四虎影视精品| 精品不卡一区| 欧美一区不卡| 亚洲永久精品唐人导航网址| 91精品国产乱码久久久久久久| 欧美精品99| 亚洲精品乱码久久久久久蜜桃麻豆| 久久久久久久久成人| 日本亚洲视频在线| 老鸭窝亚洲一区二区三区| 99精品网站| 神马久久午夜| 国内精品麻豆美女在线播放视频| 欧美一区自拍| 日本亚洲视频在线| 天堂成人免费av电影一区 | 国产一区福利| 国产欧美丝祙| 日韩中出av| 黄色国产精品| 久久精品一区二区不卡| 成人在线免费观看91| 国产精品对白久久久久粗| 亚洲精品成人一区| 亚洲欧美日韩专区| 99国产精品久久久久久久成人热| 日韩精品午夜| 肉色欧美久久久久久久免费看| 久久久免费人体| 国产精品一在线观看| 欧美日韩18| 国产精品激情| 久久99蜜桃| 四季av一区二区凹凸精品|