Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将极小极大函数从Java转换为JavaScript_Javascript_Arrays_Minimax_Negamax - Fatal编程技术网

将极小极大函数从Java转换为JavaScript

将极小极大函数从Java转换为JavaScript,javascript,arrays,minimax,negamax,Javascript,Arrays,Minimax,Negamax,这将是一个巨大的代码墙,但我希望有人有时间和耐心来帮助我 我目前正在尝试为我的HTML井字游戏创建一个AI播放器。我正在使用这个资源,其中包含使用minimax算法用Java编程的人工智能播放器代码:(第1.5节) 我想把这个给定的Java代码翻译成JavaScript。资源代码和我的HTML/JS代码之间的一个主要区别是,资源在游戏板上使用二维数组,而我使用一维数组 这意味着资源的数组如下所示:Cell[]cells其中第一个索引表示行,第二个索引表示列;我的数组如下所示:let board_

这将是一个巨大的代码墙,但我希望有人有时间和耐心来帮助我

我目前正在尝试为我的HTML井字游戏创建一个AI播放器。我正在使用这个资源,其中包含使用minimax算法用Java编程的人工智能播放器代码:(第1.5节)

我想把这个给定的Java代码翻译成JavaScript。资源代码和我的HTML/JS代码之间的一个主要区别是,资源在游戏板上使用二维数组,而我使用一维数组

这意味着资源的数组如下所示:
Cell[]cells其中第一个索引表示行,第二个索引表示列;我的数组如下所示:
let board_array=[]长度为9,表示从左上到右下读取的板,因此,例如,左上单元格位于索引0,右中单元格位于索引5

另一个微小的区别是,资源使用播放器种子存储在单元格数组中,而我只使用字符串
'X'
来表示人,使用字符串
'O'
来表示人工智能

我花了很多时间试图将给定的Java函数转换为我的JS脚本,但不管我怎么做,
minimax
总是返回
-1
作为最终的最佳单元格,据我所知,只有在没有更多可用单元格的情况下才会出现,这表明游戏已经结束。我已经做了一些console.log调试,我可以看到在递归过程中的某个时刻,实际上返回了合法的最佳单元格(例如0或4),但在最终返回中,它总是-1

我敢打赌,我的错误要么在于从二维数组到一维数组的错误转换,要么与JS在特定行中做了与Java完全不同的事情有关。我可以想象,
WINNING\u PATTERNS
数组中的二进制值或
haswun
函数中对它们的操作可能会引起麻烦。我不知道它在JS中是否能像这样工作,但它不会抛出任何错误,所以我无法自己解决

无论如何,我的代码如下:

let board_array = ['X', '', '', '', '', '', '', '', '']; // X at a random index because the human player always makes the first turn
const MY_SEED = 'O';
const OPP_SEED = 'X';

function moveAI() {
  let result = minimax(2, MY_SEED);
  let best_cell = result[1];
  console.log(best_cell); // always returns -1
  // if best_cell would be properly returned I could do "board_array[best_cell] = 'O'" here
}

function minimax(depth, player) {
  let next_moves = generateMoves();
  let best_score = (player === MY_SEED) ? Number.MIN_VALUE : Number.MAX_VALUE;
  let current_score;
  let best_cell = -1;

  if (next_moves.length === 0 || depth === 0) {
    best_score = evaluate();
  }
  else {
    for (let move in next_moves) {
      move = parseInt(move);
      board_array[move] = player;
      if (player === MY_SEED) {
        current_score = minimax(depth - 1, OPP_SEED)[0];
        if (current_score > best_score) {
          best_score = current_score;
          best_cell = move;
        }
      }
      else {
        current_score = minimax(depth - 1, MY_SEED)[0];
        if (current_score < best_score) {
          best_score = current_score;
          best_cell = move;
        }
      }
      board_array[move] = '';
    }
  }
  return [best_score, best_cell];
}

function generateMoves() {
  let next_moves = [];
  if (hasWon(MY_SEED) || hasWon(OPP_SEED)) {
    return next_moves;
  }
  for (let i = 0; i < board_array.length; i++) {
    if (board_array[i] === '') { next_moves.push(i); }
  }
  return next_moves;
}

function evaluate() {
  let score = 0;
  score += evaluateLine(0, 1, 2);
  score += evaluateLine(3, 4, 5);
  score += evaluateLine(6, 7, 8);
  score += evaluateLine(0, 3, 6);
  score += evaluateLine(1, 4, 7);
  score += evaluateLine(2, 5, 8);
  score += evaluateLine(0, 4, 8);
  score += evaluateLine(2, 4, 6);
  return score;
}

function evaluateLine(c1, c2, c3) {
  let score = 0;

  if (board_array[c1] === MY_SEED) { score = 1; }
  else if (board_array[c1] === OPP_SEED) { score = -1; }

  if (board_array[c2] === MY_SEED) {
    if (score === 1) { score = 10; }
    else if (score === -1) { return 0; }
    else { score = 1; }
  }
  else if (board_array[c2] === OPP_SEED) {
    if (score === -1) { score = -10; }
    else if (score === 1) { return 0; }
    else { score = -1; }
  }

  if (board_array[c3] === MY_SEED) {
    if (score > 0) { score *= 10; }
    else if (score < 0) { return 0; }
    else { score = 1; }
  }
  else if (board_array[c3] === OPP_SEED) {
    if (score < 0) { score *= 10; }
    else if (score > 1) { return 0; }
    else { score = -1; }
  }

  return score;
}

const WINNING_PATTERNS = [
  0b111000000, 0b000111000, 0b000000111,
  0b100100100, 0b010010010, 0b001001001,
  0b100010001, 0b001010100
];

function hasWon(player) {
  let pattern = 0b000000000; // does JS recognize this as a binary number like Java does?
  for (let i = 0; i < board_array.length; i++) {
    if (board_array[i] === player) {
      pattern |= (1 << (9 - i)); // does this actually do what I think it does? (compare to Java code)
    }
  }
  for (let winning_pattern in WINNING_PATTERNS) {
    if ((pattern & winning_pattern) === winning_pattern) { return true; }
  }
  return false;
}

moveAI(); // usually called after the human player sets their X
let board_array=['X'、''、''、''、''、''、''、''、''、''、'];//因为人类玩家总是第一个回合
const MY_SEED='O';
const OPP_SEED='X';
函数moveAI(){
设结果=极小极大(2,我的种子);
设最佳_单元=结果[1];
console.log(最佳_单元格);//始终返回-1
//如果最佳单元正确返回,我可以在这里执行“board_array[best_cell]='O'”
}
函数minimax(深度,播放器){
让下一步移动=生成移动();
让最佳得分=(玩家==我的种子)?Number.MIN\u值:Number.MAX\u值;
让当前的_评分;
设最佳_单元=-1;
if(next_moves.length==0 | | depth==0){
最佳分数=评估();
}
否则{
for(让我们进入下一步){
move=parseInt(move);
棋盘阵列[移动]=玩家;
如果(玩家===我的种子){
当前_分数=最小最大值(深度-1,OPP_SEED)[0];
如果(当前评分>最佳评分){
最佳_分数=当前_分数;
最佳_单元=移动;
}
}
否则{
当前_分数=极大极小值(深度-1,我的_种子)[0];
if(当前评分<最佳评分){
最佳_分数=当前_分数;
最佳_单元=移动;
}
}
板_阵列[移动]='';
}
}
返回[best_score,best_cell];
}
函数generateMoves(){
让下一步行动=[];
如果(我的种子){
返回下一步动作;
}
for(设i=0;i0){score*=10;}
如果(分数<0){返回0;}
else{score=1;}
}
else if(板阵列[c3]==OPP\U种子){
如果(分数<0){score*=10;}
如果(分数>1){返回0;}
else{score=-1;}
}
返回分数;
}
常量模式=[
0b111000000、0b000111000、0b000000111、,
0b100100100、0b010010010、0b001001001、,
0B1000100100B001010100
];
哈斯旺(玩家){
让pattern=0b00000000;//JS是否像Java一样将其识别为二进制数?
for(设i=0;i模式|=(1二进制数在JavaScript中是可能的,因为ES6-


和JavaScript中的位运算符(例如,尝试输入一些调试代码。这不是java问题。请删除java标记。JavaScript中的二进制数,因为ES6和JavaScript中的位运算符(
Number.MAX\u VALUE
(1.79E+308)与java的
Integer.MAX\u VALUE
(2147483647)不同-不确定这有多重要?@AlexL I将
Number.MAX\u VALUE
替换为
Number.MAX\u SAFE\u INTEGER
(最小值也一样)现在整个算法似乎运行正常。我不认为这会有任何区别。非常感谢你的帮助。你可以将你最后的评论作为答案发布,这样如果你愿意,我可以接受。