使用Qt开发中国象棋(四):步时控制

        一般的象棋游戏中都会限时,超过时间没走棋,就算输了。这个游戏采用的是步时限制。走棋的时候会有提示,像下面那样:


        界面用的是一个QLable来显示“红方走棋”,后面显示时间的用的是一个QLCDNumber的控件。显示时间可以用定时器的方式或者线程的方式,我这里用的是线程的方式。采用的是线程和条件变量的方式。Qt提供了QWaitCondition用于条件变量,QMutex用于互斥锁,QThread类用于线程。了解POSIX多线程编程的同学想必都知道,条件变量,锁和线程是POSIX多线程编程惯用的伎俩。做这个东西时,我就参考的这种方式。要使用线程,可以写一个类继承自QThread类,据说还有一种方法,这里就不研究了,必须实现其run方法,也就是线程要做的事情。

        整个思路如下:

       (1)每开始新的一局时,启动子线程,然后子线程就等待条件变量A,同时主线程睡眠500毫秒,然后广播条件变量,子线程被唤醒,开始显示时间。

       (2)在一个while循环里面,子线程不停的等待条件变量B,每次等待的超时时间为1s,到时后,更新QLCDNumber控件上的时间显示。

       (3)走完一步棋后,主线程广播条件变量B,子线程重置QLCDNumber控件上的时间为步时,这个时候并未退出while循环,又开始等待条件变量B。

       (4)当步时完了或者是游戏结束了仍未等到条件变量时,子线程会退出while循环。

        线程类是StepTimerThread,互斥锁是stepTimeMutex,有两个条件变量,gameStartCond表示新局开始,stepOverCond表示走棋结束。都是MainWindows的成员,线程类实例化时,传入MainWindow的指针作为参数,这样在run方法中就可以通过指针来调用某些函数。每次每次线程调用start方法后,就会进入run方法中去做事情。

       下面是线程run方法的代码:

void StepTimerThread::run()
{
    MainWindow *mainWin = (MainWindow *)threadData;

    mainWin->stepTimeMutex.lock();
    while (mainWin->getStepInterval() == 0)
    {
        mainWin->gameStartCond.wait(&mainWin->stepTimeMutex, 500);
        mainWin->setStepInterval(g_gameSettings.getStepTime());
    }
    mainWin->stepTimeMutex.unlock();
    mainWin->displayStepTime(mainWin->getStepInterval());

    while (!mainWin->isGameOver())
    {
        mainWin->stepTimeMutex.lock();
        while (mainWin->getStepInterval() > 0 && !mainWin->isGameOver())
        {
            if(mainWin->stepOverCond.wait(&mainWin->stepTimeMutex, 1000) == false)
            {
                int interval = mainWin->getStepInterval() - 1;
                mainWin->setStepInterval(interval);
            }
            else
            {
                mainWin->setStepInterval(g_gameSettings.getStepTime());
            }

            mainWin->displayStepTime(mainWin->getStepInterval());
        }
        mainWin->setStepInterval(0);
        mainWin->setGameOver(true);
        mainWin->stepTimeOver();
        mainWin->stepTimeMutex.unlock();
    }
}
         每次新局开始时会调用线程的start方法,主线程也会广播条件变量:

    if (g_gameSettings.getStepTime() > 0)
    {
        timerThread.start();
        usleep(500);
        gameStartCond.wakeAll();
    }
每次走完一步棋也会广播条件变量:

    if (SRC(info.move) > 0 && DST(info.move) > 0)
    {
        chessBoard->loadPixmap(chessHandler->getChessman());
        addToStepList(info);
        if (gameResult == -1 && g_gameSettings.getStepTime() > 0)
        {
            stepOverCond.wakeAll();
        }
    }
       以上就是这个游戏中步时控制的逻辑,这种模式就是完全借鉴的posix多线程编程的模式。posix多线程编程是基础啊,当初学习posix多线程编程还是很值得的。

源代码下载链接:http://download.csdn.net/detail/zxywd/9172917

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值