js實(shí)現(xiàn)AI五子棋人機(jī)大戰(zhàn)
本文實(shí)例為大家分享了js實(shí)現(xiàn)AI五子棋人機(jī)大戰(zhàn)的具體代碼,供大家參考,具體內(nèi)容如下
實(shí)現(xiàn)原理就是計(jì)算五子棋所有贏的種類,利用canvas實(shí)現(xiàn)五子棋排版落子。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>五子棋</title> <style> #canvas{ display: block; margin:50px auto; box-shadow: -2px -2px 2px #EFEFEF, 5px 5px 5px #b9b9b9; } </style> </head> <body> <canvas id="canvas" width="450px" height="450px"></canvas> <script> var canvas = document.getElementById('canvas'); var context = canvas.getContext('2d'); var me = true; //true黑子, false, 白子 var over = false; var box = []; //全部落子點(diǎn) var wins = []; //全部贏的方法 三維數(shù)組 for(var i = 0; i< 15 ;i++) { box[i] = []; wins[i] = []; for(var j = 0; j < 15; j++) { box[i][j] = 0; wins[i][j] = []; } } var count = 0; //總共贏的數(shù)量572種 //橫向 for(var a = 0; a < 15; a++) { for(var b = 0; b < 11;b++) { //wins[0][0][0] //wins[0][1][0] //wins[0][2][0] for(var c = 0; c < 5;c++) { wins[a][b + c][count] = true; } count++; } } //縱向 for(var a = 0; a < 15; a++) { for(var b = 0; b < 11;b++) { //wins[0][0][0] //wins[0][1][0] //wins[0][2][0] for(var c = 0; c < 5;c++) { wins[b + c][a][count] = true; } count++; } } //斜 '\' for(var a = 0; a < 11; a++) { for(var b = 0; b < 11;b++) { //a = 0, b = 10 //win[0][10] //win[1][11] for(var c =0; c < 5;c++) { wins[a + c][b + c][count] = true; } count++; } } //反斜 '/' for(var a = 0; a < 11; a++) { for(var b = 4; b < 15;b++) { //a = 0, b = 0 //win[0][5] //win[1][4] for(var c =0; c < 5;c++) { wins[a + c][b - c][count] = true; } count++; } } //我方、計(jì)算機(jī)方總共可以贏的數(shù)量,每在某一方式上可以贏的位置下一顆子,myWin[i]++ //當(dāng)myWin[i] == 5,說明我方在這個方式上贏的落子已經(jīng)達(dá)到5顆,說明我方已經(jīng)贏了 var myWin = []; // var computerWin = []; for(var i = 0; i < count;i++) { myWin[i] = 0; computerWin[i] = 0; } //畫縱橫線條 function drawLine() { context.strokeStyle = '#ccc'; for(var i = 0; i < 15; i++) { context.moveTo(15 + 30 * i, 15); context.lineTo(15 + 30 * i, 435); context.stroke(); context.moveTo(15, 15 + 30 * i); context.lineTo(435, 15 + 30 * i); context.stroke(); } } drawLine() //走一步,畫黑白子,并記錄,黑子為1,白子為2 function oneStep(i, j, me) { context.beginPath(); context.arc(15 + i * 30, 15 + j*30, 13, 0, Math.PI * 2); context.closePath(); var gradient = context.createRadialGradient(15 + i * 30 + 2, 15 + j*30 - 2, 13, 15 + i * 30 + 2, 15 + j*30 - 2, 0) if(me) { //黑子 gradient.addColorStop(0, '#0A0A0A'); gradient.addColorStop(1, '#636766'); box[i][j] = 1; } else { //白子 gradient.addColorStop(0, '#D1D1D1'); gradient.addColorStop(1, '#F9F9F9'); box[i][j] = 2; } context.fillStyle = gradient; context.fill(); } canvas.onclick = function(e) { if(over) return; if(!me) return; var x = Math.floor(e.offsetX/30); var y = Math.floor(e.offsetY/30); if(box[x][y] == 0) { //判斷沒有落子 oneStep(x, y, me); for(var k = 0; k<count; k++) {//第幾種贏法 if(wins[x][y][k]) { myWin[k]++; computerWin[k] = 6; //因?yàn)槲曳皆谶@個點(diǎn)上已經(jīng)落子,所以計(jì)算機(jī)不可能在這個點(diǎn)上贏, if(myWin[k] == 5) { console.log('你贏了') over = true; } } } if(!over) { me = !me; computerAI(); } } } //計(jì)算機(jī) function computerAI() { var myScore = []; //我方分?jǐn)?shù) var computerScore = []; //計(jì)算機(jī)分?jǐn)?shù) var max = 0; //最大分?jǐn)?shù) var u = 0, v = 0; //最大分?jǐn)?shù)點(diǎn) for(var i =0; i < 15; i++) { myScore[i] = []; computerScore[i] = []; for(var j =0; j < 15; j++) { myScore[i][j] = 0; computerScore[i][j] = 0; } } for(var i =0; i < 15; i++) { for(var j =0; j < 15; j++) { if(box[i][j] == 0) { //每個空閑點(diǎn)上進(jìn)行計(jì)算分?jǐn)?shù) for(var k =0;k<count;k++) { //遍歷所有可以贏的,數(shù)量 if(wins[i][j][k]) { //可以贏的點(diǎn)進(jìn)行算分 if(myWin[k] == 1) { myScore[i][j] += 200; } else if(myWin[k] == 2) { myScore[i][j] += 400; } else if(myWin[k] == 3) { myScore[i][j] += 2000; } else if(myWin[k] == 4) { myScore[i][j] += 10000; } if(computerWin[k] == 1) { computerScore[i][j] += 220; } else if(computerWin[k] == 2) { computerScore[i][j] += 420; } else if(computerWin[k] == 3) { computerScore[i][j] += 2100; } else if(computerWin[k] == 4) { computerScore[i][j] += 20000; } } } //得出最大分?jǐn)?shù)的點(diǎn),并賦給u,v if(myScore[i][j] > max) { max = myScore[i][j]; u = i; v = j; } else if(myScore[i][j] == max) { if(computerScore[i][j] > computerScore[u][v]) { u = i; v = j; } } if(computerScore[i][j] > max) { max = computerScore[i][j]; u = i; v = j; } else if(computerScore[i][j] == max) { if(myScore[i][j] > myScore[u][v]) { u = i; v = j; } } }//所有空閑點(diǎn)上進(jìn)行計(jì)算分?jǐn)?shù) } } oneStep(u, v, false); //走一步 for(var k = 0; k<count; k++) {//第幾種贏法 if(wins[u][v][k]) { computerWin[k]++; myWin[k] = 6; if(computerWin[k] == 5) { console.log('計(jì)算機(jī)贏了--') over = true; } } } if(!over) { me = !me; } } </script> </body> </html>
效果圖如下
實(shí)際操作效果還行,但相比真正ai實(shí)現(xiàn)還是有很多不足。/p>
更多有趣的經(jīng)典小游戲?qū)崿F(xiàn)專題,分享給大家:
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
JS實(shí)現(xiàn)點(diǎn)擊網(wǎng)頁判斷是否安裝app并打開否則跳轉(zhuǎn)app store
這篇文章主要介紹了JS實(shí)現(xiàn)點(diǎn)擊網(wǎng)頁判斷是否安裝app并打開否則跳轉(zhuǎn)app store的相關(guān)資料,非常不錯,具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11JavaScript禁用右鍵單擊優(yōu)缺點(diǎn)分析
在本篇文章里小編給大家分享了關(guān)于JavaScript禁用右鍵單擊優(yōu)缺點(diǎn)分析,有需要的朋友們學(xué)習(xí)下。2019-01-01document.documentElement和document.body區(qū)別介紹
body是DOM對象里的body子節(jié)點(diǎn),即body標(biāo)簽,documentElement 是整個節(jié)點(diǎn)樹的根節(jié)點(diǎn)root,詳細(xì)介紹請看本文,感興趣的朋友可以參考下2013-09-09通過MSXML2自動獲取QQ個人頭像及在線情況(給初學(xué)者)
通過MSXML2自動獲取QQ個人頭像及在線情況(給初學(xué)者)...2007-01-01echarts學(xué)習(xí)之如何給餅圖中間添加文字
這篇文章主要介紹了echarts學(xué)習(xí)之如何給餅圖中間添加文字問題,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-03-03基于javascript制作經(jīng)典傳統(tǒng)的拼圖游戲
這篇文章主要為大家詳細(xì)介紹了基于javascript制作拼圖游戲的相關(guān)內(nèi)容,經(jīng)典傳統(tǒng)的拼圖游戲是大家最喜愛的游戲之一,具有挑戰(zhàn)性,感興趣的小伙伴們可以參考一下2016-03-03js方法數(shù)據(jù)驗(yàn)證的簡單實(shí)例
下面小編就為大家?guī)硪黄猨s方法數(shù)據(jù)驗(yàn)證的簡單實(shí)例。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-09-09