0

我正在嘗試使用min max算法來構建井字遊戲AI。我指的是來自geekforgeeks的這個post編寫我的代碼。但奇怪的是,當我通過修改下面給出的代碼來使用一維數組而不是二維數組時,我沒有從findBestMove函數獲得正確的輸出。它應該返回索引爲4,但它總是返回2.我做錯了什麼?井字遊戲:在2d陣列上使用1d陣列時不同的輸出

function Move(x,y){ 
    this.row = x, 
    this.col = y; 
}; 

const player = 'o', opponent = 'x'; 


const isMovesLeft = (board) => { 
    for (let i = 0; i<3; i++) 
     for (let j = 0; j<3; j++) 
      if (board[i][j]=='_') 
       return true; 
    return false; 
} 

const isMovesLeft2 = (board) => { 
    for (let i = 0; i<9; i++) 
     if (board[i]=='_') 
      return true; 
    return false; 
} 

const evaluate = (b) =>{ 
    for (let row = 0; row<3; row++) 
    { 
     if (b[row][0]==b[row][1] && 
      b[row][1]==b[row][2]) 
     { 
      if (b[row][0]==player) 
       return +10; 
      else if (b[row][0]==opponent) 
       return -10; 
     } 
    } 

    for (let col = 0; col<3; col++) 
    { 
     if (b[0][col]==b[1][col] && 
      b[1][col]==b[2][col]) 
     { 
      if (b[0][col]==player) 
       return +10; 

      else if (b[0][col]==opponent) 
       return -10; 
     } 
    } 

    if (b[0][0]==b[1][1] && b[1][1]==b[2][2]) 
    { 
     if (b[0][0]==player) 
      return +10; 
     else if (b[0][0]==opponent) 
      return -10; 
    } 

    if (b[0][2]==b[1][1] && b[1][1]==b[2][0]) 
    { 
     if (b[0][2]==player) 
      return +10; 
     else if (b[0][2]==opponent) 
      return -10; 
    } 

    return 0; 
} 

const evaluate2 = (b) =>{ 
    for (let row = 0; row<3; row++) 
    { 
     if (b[row]==b[row+1] && 
      b[row+1]==b[row+2]) 
     { 
      if (b[row]==player) 
       return +10; 
      else if (b[row]==opponent) 
       return -10; 
     } 
    } 

    for (let col = 0; col<3; col++) 
    { 
     if (b[col]==b[col+3] && 
      b[col+3]==b[col+6]) 
     { 
      if (b[col]==player) 
       return +10; 

      else if (b[col]==opponent) 
       return -10; 
     } 
    } 

    if (b[0]==b[4] && b[4]==b[8]) 
    { 
     if (b[0]==player) 
      return +10; 
     else if (b[0]==opponent) 
      return -10; 
    } 

    if (b[2]==b[4] && b[4]==b[6]) 
    { 
     if (b[2]==player) 
      return +10; 
     else if (b[2]==opponent) 
      return -10; 
    } 

    return 0; 
} 

const minimax = (board , depth, isMax) => { 
    let score = evaluate(board); 

    if (score == 10) 
     return score; 

    if (score == -10) 
     return score; 

    if (isMovesLeft(board)==false) 
     return 0; 

    if (isMax) 
    { 
     let best = -1000; 

     for (let i = 0; i<3; i++) 
     { 
      for (let j = 0; j<3; j++) 
      { 
       if (board[i][j]=='_') 
       { 
        board[i][j] = player; 


        best = Math.max(best, 
         minimax(board, depth+1, !isMax)); 

        board[i][j] = '_'; 
       } 
      } 
     } 
     return best; 
    } 

    else 
    { 
     let best = 1000; 

     // Traverse all cells 
     for (let i = 0; i<3; i++) 
     { 
      for (let j = 0; j<3; j++) 
      { 

       if (board[i][j]=='_') 
       { 
        board[i][j] = opponent; 

        best = Math.min(best, 
         minimax(board, depth+1, !isMax)); 
        board[i][j] = '_'; 
       } 
      } 
     } 
     return best; 
    } 
} 

const minimax2 = (board , depth, isMax) => { 
    let score = evaluate2(board); 

    if (score == 10) 
     return score; 

    if (score == -10) 
     return score; 

    if (isMovesLeft2(board)==false) 
     return 0; 

    if (isMax) 
    { 
     let best = -1000; 

     for (let i = 0; i<9; i++) 
     { 
       if (board[i]=='_') 
       { 
        board[i] = player; 


        best = Math.max(best, 
         minimax2(board, depth+1, !isMax)); 

        board[i] = '_'; 
       } 

     } 
     return best; 
    } 

    else 
    { 
     let best = 1000; 

     for (let i = 0; i<9; i++) 
     { 


       if (board[i]=='_') 
       { 
        board[i] = opponent; 

        best = Math.min(best, 
         minimax2(board, depth+1, !isMax)); 
        board[i] = '_'; 
       } 
     } 
     return best; 
    } 
} 

const findBestMove = (board) =>{ 
    let bestVal = -1000; 
    let bestMove = new Move(-1,-1); 

    for (let i = 0; i<3; i++) 
    { 
     for (let j = 0; j<3; j++) 
     { 
      if (board[i][j]=='_') 
      { 
       board[i][j] = player; 

       let moveVal = minimax(board, 0, false); 

       board[i][j] = '_'; 

       if (moveVal > bestVal) 
       { 
        bestMove.row = i; 
        bestMove.col = j; 
        bestVal = moveVal; 
       } 
      } 
     } 
    } 


    return bestMove; 
} 

const findBestMove2 = (board) =>{ 
    let bestVal = -1000; 
    let bestMove = -1; 

    for (let i = 0; i<9; i++) 
    { 

      if (board[i]=='_') 
      { 
       board[i] = player; 

       let moveVal = minimax2(board, 0, false); 

       board[i]= '_'; 

       if (moveVal > bestVal) 
       { 
        bestMove = i 
        bestVal = moveVal; 
       } 
      } 

    } 


    return bestMove; 
} 


const test =() => { 
    const board = [['x','_','_'], 
        ['_','_','_'], 
        ['_','_','_']]; 
    const board2 = ['x','_','_', 
        '_','_','_', 
        '_','_','_']; 
    console.log(findBestMove(board)); 
    console.log(findBestMove2(board2)); 
} 

test(); 

當測試()被執行第一函數調用返回最理想的做法爲(1,1),但第二個函數返回2.應當4理想。

+0

對不起Suneeth,我們不能幫助尋找錯誤。你遇到了什麼錯誤?你到目前爲止搜索和嘗試過什麼? – RaphaMex

+0

很難說明代碼有什麼問題,而不進行調試。您可以嘗試使用調試器,通過設置中斷點,觀察值。 – grepLines

+0

@ R.Saban:描述已更新,以更好地解釋我的問題。除了使用的數組類型之外,我找不到兩組函數之間的區別。他們仍然返回兩個不同的值。 –

回答

0

在功能evaluate2,你循環是這樣的:

for (let row = 0; row<3; row++) 

你應該循環這樣

for (let row = 0; row<9; row+=3) 
+0

非常感謝。這就是爲什麼人們說2雙眼睛總是比1更好的原因。 –