关闭

一步一步实现五子棋3

标签: gdi+五子棋线程
636人阅读 评论(0) 收藏 举报

昨天有面试,五子棋的工作暂停了一下,今天继续。

  前面五子棋的棋盘棋子的绘制以及用鼠标下棋的功能已经实现了,下一步我们的工作就是让电脑一步一步学会如何下棋。首先要教会的是如何判断输赢,我们都知道当相同棋子在横向、纵向和斜对角方向形成五连珠者分出胜负,所以只要扫描整个棋盘发现有五连珠即可判断输赢。当然,扫描整个棋盘的方法笨了点,只关注最后落子的点是否能形成五连珠就可以了,话不多说,上代码:

BOOL Engine::isFive( int x, int y )
{
    int value = 1;
    int i = 0;


    int type = m_chessTable[x][y].type;


    // 横向
    for (i = 1; ((x + i) <= 14) && (m_chessTable[x + i][y].type == type); i++, value++);
    for (i = 1; ((x - i) >= 0)  && (m_chessTable[x - i][y].type == type); i++, value++);


    if (value >= 5)
    {
        return TRUE;
    }


    // 纵向
    value = 1;
    for (i = 1; ((y + i) <= 14) && (m_chessTable[x][y + i].type == type); i++, value++);
    for (i = 1; ((y - i) >= 0)  && (m_chessTable[x][y - i].type == type); i++, value++);


    if (value >= 5)
    {
        return TRUE;
    }


    //西北-东南向
    value = 1;
    for (i = 1; ((x + i) <= 14) && ((y + i) <= 14) && (m_chessTable[x + i][y + i].type == type); i++, value++);
    for (i = 1; ((x - i) >= 0)  && ((y - i) >= 0)  && (m_chessTable[x - i][y - i].type == type); i++, value++);


    if (value >= 5)
    {
        return TRUE;
    }


    // 西南-东北
    value = 1;
    for (i = 1; ((x + i) <= 14) && ((y - i) >= 0)  && (m_chessTable[x + i][y - i].type == type); i++, value++);
    for (i = 1; ((x - i) >= 0)  && ((y + i) <= 14) && (m_chessTable[x - i][y + i].type == type); i++, value++);


    if (value >= 5)
    {
        return TRUE;
    }


    return FALSE;
}

添加其他相关的处理以后电脑就能够判断输赢了,看效果:

  

  教会了判断输赢的规则,下面将渐渐进入重点了——告诉电脑怎么下棋。这个过程是很漫长的,我们慢慢来,先做一些前期的准备工作。

  首先建立一个独立线程,有了这个线程,当对手下棋后,这个线程就开始工作替电脑分析对策,给出指导。

class ThreadAI :
    public ThreadObject
{
public:
    ThreadAI(void);
    ~ThreadAI(void);

     void Run();

      void PushTask(Task* taskPtr);

      Task* PopTask();

private:
    std::vector<Task*> m_taskList;
    Mutex m_taskMutex;
};


  大家可能注意到了线程有两个成员m_taskList和m_taskMutex。m_taskList用来缓存任务,比如当对手落子后,主线程就会生成一个任务,加入到m_taskList中,告诉电脑“家已经下了,轮到你小子了”,电脑就会通过线程来处理这些任务。这是线程间通讯的一种很常用的方式。m_taskMutex看名字就知道是用来进行线程间同步的。这里的线程类和同步量对象都是经过封装的类,不是C++标准库里的,如果直接拷贝代码去编译肯定编译不过的。下面是run()的实现:

void ThreadAI::Run()
{
    Task *taskPtr = NULL;
    while (!IsBreak())
    {
        taskPtr = PopTask();
        if (taskPtr != NULL)
        {
            taskPtr->Run();
            delete taskPtr;
            taskPtr = NULL;
        }

        Wait(100);
    }
}

  时间过得真快,一下子就到了吃饭时间了,下午我重点研究下五子棋局面评估算法。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:5036次
    • 积分:118
    • 等级:
    • 排名:千里之外
    • 原创:6篇
    • 转载:0篇
    • 译文:0篇
    • 评论:2条
    文章存档
    最新评论