这是游戏AI最推荐的线程模式,以及如何实现它

本文关键字:何实现 实现 模式 AI 游戏 线程 | 更新日期: 2023-09-27 18:18:08

我是c#线程的新手,尽管阅读了很多关于线程的理论,但在实践中并没有多大帮助。

我想为跳棋游戏编写AI函数(minmax alphabeta),并在不同的线程中执行。

有4个选项:常规Tread,线程池,异步委托,BackgroundWorker。

BackgroundWorker对我来说似乎是理想的,它有完成委托,所以我可以运行"makemove"函数,它实际上会在板上计算移动和更新进度条。

我有三个问题:

  1. BackgroundWorker真的是这种情况下的最佳解决方案吗?

  2. BackgroundWorker在线程池中执行,这样做的好处是什么?当你有许多不同的线程时,人们总是说线程池是好的,但这并不完全是我的情况。

  3. 我看到的所有代码示例都太简单了,只展示了如何创建一个这样的线程。在我的程序中,每次轮到计算机时我都需要运行这个函数,所以我可能需要杀死前一个线程并启动一个新线程。实现这一切的正确方法是什么?

这是游戏AI最推荐的线程模式,以及如何实现它

1)这些解决方案都是可行的;你只需要使用一些不同的逻辑来处理每一个。

2)当你有一组可以在多个线程上执行的事情时,ThreadPool也很有用(例如,在中国跳棋游戏中,你可以通过ThreadPool运行5种不同的AI模拟,它将在具有两个核心的计算机上运行最佳,而使用线程将由于上下文切换而减慢进程)。它当然适用于你的情况-你只需要排队第二次AIEvaluation或其他什么,它会开始执行尽快。

3)嗯,不完全是。计算机只有在运行alphabeta之后才能真正开始行动(可能会有一些截断深度:P),所以AI线程无论如何都会完成它的工作。你可以每次都使用ThreadPool/BackgroundWorker。

一些关于BackgroundWorker的一般信息:当你有"额外"的CPU时间时,它会运行,所以如果你的主线程由于某种原因占用CPU,它不会做很多事情。使用普通的ThreadPool可能会更好。

让我们说你的程序调用AIAct()时,轮到AI在主线程。另外,让timerTick成为Windows窗体中存在的那种计时器。此外,让类AIState和GameBoard封装alpha-beta所需的功能。

using System.Threading;
const int CUTOFF_DEPTH = 6;//Maximum plys for alpha-beta
AIState state;
void AIAct()
{
    state = new AIState( this.GameBoard.GetState() );
ThreadPool.QueueUserWorkItem(RunMinimax, state);
    //assume that timerTick is a Timer (Windows Forms Timer) that ticks every 100 ms
    timerTick.Enabled = true;
}
void timerTick_Tick(object sender, EventArgs e)
{
    if (state.IsComplete)
    {
        ExecuteAction(state.Result);
        timerTick.Enabled = false;
        //whatever else you need to do
    }
}
private static void RunMinimax(object args)
{
    AIState state = args as AIState;
    if (state == null)
    {
        //error handling of some sort
        Thread.CurrentThread.Abort();
    }
    //run your minimax function up to max depth of CUTOFF_DEPTH
    state.Result = Minimax( /* */ );
    state.IsComplete = true;
}
private class AIState
{
    public AIState(GameBoard board)
    {
        this.Board = board;
    }
    public readonly GameBoard Board;
    public AIAction Result;
    public volatile bool IsComplete;
}