diff --git a/html/chessboard.html b/html/chessboard.html index 75bf413..2826f0a 100644 --- a/html/chessboard.html +++ b/html/chessboard.html @@ -18,5 +18,6 @@ + diff --git a/js/AI.js b/js/AI.js index 53d650a..01b93ac 100644 --- a/js/AI.js +++ b/js/AI.js @@ -1,53 +1,73 @@ -//alert("this is ai"); -const Constants = { +// for judgement convenience +// let wrappedBoard = []; +let StepGenerator = (function(){ + +let StepGenerator = {}; + +let Constants = { ChessBoard:{ ROW_NUM:15, - COL_NUM:15 + COL_NUM:15, }, Chesspiece:{ BLACK: 1, WHITE: 0, - EMPTY: 'e' + EMPTY: 'e', + BORDER: 'b' } }; -// for judgement convenience -let wrappedBoard = []; - -function wrapBoard(board){ - let padding = new Array(Constants.ChessBoard.COL_NUM + 4).fill( - Constants.Chesspiece.EMPTY); - for(let row of board){ - row.unshift(Constants.Chesspiece.EMPTY, Constants.Chesspiece.EMPTY); - row.push(Constants.Chesspiece.EMPTY, Constants.Chesspiece.EMPTY); +let UtilMethods = { + // wrappedBoard + isPositionEmpty(board, rowPos, colPos){ + return (board[rowPos][colPos] === Constants.Chesspiece.EMPTY); + }, + // like this 'b' 'b' + hasOneStepNeighbour(board, color, rowPos, colPos){ + return (board[rowPos-1][colPos-1] == color) || + (board[rowPos-1][colPos] == color) || + (board[rowPos-1][colPos+1] == color) || + (board[rowPos][colPos-1] == color) || + (board[rowPos][colPos+1] == color) || + (board[rowPos+1][colPos-1] == color) || + (board[rowPos+1][colPos] == color) || + (board[rowPos+1][colPos+1] == color); + }, + // like this 'b' 'e' 'b' + hasTwoStepNeighbour(board, color, rowPos, colPos){ + return (board[rowPos-2][colPos-2] == color) || + (board[rowPos-2][colPos] == color) || + (board[rowPos-2][colPos+2] == color) || + (board[rowPos][colPos-2] == color) || + (board[rowPos][colPos+2] == color) || + (board[rowPos+2][colPos-2] == color) || + (board[rowPos+2][colPos] == color) || + (board[rowPos+2][colPos+2] == color); } - return [padding, padding, ...board, padding, padding]; -} - -// like this 'b' 'b' -function hasOneStepNeighbour(board, color, rowPos, colPos){ - return (board[rowPos-1][colPos-1] == color) || - (board[rowPos-1][colPos] == color) || - (board[rowPos-1][colPos+1] == color) || - (board[rowPos][colPos-1] == color) || - (board[rowPos][colPos+1] == color) || - (board[rowPos+1][colPos-1] == color) || - (board[rowPos+1][colPos] == color) || - (board[rowPos+1][colPos+1] == color); } -// like this 'b' 'e' 'b' -function hasTwoStepNeighbour(board, color, rowPos, colPos){ - return (board[rowPos-2][colPos-2] == color) || - (board[rowPos-2][colPos] == color) || - (board[rowPos-2][colPos+2] == color) || - (board[rowPos][colPos-2] == color) || - (board[rowPos][colPos+2] == color) || - (board[rowPos+2][colPos-2] == color) || - (board[rowPos+2][colPos] == color) || - (board[rowPos+2][colPos+2] == color); -} +StepGenerator.Constants = Constants; +StepGenerator.UtilMethods = UtilMethods; +StepGenerator.copyAndWrapBoard = (function(){ + let padding = new Array(Constants.ChessBoard.COL_NUM + 4).fill( + Constants.Chesspiece.BORDER); + + return function(board) { + let res = [padding, padding]; + for(let row of board){ + res.push([ + Constants.Chesspiece.BORDER, + Constants.Chesspiece.BORDER, + ...row, + Constants.Chesspiece.BORDER, + Constants.Chesspiece.BORDER + ]); + } + res.push(padding, padding); + return res; + }; +})(); // return type // [ @@ -55,20 +75,28 @@ function hasTwoStepNeighbour(board, color, rowPos, colPos){ // ] // range: [0,15) -function generateAllNextPossibleMove(wrappedBoard, color){ +StepGenerator.generateAllNextPossibleMove = function(wrappedBoard, color){ let oneStepNeighbours = [], twoStepNeighbours = []; let rowEnd = Constants.ChessBoard.ROW_NUM + 2, colEnd = Constants.ChessBoard.COL_NUM + 2; - for(let i = 2; i < rowEnd;i++){ - for(let j = 2;j < colEnd;j++){ - if(hasOneStepNeighbour(wrappedBoard, color, i, j)){ - oneStepNeighbours.push([i-2, j-2]); - }else if(hasTwoStepNeighbour(wrappedBoard, color, i, j)){ - twoStepNeighbours.push([i-2, j-2]); + + //console.log(wrappedBoard); + for(let i = 2; i < rowEnd; i++){ + for(let j = 2; j < colEnd; j++){ + if(UtilMethods.isPositionEmpty(wrappedBoard, i, j)){ + if(UtilMethods.hasOneStepNeighbour(wrappedBoard, color, i, j)){ + oneStepNeighbours.push([i-2, j-2]); + }else if(UtilMethods.hasTwoStepNeighbour(wrappedBoard, color, i, j)){ + twoStepNeighbours.push([i-2, j-2]); + } } } } return [...oneStepNeighbours, ...twoStepNeighbours]; -} \ No newline at end of file +} + +return StepGenerator; + +})(); \ No newline at end of file diff --git a/js/AIController.js b/js/AIController.js index e9a6550..9f862d6 100644 --- a/js/AIController.js +++ b/js/AIController.js @@ -6,20 +6,29 @@ generateAllNextPossibleMove(wrapBoard(matrix), color) //落子位置函数 */ -const MIN = -4294967295; -const MAX = 4294967295; +const MIN = Number.NEGATIVE_INFINITY; +const MAX = Number.POSITIVE_INFINITY; +var alpha = Number.NEGATIVE_INFINITY, + beta = Number.POSITIVE_INFINITY; + +var pointCounter = 0; //board 当前棋盘, deep 思考步数 var FunctionMaxMin = function(board, color, deep) { var best = MIN; - var points = generateAllNextPossibleMove(wrapBoard(board), color); + //console.log(board); + var boardTemp = StepGenerator.copyAndWrapBoard(board); + var points = StepGenerator.generateAllNextPossibleMove(boardTemp, color); var bestPoints = []; - console.log(points); + //console.log(points); for(var i = 0; i < points.length; i++){ var now_point = points[i]; - board[now_point[0]][now_point[1]] = color; //电脑下子的颜色 - var value = min(board, Math.abs(color-1), deep-1); + boardTemp[now_point[0]+2][now_point[1]+2] = color; //下子的颜色 + + var value = min(boardTemp, Math.abs(color-1), alpha, beta, deep-1); + + pointCounter++; if(value == best){ bestPoints.push(now_point); @@ -32,51 +41,67 @@ var FunctionMaxMin = function(board, color, deep) { else{ console.log('ignore'); } - board[now_point[0]][now_point[1]] = 'e'; + boardTemp[now_point[0]+2][now_point[1]+2] = 'e'; } - console.log(bestPoints.length); + console.log("搜索节点数:"+pointCounter); var result = bestPoints[Math.floor(Math.random() * bestPoints.length)]; - return result; + if(result == undefined) + return []; + return [result[0]+1, result[1]+1]; //此处是为了方便手动下棋,电脑下棋应当把 +1 部分都去掉,直接return result } //max函数 -var max = function(board, color, deep){ - var v = evaluate(board); - if(deep <= 0) +var max = function(board, color, alpha, beta, deep){ + var v = ModuleEvaluate.evaluate(board); + if(deep <= 0 || ModuleWinnerCheck.checkWinnerInAiController(board, color)) return v; var best = MIN; - var points = generateAllNextPossibleMove(wrapBoard(board), color); + var points = StepGenerator.generateAllNextPossibleMove(board, color); for( var i = 0; i < points.length; i++){ + + pointCounter++; + var p = points[i]; - board[p[0]][p[1]] = color; - var v = min(board, Math.abs(color-1), deep-1); - board[p[0]][p[1]] = 'e'; + board[p[0]+2][p[1]+2] = color; + var v = min(board, Math.abs(color-1), alpha, best > beta? best : beta, deep-1); + board[p[0]+2][p[1]+2] = 'e'; if(v > best) best = v; + if(v > alpha) + break; + //alpha:上一层(min层)的当前最小值,v:当前层(mx层)的下一层的最小值 + /*我方在当前位置的下子,应当使对方紧接着的下子所产生的优势不超过对方上一步下子所产生的优势*/ } return best; -} +}; //min函数 -var min = function(board, color, deep){ - var v = evaluate(board); - if(deep <= 0) +var min = function(board, color, alpha, beta, deep){ + var v = ModuleEvaluate.evaluate(board); + if(deep <= 0 || ModuleWinnerCheck.checkWinnerInAiController(board, color)) return v; var best = MAX; - var points = generateAllNextPossibleMove(wrapBoard(board), color); + var points = StepGenerator.generateAllNextPossibleMove(board, color); for( var i = 0; i < points.length; i++){ + + pointCounter++; + var p = points[i]; - board[p[0]][p[1]] = color; - var v = max(board, Math.abs(color-1), deep-1); - board[p[0]][p[1]] = 'e'; + board[p[0]+2][p[1]+2] = color; + var v = max(board, Math.abs(color-1), best < alpha? best : alpha, beta, deep-1); + board[p[0]+2][p[1]+2] = 'e'; if(v < best) best = v; + if(v < beta) + break; + //beta:上一层(max层)的当前最大值,v:当前层(min层)的下一层的最大值 + /*对方在当前位置的下子,应当使我方紧接着的下子所产生的优势超过我方上一步下子所产生的优势*/ } return best; -} \ No newline at end of file +}; \ No newline at end of file diff --git a/js/basic.js b/js/basic.js index 1b33b05..2deacf6 100644 --- a/js/basic.js +++ b/js/basic.js @@ -3,6 +3,48 @@ var list = document.getElementsByClassName('chess'); var map; var is_win = false; +var playMode = { + "PvP": { + "player1": true, + "player2": false + }, + + "PvE": { + "computer": false, + "human": true + } +}; + +var playModeController = function(Mode, color) { + var playingMode; + color = color == "black" ? 1 : 0; + if(Mode === "PvP"){ + playingMode = playMode.PvP; + playingMode.player1 = !playingMode.player1; + playingMode.player2 = !playingMode.player2; + } + if(Mode === "PvE"){ + playingMode = playMode.PvE; + if(playingMode.human && !playingMode.computer){ + playingMode.human = !playingMode.human; + playingMode.computer = !playingMode.computer; + return; + } + if(playingMode.computer && !playingMode.human){ + var point = FunctionMaxMin(map, Math.abs(color-1), 4); + console.log(point); + playingMode.human = !playingMode.human; + playingMode.computer = !playingMode.computer; + robotClick(point); + } + } +}; + +var robotClick = function(point) { + var p = (point[0]-1)*15 + (point[1]-1); + var id = "#" + p; + $(id).click(); +}; //生成元素 var createMap = function() { @@ -48,6 +90,7 @@ window.onload = function() { list[i].onclick = operate; } is_win = false; + $("#112").click(); //默认初始下子位置,黑棋 } var operate = function() { @@ -58,84 +101,20 @@ var operate = function() { $(this).attr("check", true); if(black_or_white == "black"){ - createRecord("black", checkWinner(1, num)); + createRecord("black", ModuleWinnerCheck.checkWinner(1, num)); $(this).addClass("blackChess"); black_or_white = "white"; $("#record").scrollTop(document.getElementById('record').scrollHeight); - //alert(map); + setTimeout('playModeController("PvE", "black")', 500); //当前颜色 return; } else{ - createRecord("white", checkWinner(0, num)); + createRecord("white", ModuleWinnerCheck.checkWinner(0, num)); $(this).addClass("whiteChess"); black_or_white = "black"; $("#record").scrollTop(document.getElementById('record').scrollHeight); - //alert(map); + setTimeout('playModeController("PvE", "white")', 500); return; - } -} - - -//判断胜负部分 -var checkWinner = function(color, num) { - var col = num%15; - var row = (num-col)/15; - map[row][col] = color; - - /*测试语句,输出为黑棋与白旗的权值差(black - white)*/ - console.log(color); - console.log(Math.abs(color-1)); - console.log(evaluate(map)); - console.log(FunctionMaxMin(map, Math.abs(color-1), 4)); - /***********************/ - - var count = 1; - is_win = checkControl(row, col, color); - if(is_win) - return -1; - else - return num; -} - -var checkControl = function(row, col, color) { - if(checkWinnerScan(row, col, color, 0) + checkWinnerScan(row, col, color, 4) - 1 < 5) - if(checkWinnerScan(row, col, color, 1) + checkWinnerScan(row, col, color, 5) - 1 < 5) - if(checkWinnerScan(row, col, color, 2) + checkWinnerScan(row, col, color, 6) - 1 < 5) - if(checkWinnerScan(row, col, color, 3) + checkWinnerScan(row, col, color, 7) - 1 < 5) - return false; - return true; -} - -var checkWinnerScan = function(row, col, color, state) { - if(row < 0 || row > 14 || col < 0 || col > 14 || map[row][col] != color){ - return 0; - } - else if(!is_win && state == 0){ - return 1 + checkWinnerScan(row-1, col, color, 0); - } - else if(!is_win && state == 1){ - return 1 + checkWinnerScan(row-1, col+1, color, 1); - } - else if(!is_win && state == 2){ - return 1 + checkWinnerScan(row, col+1, color, 2); - } - else if(!is_win && state == 3){ - return 1 + checkWinnerScan(row+1, col+1, color, 3); - } - else if(!is_win && state == 4){ - return 1 + checkWinnerScan(row+1, col, color, 4); - } - else if(!is_win && state == 5){ - return 1 + checkWinnerScan(row+1, col-1, color, 5); } - else if(!is_win && state == 6){ - return 1 + checkWinnerScan(row, col-1, color, 6); - } - else if(!is_win && state == 7){ - return 1 + checkWinnerScan(row-1, col-1, color, 7); - } - else{ - return 0; - } -} - + +} \ No newline at end of file diff --git a/js/evaluate.js b/js/evaluate.js index 4908595..3650aa4 100644 --- a/js/evaluate.js +++ b/js/evaluate.js @@ -1,12 +1,4 @@ -var total_count = { - white: 0, - black: 0 -}; - -var error_state = { - empty: 'empty', - error: 'error' -}; +'use strict'; const judge_standard = { //连五 @@ -29,202 +21,198 @@ const judge_standard = { BLOCK_ONE: 1 }; -var pointDirection = function( row, col, matrix) { +var ModuleEvaluate = { + + _pointDirection: function( row, col, matrix) { - //公用部分 - var result = new Array(4); - var count; - var a = row; - var b = col; - - //按四个方向划分四个一维数组 - //横线 - var horizon = []; - for(var i = 0; i < 15; i++) - horizon[i] = matrix[row][i]; - //竖直线 - var vertical = []; - for(var i = 0; i < 15; i++) - vertical[i] = matrix[i][col]; - //右上斜线 - var rightTop = []; - while(a < 14 && b > 0){ a++; b--; }; - /*console.log(a); - console.log(b);*/ - for(var i = 0; a >= 0 && b < 15; i++) - rightTop[i] = matrix[a--][b++]; - //右下斜线 - a = row; - b = col; - var rightDown = []; - while(a > 0 && b > 0){ a--; b--; }; - /*console.log(a); - console.log(b);*/ - for(var i = 0; a < 15 && b < 15; i++) - rightDown[i] = matrix[a++][b++]; - - //统计部分 - //横线 - var horizonCheck = 'b'+horizon.join('')+'b'; - //console.log(horizon); - //console.log(horizonCheck); - - //竖直线 - var verticalCheck = 'b'+vertical.join('')+'b'; - //console.log(vertical); - //console.log(verticalCheck); - - //右上斜线 - var rightTopCheck = 'b'+rightTop.join('')+'b'; - //console.log(rightTop); - //console.log(rightTopCheck); - - //右下斜线 - var rightDownCheck = 'b'+rightDown.join('')+'b'; - //console.log(rightDown); - //console.log(rightDownCheck); + //公用部分 + var result = new Array(4); + var count; + var a = row; + var b = col; + + //按四个方向划分四个一维数组 + //横线 + var horizon = []; + for(var i = 0; i < 15; i++) + horizon[i] = matrix[row][i]; + + //竖直线 + var vertical = []; + for(var i = 0; i < 15; i++) + vertical[i] = matrix[i][col]; + + //右上斜线 + var rightTop = []; + while(a < 14 && b > 0){ a++; b--; }; + for(var i = 0; a >= 0 && b < 15; i++) + rightTop[i] = matrix[a--][b++]; + + //右下斜线 + a = row; + b = col; + var rightDown = []; + while(a > 0 && b > 0){ a--; b--; }; + for(var i = 0; a < 15 && b < 15; i++) + rightDown[i] = matrix[a++][b++]; + + //统计部分 + //横线 + var horizonCheck = 'b'+horizon.join('')+'b'; + + //竖直线 + var verticalCheck = 'b'+vertical.join('')+'b'; + + //右上斜线 + var rightTopCheck = 'b'+rightTop.join('')+'b'; + + //右下斜线 + var rightDownCheck = 'b'+rightDown.join('')+'b'; + + return [horizonCheck, verticalCheck, rightTopCheck, rightDownCheck]; + }, + + /* + 连五:color+color+color+color+color + + 活四:(-1)+color+color+color+color+(-1) + + 眠四:(!color)+color+color+color+color+(-1) || + color+color+color+(-1)+color || + color+color+(-1)+color+color + + 活三:(-1)+color+color+color+(-1) || + color+color+(-1)+color + + 眠三:(!color)+color+color+color+(-1)+(-1) || + (!color)+color+color+(-1)+color+(-1) || + (!color)+color+(-1)+color+color+(-1) + + 活二:(-1)+(-1)+color+color+(-1)+(-1) || + (-1)+color+(-1)+color+(-1) || + color+(-1)+(-1)+color + + 眠二:(!color)+color+color+(-1)+(-1)+(-1) || + (!color)+color+(-1)+color+(-1)+(-1) || + (!color)+color+(-1)+(-1)+color+(-1) + + 活一:(-1)+color+(-1) + + 眠一:(!color)+color+(-1) + + */ + + + //b代表边界,e代表空位,color代表当前颜色,ncolor代表相反的颜色 + _regExpConstructor: function ( chessColor ){ + var regex = new Array(28); + var color = parseInt(chessColor); + var ncolor = color == 1? 0 : 1; + + //连五 + regex[0] = new RegExp(color+''+color+''+color+''+color+''+color, 'g'); + //活四 + regex[1] = new RegExp('e'+color+''+color+''+color+''+color+'e', 'g'); + //眠四 + regex[2] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+''+color+''+color+'e', 'g'); + regex[3] = new RegExp('e'+color+''+color+''+color+''+color+''+('('+ncolor+'|b)'), 'g'); + regex[4] = new RegExp(color+''+color+'e'+color+''+color, 'g'); + regex[5] = new RegExp(color+'e'+color+''+color+''+color, 'g'); + regex[6] = new RegExp(color+''+color+''+color+'e'+color, 'g'); + //活三 + regex[7] = new RegExp('e'+color+''+color+''+color+'e', 'g'); + regex[8] = new RegExp('e'+color+'e'+color+''+color+'e', 'g'); + regex[9] = new RegExp('e'+color+''+color+'e'+color+'e', 'g'); + //眠三 + regex[10] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+''+color+'e'+'e', 'g'); + regex[11] = new RegExp('e'+'e'+color+''+color+''+color+''+('('+ncolor+'|b)'), 'g'); + regex[12] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+'e'+color+'e', 'g'); + regex[13] = new RegExp('e'+color+'e'+color+''+color+''+('('+ncolor+'|b)'), 'g'); + regex[14] = new RegExp(('('+ncolor+'|b)')+''+color+'e'+color+''+color+'e', 'g'); + regex[15] = new RegExp('e'+color+''+color+'e'+color+''+('('+ncolor+'|b)'), 'g'); + //活二 + regex[16] = new RegExp('e'+'e'+color+color+'e'+'e', 'g'); + regex[17] = new RegExp('e'+color+'e'+color+'e', 'g'); + regex[18] = new RegExp('e'+color+'e'+'e'+color+'e', 'g'); + //眠二 + regex[19] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+'e'+'e'+'e', 'g'); + regex[20] = new RegExp('e'+'e'+'e'+color+''+color+''+('('+ncolor+'|b)'), 'g'); + regex[21] = new RegExp(('('+ncolor+'|b)')+''+color+'e'+color+'e'+'e', 'g'); + regex[22] = new RegExp('e'+'e'+color+'e'+color+''+('('+ncolor+'|b)'), 'g'); + regex[23] = new RegExp(('('+ncolor+'|b)')+''+color+'e'+'e'+color+'e', 'g'); + regex[24] = new RegExp('e'+color+'e'+'e'+color+''+('('+ncolor+'|b)'), 'g'); + //活一 + regex[25] = new RegExp('e'+color+'e', 'g'); + //眠一 + regex[26] = new RegExp(('('+ncolor+'|b)')+''+color+'e', 'g'); + regex[27] = new RegExp('e'+color+('('+ncolor+'|b)'), 'g') + + //console.log(regex); + + return regex; + }, + + _pointCounter: function( strList, regExpList ){ + var count = 0; + var size = 0; + for( var i = 0; i < 4; i++){ + for(var j = 0; j < 28; j++){ + size = strList[i].match(regExpList[j]) == null? 0: strList[i].match(regExpList[j]).length; + if(j == 0){ + count += (size) * judge_standard.FIVE; + } + else if(j == 1){ + count += (size) * judge_standard.FOUR; + } + else if(j >= 2 && j <= 6){ + count += (size) * judge_standard.BLOCK_FOUR; + } + else if(j >= 7 && j <= 9){ + count += (size) * judge_standard.THREE; + } + else if(j >= 10 && j <= 15){ + count += (size) * judge_standard.BLOCK_THREE; + } + else if(j >= 16 && j <= 18){ + count += (size) * judge_standard.TWO; + } + else if(j >= 19 && j <= 24){ + count += (size) * judge_standard.BLOCK_TWO; + } + else if(j == 25){ + count += (size) * judge_standard.ONE; + } + else{ + count += (size) * judge_standard.BLOCK_ONE; + } + strList[i].replace(regExpList[j], "-"); + } + } + return count; + }, + + evaluate: function( matrix ){ + var black_value = 0; + var white_value = 0; + for(var i = 0; i < 15; i++){ + for(var j = 0; j < 15; j++){ + if(matrix[i][j] == 1){ + black_value += this._pointCounter(this._pointDirection(i, j, matrix), BLACK_REG); + } + else if(matrix[i][j] == 0){ + white_value += this._pointCounter(this._pointDirection(i, j, matrix), WHITE_REG); + } + else{ + continue; + } + } + } + + return (black_value - white_value); + } + +}; + +const BLACK_REG = ModuleEvaluate._regExpConstructor(1); - return [horizonCheck, verticalCheck, rightTopCheck, rightDownCheck]; -} - -/* -连五:color+color+color+color+color - -活四:(-1)+color+color+color+color+(-1) - -眠四:(!color)+color+color+color+color+(-1) || - color+color+color+(-1)+color || - color+color+(-1)+color+color - -活三:(-1)+color+color+color+(-1) || - color+color+(-1)+color - -眠三:(!color)+color+color+color+(-1)+(-1) || - (!color)+color+color+(-1)+color+(-1) || - (!color)+color+(-1)+color+color+(-1) - -活二:(-1)+(-1)+color+color+(-1)+(-1) || - (-1)+color+(-1)+color+(-1) || - color+(-1)+(-1)+color - -眠二:(!color)+color+color+(-1)+(-1)+(-1) || - (!color)+color+(-1)+color+(-1)+(-1) || - (!color)+color+(-1)+(-1)+color+(-1) - -活一:(-1)+color+(-1) - -眠一:(!color)+color+(-1) - -*/ - - -//b代表边界,e代表空位,color代表当前颜色,ncolor代表相反的颜色 -var regExpConstructor = function ( chessColor ){ - var regex = new Array(28); - var color = parseInt(chessColor); - var ncolor = color == 1? 0 : 1; - - //连五 - regex[0] = new RegExp(color+''+color+''+color+''+color+''+color, 'g'); - //活四 - regex[1] = new RegExp('e'+color+''+color+''+color+''+color+'e', 'g'); - //眠四 - regex[2] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+''+color+''+color+'e', 'g'); - regex[3] = new RegExp('e'+color+''+color+''+color+''+color+''+('('+ncolor+'|b)'), 'g'); - regex[4] = new RegExp(color+''+color+'e'+color+''+color, 'g'); - regex[5] = new RegExp(color+'e'+color+''+color+''+color, 'g'); - regex[6] = new RegExp(color+''+color+''+color+'e'+color, 'g'); - //活三 - regex[7] = new RegExp('e'+color+''+color+''+color+'e', 'g'); - regex[8] = new RegExp('e'+color+'e'+color+''+color+'e', 'g'); - regex[9] = new RegExp('e'+color+''+color+'e'+color+'e', 'g'); - //眠三 - regex[10] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+''+color+'e'+'e', 'g'); - regex[11] = new RegExp('e'+'e'+color+''+color+''+color+''+('('+ncolor+'|b)'), 'g'); - regex[12] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+'e'+color+'e', 'g'); - regex[13] = new RegExp('e'+color+'e'+color+''+color+''+('('+ncolor+'|b)'), 'g'); - regex[14] = new RegExp(('('+ncolor+'|b)')+''+color+'e'+color+''+color+'e', 'g'); - regex[15] = new RegExp('e'+color+''+color+'e'+color+''+('('+ncolor+'|b)'), 'g'); - //活二 - regex[16] = new RegExp('e'+'e'+color+color+'e'+'e', 'g'); - regex[17] = new RegExp('e'+color+'e'+color+'e', 'g'); - regex[18] = new RegExp('e'+color+'e'+'e'+color+'e', 'g'); - //眠二 - regex[19] = new RegExp(('('+ncolor+'|b)')+''+color+''+color+'e'+'e'+'e', 'g'); - regex[20] = new RegExp('e'+'e'+'e'+color+''+color+''+('('+ncolor+'|b)'), 'g'); - regex[21] = new RegExp(('('+ncolor+'|b)')+''+color+'e'+color+'e'+'e', 'g'); - regex[22] = new RegExp('e'+'e'+color+'e'+color+''+('('+ncolor+'|b)'), 'g'); - regex[23] = new RegExp(('('+ncolor+'|b)')+''+color+'e'+'e'+color+'e', 'g'); - regex[24] = new RegExp('e'+color+'e'+'e'+color+''+('('+ncolor+'|b)'), 'g'); - //活一 - regex[25] = new RegExp('e'+color+'e', 'g'); - //眠一 - regex[26] = new RegExp(('('+ncolor+'|b)')+''+color+'e', 'g'); - regex[27] = new RegExp('e'+color+('('+ncolor+'|b)'), 'g') - - //console.log(regex); - - return regex; -} - -var pointCounter = function( strList, regExpList ){ - var count = 0; - var size = 0; - for( var i = 0; i < 4; i++){ - for(var j = 0; j < 28; j++){ - size = strList[i].match(regExpList[j]) == null? 0: strList[i].match(regExpList[j]).length; - if(j == 0){ - count += (size) * judge_standard.FIVE; - } - else if(j == 1){ - count += (size) * judge_standard.FOUR; - } - else if(j >= 2 && j <= 6){ - count += (size) * judge_standard.BLOCK_FOUR; - } - else if(j >= 7 && j <= 9){ - count += (size) * judge_standard.THREE; - } - else if(j >= 10 && j <= 15){ - count += (size) * judge_standard.BLOCK_THREE; - } - else if(j >= 16 && j <= 18){ - count += (size) * judge_standard.TWO; - } - else if(j >= 19 && j <= 24){ - count += (size) * judge_standard.BLOCK_TWO; - } - else if(j == 25){ - count += (size) * judge_standard.ONE; - } - else{ - count += (size) * judge_standard.BLOCK_ONE; - } - strList[i].replace(regExpList[j], "-"); - } - } - return count; -} - -var black_reg = regExpConstructor(1); -var white_reg = regExpConstructor(0); - -function evaluate( matrix ){ - var black_value = 0; - var white_value = 0; - for(var i = 0; i < 15; i++){ - for(var j = 0; j < 15; j++){ - if(matrix[i][j] == 1){ - black_value += pointCounter(pointDirection(i, j, matrix), black_reg); - } - else if(matrix[i][j] == 0){ - white_value += pointCounter(pointDirection(i, j, matrix), white_reg); - } - else{ - continue; - } - } - } - - return (black_value - white_value); -} \ No newline at end of file +const WHITE_REG = ModuleEvaluate._regExpConstructor(0); \ No newline at end of file diff --git a/js/winnercheck.js b/js/winnercheck.js new file mode 100644 index 0000000..d1c05b5 --- /dev/null +++ b/js/winnercheck.js @@ -0,0 +1,77 @@ +//判断胜负部分 + +var ModuleWinnerCheck = { + + checkWinner: function(color, num) { + var col = num % 15; + var row = (num-col) / 15; + map[row][col] = color; + + /*测试语句,输出为黑棋与白旗的权值差(black - white)*/ + //console.log(color); + //console.log(Math.abs(color-1)); + console.log(ModuleEvaluate.evaluate(map)); + /***********************/ + + var count = 1; + is_win = this._checkControl(row, col, color); + if(is_win) + return -1; + else + return num; + }, + + checkWinnerInAiController: function(matrix, color) { + for(var i = 0; i < 15; i++){ + for(var j = 0; j < 15; j++){ + if(matrix[i][j] != color) + continue; + if(this._checkControl(i, j, color)) + return true; + } + } + return false; + }, + + _checkControl: function(row, col, color) { + if(this._checkWinnerScan(row, col, color, 0) + this._checkWinnerScan(row, col, color, 4) - 1 < 5) + if(this._checkWinnerScan(row, col, color, 1) + this._checkWinnerScan(row, col, color, 5) - 1 < 5) + if(this._checkWinnerScan(row, col, color, 2) + this._checkWinnerScan(row, col, color, 6) - 1 < 5) + if(this._checkWinnerScan(row, col, color, 3) + this._checkWinnerScan(row, col, color, 7) - 1 < 5) + return false; + return true; + }, + + _checkWinnerScan: function(row, col, color, state) { + if(row < 0 || row > 14 || col < 0 || col > 14 || map[row][col] != color){ + return 0; + } + else if(!is_win && state == 0){ + return 1 + this._checkWinnerScan(row-1, col, color, 0); + } + else if(!is_win && state == 1){ + return 1 + this._checkWinnerScan(row-1, col+1, color, 1); + } + else if(!is_win && state == 2){ + return 1 + this._checkWinnerScan(row, col+1, color, 2); + } + else if(!is_win && state == 3){ + return 1 + this._checkWinnerScan(row+1, col+1, color, 3); + } + else if(!is_win && state == 4){ + return 1 + this._checkWinnerScan(row+1, col, color, 4); + } + else if(!is_win && state == 5){ + return 1 + this._checkWinnerScan(row+1, col-1, color, 5); + } + else if(!is_win && state == 6){ + return 1 + this._checkWinnerScan(row, col-1, color, 6); + } + else if(!is_win && state == 7){ + return 1 + this._checkWinnerScan(row-1, col-1, color, 7); + } + else{ + return 0; + } + } +}; \ No newline at end of file