You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让<div>.innerHTML实时输出Connect Four AI对战中间状态?

四子棋AI对战页面实时输出中间状态问题

问题描述

我有一个基于Alpha-beta剪枝的四子棋AI对战页面,运行两个AI bot进行对战。目前遇到的问题是:尽管在对战过程中通过innerHTML向承载输出的<div>添加进度文本,但所有输出需等游戏结束后才会显示。如何实现将对战中间状态文本实时输出到目标<div>中?

问题代码

let text = "";
const output = document.getElementById('output-text-div');
const heuristicFunction = ...;
const engine = ...;
const depth = 8;

let state = new ConnectFourBoard();
text += state.toString() + "&lt;br/&gt;";

function millis() {
  return new Date().valueOf();
}

let totalDurationX = 0;
let totalDurationO = 0;

while (true) {
  text += "X's turn:&lt;br/&gt;";

  let ta = millis();
  state = engine.search(state, depth, X);
  let tb = millis();

  totalDurationX += tb - ta;

  text += state.toString();
  text += "&lt;br/&gt;";
  text += "X AI duration: " + (tb - ta) + " milliseconds.&lt;br/&gt;";
  output.innerHTML = text;

  if (state.isTie()) {
    text += "RESULT: It's a tie.&lt;br/&gt;";
    break;
  }

  if (state.isWinningFor(X)) {
    text += "RESULT: X won.&lt;br/&gt;";
    break;
  }

  text += "O's turn:&lt;br/&gt;";
  output.innerHTML = text;

  var i = output.height;

  ta = millis();
  state = engine.search(state, depth, O);
  tb = millis();
  output.innerHTML = text;

  totalDurationO += tb - ta;

  text += state.toString();
  text += "&lt;br/&gt;";
  text += "O AI duration: " + (tb - ta) + " milliseconds.&lt;br/&gt;";

  if (state.isTie()) {
    text += "RESULT: It's a tie.&lt;br/&gt;";
    break;
  }

  if (state.isWinningFor(O)) {
    text += "RESULT: O won.&lt;br/&gt;";
    break;
  }

  output.innerHTML = text;
  i = output.width;
}

text += "X AI total duration: " + totalDurationX + " milliseconds.&lt;br/&gt;";
text += "O AI total duration: " + totalDurationO + " milliseconds.&lt;br/&gt;";

output.innerHTML = text;

解决方案

问题根源

浏览器的UI渲染线程与JavaScript执行线程互斥,同步while(true)循环会持续阻塞JS线程,导致UI线程无法及时处理DOM更新请求,所有渲染操作会被延迟到循环结束后批量执行。

修复方法

将同步循环改为基于async/await的异步逻辑,每次AI思考完成后主动让出线程,给UI渲染留出时间:

修改后的代码

let text = "";
const output = document.getElementById('output-text-div');
const heuristicFunction = ...;
const engine = ...;
const depth = 8;

let state = new ConnectFourBoard();
text += state.toString() + "&lt;br/&gt;";
output.innerHTML = text;

function millis() {
  return new Date().valueOf();
}

// 让出线程,允许UI渲染当前更新
async function yieldToUI() {
  await new Promise(resolve => setTimeout(resolve, 0));
}

async function startBattle() {
  let totalDurationX = 0;
  let totalDurationO = 0;

  while (true) {
    text += "X's turn:&lt;br/&gt;";
    output.innerHTML = text;
    await yieldToUI(); // 等待UI渲染当前文本

    let ta = millis();
    state = engine.search(state, depth, X);
    let tb = millis();

    totalDurationX += tb - ta;

    text += state.toString();
    text += "&lt;br/&gt;";
    text += "X AI duration: " + (tb - ta) + " milliseconds.&lt;br/&gt;";
    output.innerHTML = text;
    await yieldToUI();

    if (state.isTie()) {
      text += "RESULT: It's a tie.&lt;br/&gt;";
      break;
    }

    if (state.isWinningFor(X)) {
      text += "RESULT: X won.&lt;br/&gt;";
      break;
    }

    text += "O's turn:&lt;br/&gt;";
    output.innerHTML = text;
    await yieldToUI();

    ta = millis();
    state = engine.search(state, depth, O);
    tb = millis();

    totalDurationO += tb - ta;

    text += state.toString();
    text += "&lt;br/&gt;";
    text += "O AI duration: " + (tb - ta) + " milliseconds.&lt;br/&gt;";
    output.innerHTML = text;
    await yieldToUI();

    if (state.isTie()) {
      text += "RESULT: It's a tie.&lt;br/&gt;";
      break;
    }

    if (state.isWinningFor(O)) {
      text += "RESULT: O won.&lt;br/&gt;";
      break;
    }
  }

  text += "X AI total duration: " + totalDurationX + " milliseconds.&lt;br/&gt;";
  text += "O AI total duration: " + totalDurationO + " milliseconds.&lt;br/&gt;";
  output.innerHTML = text;
}

// 启动对战
startBattle();

核心说明

  • yieldToUI函数通过setTimeout(resolve, 0)触发微任务,让JS线程暂时释放控制权,UI线程得以处理DOM更新并完成渲染
  • 每次修改output.innerHTML后调用await yieldToUI(),确保中间状态能实时显示
  • 整个对战逻辑封装在async函数中,避免阻塞主线程

内容的提问来源于stack exchange,提问作者coderodde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:54:55