//開始回合 //傳入值為下回合行動方 //1為黑棋,2為白棋 function startTurn(nextTurn){ turn=nextTurn; //下回合為ai回合 if(turn==ai){ //處理AI aiAction(); } } function aiAction(){ } |
function aiAction(){ //取得評價最大的索引 var aiPickIndex=getMaxEvaluateIndex(turn); //取得索引相對的棋格物件 var aiPickPiece=boardPiece.childNodes[aiPickIndex+18+Math.floor(aiPickIndex/15)*2]; //ai放棋 putChess(aiPickPiece,aiPickIndex); } |
//取得最大評價索引 function getMaxEvaluateIndex(){ //回傳index為1的棋格 return 1; } |
//取得最大評價索引 function getMaxEvaluateIndex(){ var evaluate=[]; for(var y=0; y<15; y++){ for(var x=0; x<15; x++){ //依序評價每個座標點 evaluate.push(evaluatePoint(x,y)); } } //取得最大值 var max = Math.max.apply(Math,evaluate); //在等同最大值的評價中隨機取一索引 return selectRandomIndexByValue(evaluate,max); } |
//在同值的陣列成員中隨機取一索引 function selectRandomIndexByValue(arr,value){ var indexs=[]; for(var i=0;i<arr.length;i++){ if(arr==value){ indexs.push(i); } } return indexs[Math.floor(Math.random()*indexs.length)]; } |
function evaluatePoint(x,y){ return 1; } |
//評價座標點 function evaluatePoint(x,y){ //該點非空棋格 if(board[y*15+x] > 0){ //回傳-1權重 return -1; } //總評價值 var evaluateValue=0; //評價橫←,→ evaluateValue+=evaluateLine(x,y,1,0); //評價直↑,↓ evaluateValue+=evaluateLine(x,y,0,-1); //評價左上斜↖,↘ evaluateValue+=evaluateLine(x,y,-1,-1); //評價左下斜↙,↗ evaluateValue+=evaluateLine(x,y,1,-1); //回傳評價 return evaluateValue; } |
//評價通過某點直線的攻防比重 function evaluateLine(x,y,dx,dy){ var atkValue=0;//攻擊權重 var defValue=0;//防禦權重 //正方向估值 atkValue+=evaluateVector(x,y,dx,dy,atkValues,turn); defValue+=evaluateVector(x,y,dx,dy,defValues,3-turn); //反方向估值 atkValue+=evaluateVector(x,y,dx*-1,dy*-1,atkValues,turn); defValue+=evaluateVector(x,y,dx*-1,dy*-1,defValues,3-turn); //總和評估 //如果攻擊權重大於防禦權重 if(atkValue>defValue){ //回傳攻擊權重 return atkValue; }else{ //回傳防禦權重 return defValue; } } |
//向量權重 function evaluateVector(x,y,dx,dy,evaluateValues,evaluateType){ //權重初始為0 var valueIndex=0; //一路判定原點往外整條線共4格 for(var i=0;i<4;i++){ //切換到下一點連線 x+=dx; y+=dy; //超出棋盤範圍則回傳該向量沒價值 if(!valid(x,y)){ return evaluateValues[0]; } //該連線上為判定棋則權重+2 if(board[y*15+x] == evaluateType){ valueIndex+=2; //若不是判定棋 }else{ //是判定棋的對手 且 權重索引指向活1以上 if(board[y*15+x]==3-evaluateType && valueIndex>1){ //權重-1指向死路 valueIndex-=1; } //離開迴圈 break; } } //回傳權重相對索引 return evaluateValues[valueIndex]; } |
//正反兩路結合條件 const combineIf=[ [[1,1],[3,3],[5,5],[7,7]],//雙死沒價值 [[0,1]],//沒價值+死1=死1 [[0,2]],//沒價值+活1=活1 [[0,3],[1,2]],//沒價值+死2or死1+死1=死2 [[0,4],[2,2]],//沒價值+活2or活1+活1=活2 [[0,5],[1,4],[2,3]],//沒價值+死3or死1+活2or死2+活1=死3 [[0,6],[2,4]],//沒價值+活3or活1+活2=活3 [[0,7],[1,6],[3,4],[5,2]],//沒價值+死4or死1+活3or死2+活2or死3+活1=死4 [[0,8],[2,6],[4,4]],//沒價值+活4or活1+活3or活2+活2=活4 ]; |
//評價通過某點直線的攻防比重 function evaluateLine(x,y,dx,dy){ var atkValuePosIndex=0;//正向攻擊權重索引 var atkValueNegIndex=0;//反向攻擊權重索引 var defValuePosIndex=0;//正向防禦權重索引 var defValueNegIndex=0;//反向防禦權重索引 var atkValueAll=0;//攻擊權重總和 var defValueAll=0;//防禦權重總和 //正方向估值索引 atkValuePosIndex=evaluateVector(x,y,dx,dy,turn); defValuePosIndex=evaluateVector(x,y,dx,dy,3-turn); //反方向估值索引 atkValueNegIndex=evaluateVector(x,y,dx*-1,dy*-1,turn); defValueNegIndex=evaluateVector(x,y,dx*-1,dy*-1,3-turn); //攻擊總和評估 //兩個都基數為雙死 if(atkValuePosIndex%2==1 && atkValueNegIndex%2==1){ atkValueAll=0; //其餘 }else{ atkValueAll=atkValues[atkValuePosIndex+atkValueNegIndex]; } //防禦總和評估 //兩個都基數為雙死 if(defValuePosIndex%2==1 && defValueNegIndex%2==1){ defValueAll=0; //其餘 }else{ defValueAll=defValues[defValuePosIndex+defValueNegIndex]; } //如果攻擊權重大於防禦權重 if(atkValueAll>defValueAll){ //回傳攻擊權重 return atkValueAll; }else{ //回傳防禦權重 return defValueAll; } } |
function evaluateVector(x,y,dx,dy,evaluateType){ //權重初始為0 var valueIndex=0; //一路判定原點往外整條線共4格 for(var i=0;i<4;i++){ //切換到下一點連線 x+=dx; y+=dy; //超出棋盤範圍則回傳該向量沒價值 if(!valid(x,y)){ return 0; } //該連線上為判定棋則權重+2 if(board[y*15+x] == evaluateType){ valueIndex+=2; //若不是判定棋 }else{ //是判定棋的對手 且 權重索引指向活1以上 if(board[y*15+x]==3-evaluateType && valueIndex>1){ //權重-1指向死路 valueIndex-=1; } //離開迴圈 break; } } //回傳權重相對索引 return valueIndex; } |
同標籤作品搜尋:程式|編成|html|javascript|五子棋|AI設計
留言共 8 篇留言
前一篇:【JavaScript】... 後一篇:【神寶幻想】安迪的三種型...