日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

canvas简易人机五子棋

發布時間:2023/12/10 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 canvas简易人机五子棋 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

中學時看過一本關于圍棋的漫畫《棋魂》,奈何天賦有限,圍棋至今也不會……好吧,退而求其次,五子棋相對簡單一點。對著網上的教程實現了一個簡單的五子棋:


其實ui的實現并不難,主要記錄下ai的思路吧。

// 繪制棋盤for (var i = 0; i < 15; i++) {context.beginPath();context.moveTo(15 + i * 30, 15);context.lineTo(15 + i * 30, 435);context.stroke();context.beginPath();context.moveTo(15, 15 + i * 30);context.lineTo(435, 15 + i * 30);context.stroke();};五子棋的棋盤為15*15,落子黑先白后,落子的過程其實就是在繪制旗子。
// 繪制棋子function oneStep(x, y, color) {// x,y為棋子在棋盤的坐標索引,color為黑棋或白棋context.beginPath();context.arc(15 + x * 30, 15 + y * 30, 12, 0, 2 * Math.PI);context.closePath();var gradient = context.createRadialGradient(15 + x * 30 + 2, 15 + y * 30 - 2, 12, 15 + x * 30 + 2, 15 + y * 30 - 2, 0);if (color) {gradient.addColorStop(0, '#0a0a0a');gradient.addColorStop(1, '#636766');} else {gradient.addColorStop(0, '#d1d1d1');gradient.addColorStop(1, '#f9f9f9');};context.fillStyle = gradient;context.fill();}

需要一個二維數組記錄當前棋盤的落子情況,每次落子需要判斷勝負以及是否結束。

var me = true; var chessBoard = []; //創建一個二維數組用于記錄當前棋盤的落子情況 var wins = []; //三維數組記錄五子棋所有的贏法 var count = 0; //記錄五子棋所有贏法的索引 var over = false;

//落子事件chess.onclick = function(e) {var x = e.offsetX;var y = e.offsetY;var i = Math.floor(x / 30);var j = Math.floor(y / 30);if (chessBoard[i][j] == 0 && !over) { //沒有落子的位置才能落子,黑子為1,白子為2oneStep(i, j, me);if (me) {chessBoard[i][j] = 1;} else {chessBoard[i][j] = 2;};console.log(chessBoard);winner(i, j, me);me = !me;if (!over) {computerAI(me);};};}先說判斷勝負,其實無論哪方,五子連珠作為勝利的條件,在15*15的棋盤上勝利的所有情況是可以枚舉出來的。
for (var i = 0; i < 15; i++) { //橫向統計所有的贏法for (var j = 0; j < 11; j++) {for (var k = 0; k < 5; k++) {wins[i][j + k][count] = true;};count++;};};for (var i = 0; i < 15; i++) { //縱向統計所有的贏法for (var j = 0; j < 11; j++) {for (var k = 0; k < 5; k++) {wins[j + k][i][count] = true;};count++;};};for (var i = 0; i < 11; i++) { //斜向統計所有的贏法for (var j = 0; j < 11; j++) {for (var k = 0; k < 5; k++) {wins[i + k][j + k][count] = true;};count++;};};for (var i = 0; i < 11; i++) { //斜向統計所有的贏法for (var j = 14; j > 3; j--) {for (var k = 0; k < 5; k++) {wins[i + k][j - k][count] = true;};count++;};};console.log(count);

關鍵在于wins這個三維數組,有點難理解,舉個例子:假如五子棋只有一種贏法:


那么count的值為1,但五子棋可不能一次就落五個子(這還怎么玩?)所以,每一種贏法要包含五個落子的坐標,也就是說,這五個落子的位置,無論落子先后,只要達成五子連珠,此種贏法就實現了。
var black = [];var white = [];//分別記錄五子棋黑白的贏法數組這兩個數組結合wins數組來判斷勝負,五子棋共有572種贏法,默認黑子與白子的贏法都為0。
for (var i = 0; i < count; i++) { //開局默認黑白所有的贏法都是0black[i] = 0;white[i] = 0;};

還是用上面的例子,如果黑方在第一種贏法處落下一子,那么黑子的第一種贏法+1,同時白子此種贏法作廢。

//判斷輸贏function winner(i, j, color) {for (var k = 0; k < count; k++) {if (wins[i][j][k]) {if (color) {black[k]++;white[k] = 6;//如果某種贏法黑子已經落子,白子此種贏法就作廢} else {white[k]++;black[k] = 6;};if (black[k] == 5) {alert('黑子獲勝');over = true;};if (white[k] == 5) {alert('白子獲勝');over = true;};};};}代碼到這里,已經能實現五子棋的規則邏輯了,接下來實現ai。

var blackScore = []; var whiteScore = []; //分別記錄五子棋黑白的二維得分數組 這個ai其實挺簡單的,實現思路就是通過遍歷每一個能落子的空坐標,然后結合算法找出分數最高的一個位置落子。
//AIfunction computerAI(color) {var max = 0;var u = 0;var v = 0;// 保存最大的分數和相應坐標for (var i = 0; i < 15; i++) {blackScore[i] = [];whiteScore[i] = [];for (var j = 0; j < 15; j++) {blackScore[i][j] = 0;whiteScore[i][j] = 0;};};//每個坐標的分數為零//遍歷每個空坐標,如果某種贏法已經落子的數量越大則該坐標加分越多//同理攔截對方的落子//加分的數值很重要for (var i = 0; i < 15; i++) {for (var j = 0; j < 15; j++) {if (chessBoard[i][j] == 0) {for (var k = 0; k < count; k++) {if (wins[i][j][k]) {switch (black[k]) {case 1:blackScore[i][j] += 2;break;case 2:blackScore[i][j] += 5;break;case 3:blackScore[i][j] += 20;break;case 4:blackScore[i][j] += 50;break;}switch (white[k]) {case 1:whiteScore[i][j] += 2;break;case 2:whiteScore[i][j] += 5;break;case 3:whiteScore[i][j] += 20;break;case 4:whiteScore[i][j] += 50;break;}//找出得分最高的坐標點if (blackScore[i][j] > max) {max = blackScore[i][j];u = i;v = j;} else if (blackScore[i][j] == max) {if (whiteScore[i][j] > whiteScore[u][v]) {u = i;v = j;}}if (whiteScore[i][j] > max) {max = whiteScore[i][j];u = i;v = j;} else if (whiteScore[i][j] == max) {if (blackScore[i][j] > blackScore[u][v]) {u = i;v = j;}}};};};};};oneStep(u, v, color);color ? chessBoard[u][v] = 1 : chessBoard[u][v] = 2;winner(u, v, color);me = !color;}

五子棋的棋盤上,每一個位置都存在多種贏法,此算法的邏輯就是假如一個空坐標還未落子,那么遍歷所有的贏法,如果黑方在此種贏法已經落下一子,那么這個坐標對黑方有利,加分;如果黑方落下二子,那么分數更高;白方也是同理……找出最有價值的坐標落子。

至于如何加分,可以借鑒網上的評分表:


代碼只是實現了思路,沒有優化;而且此類“”民間規則“”五子棋都是先手必勝,

在五子棋專業規則中規定,一共有26種開局。直指開局13種,斜指開局13種。
這26種開局分別是:
寒星 溪月 殘月 雨月 金星 丘月 新月?
山月 游星 長星 峽月 恒星 水月 流星
浦月 嵐月 銀月 明星 名月 彗星 花月?
松月 疏星 斜月 瑞星 云月?

其中公認黑必勝的開局有:花月,浦月
黑必敗開局有:彗星,游星
以上之適用于五子棋專業規則
在民間規則里,幾乎全部是黑先手必勝。

專業的五子棋比賽還有禁手、三手交換、五手兩打等限制,以后有機會再研究吧……


總結

以上是生活随笔為你收集整理的canvas简易人机五子棋的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。