哪个是游戏AI最推荐的线程模式以及如何实现它?

时间:2011-12-18 20:41:04

标签: c# multithreading artificial-intelligence backgroundworker threadpool

我是C#线程的新手,尽管阅读了很多关于线程的理论,但它在实践中对我没什么帮助。

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

有4种选择:常规线程,线程池,异步委托,BackgroundWorker。

BackgroundWorker在我看来是理想的,它有委托完成所以我可以运行“makemove”函数,它实际上会在板上进行计算移动并更新进度条。

我有3个问题:

  1. 对于这种情况,BackgroundWorker真的是最好的解决方案吗?

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

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

  4. 任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:3)

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

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

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

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

假设你的程序在主线程上启用了AI,你的程序会调用AIAct()。另外,让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;
}