Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function p10602_08()
- {
- /*--------------------------------Step2. 調控變數--------------------------------*/
- var step = 3; //表示要預測到幾步(>0)後,若為負數(<0)則為預測到底(即有勝負)為止,若為0則為隨便亂下
- var UsePrunning = true; //表示是否要剪枝,若為false,則只是單純的MINMAX演算法
- //計算盤面分數
- //chessData:目前的棋盤狀況(15x15) / MyColor:AI的顏色(黑1,白-1) / lastColor:「上一步」下的人的顏色 / (lastStepX, lastStepY):「上一步」下的位置
- this.Score = function(chessData, MyColor, lastColor, lastStepX, lastStepY)
- {
- /*--------------------------------Step3. 修改 Score function中的變數--------------------------------*/
- var MyScore = 0, EnemyScore = 0;
- /*============ 加速1. 只從有棋子(即1或-1)的地方嘗試延伸Pattern,也就是空格(0)不能為Pattern起點 e.g., [0,1,1,1,1,0] 應拆開為 [[0],[1,1,1,1,0]] ============*/
- var MyPattern = [[1,1,1,1,1], [[0],[1,1,1,1,0]], [[0],[1,1,1,0]], [[0],[1,1,0]] ];
- var EnemyPattern = [[1,1,1,1,1], [[0],[1,1,1,1,0]], [[0],[1,1,1,0]]];
- var MyAdd = [10000, 800, 100, 10];
- var EnemyAdd = [10000, 1000, 100, 10];
- var multiplier = 1;
- var multiflag = 0;
- var MyPositionAdd = [
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
- [ 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0 ],
- [ 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0 ],
- [ 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0 ],
- [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ];
- var EnemyPositionAdd = [
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ],
- [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
- [ 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0 ],
- [ 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 6, 7, 6, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 6, 6, 6, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 5, 5, 5, 5, 5, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 4, 4, 4, 4, 4, 4, 4, 3, 2, 1, 0 ],
- [ 0, 1, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 1, 0 ],
- [ 0, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 0 ],
- [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 ],
- [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ] ];
- /*--------------------------------修改結束--------------------------------*/
- for(var x = 0; x < 15; ++x)
- {
- for(var y = 0; y < 15; ++y)
- {
- if(chessData[x][y] == 0)
- continue;
- if(chessData[x][y] == MyColor)
- MyScore += MyPositionAdd[x][y];
- for(var i = 0; i < MyPattern.length; ++i)
- {
- if(!Array.isArray(MyPattern[i][0])) multiplier
- {
- if(this.Match(x, y, 0, -1, MyPattern[i], MyColor)) //往上找
- {
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- if(this.Match(x, y, 0, 1, MyPattern[i], MyColor)) //往下找
- {
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- if(this.Match(x, y, -1, 0, MyPattern[i], MyColor)) //往左找
- {
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- if(this.Match(x, y, 1, 0, MyPattern[i], MyColor)){ //往右找
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- if(this.Match(x, y, -1, -1, MyPattern[i], MyColor)){ //往左上找
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- if(this.Match(x, y, -1, 1, MyPattern[i], MyColor)){ //往左下找
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- if(this.Match(x, y, 1, -1, MyPattern[i], MyColor)){ //往右上找
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- if(this.Match(x, y, 1, 1, MyPattern[i], MyColor)){ //往右下找
- if(i == 3) multiflag = true;
- MyScore += MyAdd[i];
- }
- }
- else //---------------------------------------------------------------
- {
- if(this.Match(x, y+1, 0, 1, MyPattern[i][0], MyColor) && this.Match(x, y, 0, -1, MyPattern[i][1], MyColor)) //往上找
- MyScore += MyAdd[i];
- if(this.Match(x, y-1, 0, -1, MyPattern[i][0], MyColor) && this.Match(x, y, 0, 1, MyPattern[i][1], MyColor)) //往下找
- MyScore += MyAdd[i];
- if(this.Match(x+1, y, 1, 0, MyPattern[i][0], MyColor) && this.Match(x, y, -1, 0, MyPattern[i][1], MyColor)) //往左找
- MyScore += MyAdd[i];
- if(this.Match(x-1, y, -1, 0, MyPattern[i][0], MyColor) && this.Match(x, y, 1, 0, MyPattern[i][1], MyColor)) //往右找
- MyScore += MyAdd[i];
- if(this.Match(x+1, y+1, 1, 1, MyPattern[i][0], MyColor) && this.Match(x, y, -1, -1, MyPattern[i][1], MyColor)) //往左上找
- MyScore += MyAdd[i];
- if(this.Match(x+1, y-1, 1, -1, MyPattern[i][0], MyColor) && this.Match(x, y, -1, 1, MyPattern[i][1], MyColor)) //往左下找
- MyScore += MyAdd[i];
- if(this.Match(x-1, y+1, -1, 1, MyPattern[i][0], MyColor) && this.Match(x, y, 1, -1, MyPattern[i][1], MyColor)) //往右上找
- MyScore += MyAdd[i];
- if(this.Match(x-1, y-1, -1, -1, MyPattern[i][0], MyColor) && this.Match(x, y, 1, 1, MyPattern[i][1], MyColor)) //往右下找
- MyScore += MyAdd[i];
- }
- }
- if(multiflag){
- multiplier *= 4;
- multiflag = false;
- }
- }
- }
- for(var x = 0; x < 15; ++x)
- {
- for(var y = 0; y < 15; ++y)
- {
- if(chessData[x][y] == 0)
- continue;
- if(chessData[x][y] == -MyColor)
- EnemyScore += EnemyPositionAdd[x][y];
- for(var i = 0; i < EnemyPattern.length; ++i)
- {
- if(!Array.isArray(EnemyPattern[i][0]))
- {
- if(this.Match(x, y, 0, -1, EnemyPattern[i], -MyColor)) //往上找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y, 0, 1, EnemyPattern[i], -MyColor)) //往下找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y, -1, 0, EnemyPattern[i], -MyColor)) //往左找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y, 1, 0, EnemyPattern[i], -MyColor)) //往右找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y, -1, -1, EnemyPattern[i], -MyColor)) //往左上找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y, -1, 1, EnemyPattern[i], -MyColor)) //往左下找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y, 1, -1, EnemyPattern[i], -MyColor)) //往右上找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y, 1, 1, EnemyPattern[i], -MyColor)) //往右下找
- EnemyScore += EnemyAdd[i];
- }
- else
- {
- if(this.Match(x, y+1, 0, 1, EnemyPattern[i][0], -MyColor) && this.Match(x, y, 0, -1, EnemyPattern[i][1], -MyColor)) //往上找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x, y-1, 0, -1, EnemyPattern[i][0], -MyColor) && this.Match(x, y, 0, 1, EnemyPattern[i][1], -MyColor)) //往下找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x+1, y, 1, 0, EnemyPattern[i][0], -MyColor) && this.Match(x, y, -1, 0, EnemyPattern[i][1], -MyColor)) //往左找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x-1, y, -1, 0, EnemyPattern[i][0], -MyColor) && this.Match(x, y, 1, 0, EnemyPattern[i][1], -MyColor)) //往右找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x+1, y+1, 1, 1, EnemyPattern[i][0], -MyColor) && this.Match(x, y, -1, -1, EnemyPattern[i][1], -MyColor)) //往左上找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x+1, y-1, 1, -1, EnemyPattern[i][0], -MyColor) && this.Match(x, y, -1, 1, EnemyPattern[i][1], -MyColor)) //往左下找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x-1, y+1, -1, 1, EnemyPattern[i][0], -MyColor) && this.Match(x, y, 1, -1, EnemyPattern[i][1], -MyColor)) //往右上找
- EnemyScore += EnemyAdd[i];
- if(this.Match(x-1, y-1, -1, -1, EnemyPattern[i][0], -MyColor) && this.Match(x, y, 1, 1, EnemyPattern[i][1], -MyColor)) //往右下找
- EnemyScore += EnemyAdd[i];
- }
- }
- }
- }
- return (MyScore*multiplier) - EnemyScore;
- }
- //檢查由(x,y)位置往(dirX, dirY)方向延伸,是否可以找到所傳入的Pattern
- this.Match = function(x, y, dirX, dirY, Pattern, MyColor)
- {
- var n = Pattern.length;
- if(x+dirX*(n-1) < 0 || x+dirX*(n-1) > 14 || y+dirY*(n-1) < 0 || y+dirY*(n-1) > 14)
- return false;
- else
- {
- for(var i = 0; i < n; ++i)
- {
- if(Pattern[i] == 0 && chessData[x][y] != 0)
- return false;
- else if(Pattern[i] == 1 && chessData[x][y] != MyColor)
- return false;
- else if(Pattern[i] == -1 && chessData[x][y] == MyColor)
- return false;
- x += dirX;
- y += dirY;
- }
- return true;
- }
- }
- //執行MINMAX + AlphaBeta剪枝(UsePrunning為true),或僅執行MINMAX(UsePrunning為false)
- //CurrentColor:「準備」下的顏色 / (lastStepX, lastStepY):「上一步」下的位置
- this.AlphaBeta = function(chessData, step, alpha, beta, MyColor, CurrentColor, lastStepX, lastStepY)
- {
- //預測到這步就好 或者是 已經有結果(有預測的上一步並且因此分出勝負),就開始把值回傳
- if( step == 0 || (lastStepX != -1 && lastStepY != -1 && judge(lastStepX, lastStepY, -CurrentColor)) )
- return [lastStepX, lastStepY, this.Score(chessData, MyColor, -CurrentColor, lastStepX, lastStepY)];
- //否則預測所有可能的下一步
- var NotCut = true; //設定是否已經開始被剪枝
- var BestX, BestY; //最好那步的(x,y)
- var x = 7, y = 7;
- /*============ 加速2. 對於所有分枝,先走好的-->再走壞的,讓壞的有機會被剪掉;若相反,先走壞的-->再走好的,則不會做剪枝 ============*/
- //天元是最好的,嘗試走下在天元的分枝
- if(chessData[x][y] == 0)
- {
- chessData[x][y] = CurrentColor;
- var move = this.AlphaBeta(chessData, step-1, alpha, beta, MyColor, -CurrentColor, x, y)
- chessData[x][y] = 0;
- if(MyColor == CurrentColor)
- {
- if(alpha < move[2])
- {
- alpha = move[2];
- BestX = x;
- BestY = y;
- }
- }
- else
- {
- if(beta > move[2])
- {
- beta = move[2];
- BestX = x;
- BestY = y;
- }
- }
- if(UsePrunning && beta <= alpha)
- NotCut = false;
- }
- //從天元開始,由內而外、順時針尋找空格、走分枝
- var circle = 1, times = 1;
- var dir = [[1,0],[0,1],[-1,0],[0,-1]];
- var choess = 0;
- var temp = circle;
- while(true)
- {
- x += dir[choess][0];
- y += dir[choess][1];
- if(chessData[x][y] == 0)
- {
- //嘗試在空的位置下準備要下的顏色的棋
- chessData[x][y] = CurrentColor;
- //計算下一層的AlphaBeta值
- var move = this.AlphaBeta(chessData, step-1, alpha, beta, MyColor, -CurrentColor, x, y)
- //把空的位置復原
- chessData[x][y] = 0;
- //根據是自己或對方的回合,決定剪枝根據
- if(MyColor == CurrentColor)
- {
- if(alpha < move[2])
- {
- alpha = move[2];
- BestX = x;
- BestY = y;
- }
- }
- else
- {
- if(beta > move[2])
- {
- beta = move[2];
- BestX = x;
- BestY = y;
- }
- }
- //正式剪枝
- if(UsePrunning && beta <= alpha)
- NotCut = false;
- }
- if(!NotCut || (x == 14 && y == 0))
- break;
- temp--;
- if(temp == 0)
- {
- choess = (choess+1)%4;
- if(times > 0)
- {
- temp = circle;
- --times;
- }
- else
- {
- times = 1;
- ++circle;
- temp = circle;
- }
- }
- }
- //如果是自己的回合,則回傳最好(MAX)的選擇(alpha);如果是對方的回合,則回傳最差(MIN)的選擇(beta)
- if(MyColor == CurrentColor)
- return [BestX, BestY, alpha];
- else
- return [BestX, BestY, beta];
- }
- //AI主程式
- this.AI = function(chessData, MyColor)
- {
- var move;
- if(step == 0)
- move = Random(chessData);
- else
- move = this.AlphaBeta(chessData, step, Number.NEGATIVE_INFINITY, Number.POSITIVE_INFINITY, MyColor, MyColor, -1, -1);
- drawChess(move[0], move[1]);
- }
- //隨機在空格下一子
- this.Random = function(chessData)
- {
- var x, y;
- while(true)
- {
- x = Math.floor(Math.random()*15);
- y = Math.floor(Math.random()*15);
- if(chessData[x][y] == 0)
- break;
- }
- return [x,y];
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement