windows编程(Qt)实现中国象棋——人机对战,网络对战

1. 本程序包含AI思想,具有判断决策功能,但不具有学习功能

2. 本程序借鉴已有程序学习摸索,代码并非完全由我本人自己写出的

3. 本程序实现了:人机对战,网络对战功能

#ifndef STONE_H
#define STONE_H

/*
**棋子头文件
*/

#include <QRect>
#include <QPainter>    //绘制头函数

class Stone            //类声明
{
public:
    Stone();          //构造函数
    ~Stone();		  //析构函数

    enum TYPE{CHE, MA, PAO, BING, JIANG, SHI, XIANG};           //成员元素

    void init(int id);		//初始化函数

    int _row;        //
    int _col;
    TYPE _type;
    bool _dead;
    bool _red;
    int _id;

    QString name();

    void rotate();
};

#endif // STONE_H
#ifndef STEP_H
#define STEP_H


/*
**棋子移动规则
*/

#include <QObject>         //基类

class Step : public QObject
{
    Q_OBJECT
public:
    explicit Step(QObject *parent = 0);     //声明构造函数是显式的
    ~Step();

    int _moveid;		//移动
    int _killid;		//吃子
    int _rowFrom;		//移动开始位置
    int _colFrom;		//移动列位置
    int _rowTo;			//移动到行位置
    int _colTo;			//移动到列位置

signals:				//AI走子

public slots:
};

#endif // STEP_H


#ifndef SINGLEGAME_H
#define SINGLEGAME_H


/*
**电脑判断头文件
*/

#include "Board.h"

class SingleGame : public Board
{
    Q_OBJECT
public:
    SingleGame()
    {
        _level = 6;
    }
    virtual void click(int id, int row, int col);

    Step* getBestMove();
    void getAllPossibleMove(QVector<Step*>& steps);

    void fakeMove(Step* step);
    void unfakeMove(Step* step);
    int calcScore();

    int getMinScore(int level, int curMaxScore);
    int getMaxScore(int level, int curMinScore);

    int _level;

public slots:
    void computerMove();
};

#endif // SINGLEGAME_H


#include "SingleGame.h"
#include <QTimer>

/*
**电脑判断方法
*/

void SingleGame::click(int id, int row, int col)
{
    if(!this->_bRedTurn)
        return;

    Board::click(id, row, col);

    if(!this->_bRedTurn)
    {
        /* 启动0.1秒定时器,在0.1秒后电脑再思考 */
        QTimer::singleShot(100, this, SLOT(computerMove()));

    }
}
void SingleGame::computerMove()
{
    Step* step = getBestMove();
    moveStone(step->_moveid, step->_killid,
              step->_rowTo, step->_colTo);
    delete step;
    update();
}

void SingleGame::getAllPossibleMove(QVector<Step *> &steps)
{
    int min=16, max=32;
    if(this->_bRedTurn)
    {
        min = 0, max = 16;
    }
    for(int i=min; i<max; ++i)
    {
        if(_s[i]._dead) continue;

        for(int row=0; row<=9; ++row)
        {
            for(int col=0; col<=8; ++col)
            {
                int killid = this->getStoneId(row, col);
                if(sameColor(killid, i)) continue;

                if(canMove(i, killid, row, col))
                {
                    saveStep(i, killid, row, col, steps);
                }
            }
        }
    }
}

void SingleGame::fakeMove(Step* step)
{
    killStone(step->_killid);
    moveStone(step->_moveid, step->_rowTo, step->_colTo);
}

void SingleGame::unfakeMove(Step* step)
{
    reliveStone(step->_killid);
    moveStone(step->_moveid, step->_rowFrom, step->_colFrom);
}

/* 评价局面分 */
int SingleGame::calcScore()
{
    int redTotalScore = 0;
    int blackTotalScore = 0;
    //enum TYPE{CHE, MA, PAO, BING, JIANG, SHI, XIANG};
    static int chessScore[] = {100, 50, 50, 20, 1500, 10, 10};

    // 黑棋分的总数 - 红旗分的总数
    for(int i=0; i<16; ++i)
    {
        if(_s[i]._dead) continue;
        redTotalScore += chessScore[_s[i]._type];
    }
    for(int i=16; i<32; ++i)
    {
        if(_s[i]._dead) continue;
        blackTotalScore += chessScore[_s[i]._type];
    }

    return blackTotalScore - redTotalScore;
}

int SingleGame::getMaxScore(int level, int curMinScore)
{
    if(level == 0) return calcScore();

    // 1.看看有那些步骤可以走
    QVector<Step*> steps;
    getAllPossibleMove(steps);   // 是红旗的possiblemove

    int maxScore = -100000;
    while(steps.count())
    {
        Step* step = steps.back();
        steps.removeLast();

        fakeMove(step);
        int score = getMinScore(level-1, maxScore);
        unfakeMove(step);
        delete step;

        if(score >= curMinScore)
        {
            while(steps.count())
            {
                Step* step = steps.back();
                steps.removeLast();
                delete step;
            }
            return score;
        }
        if(score > maxScore)
        {
            maxScore = score;
        }

    }
    return maxScore;
}

int SingleGame::getMinScore(int level, int curMaxScore)
{


    if(level == 0) return calcScore();

    // 1.看看有那些步骤可以走
    QVector<Step*> steps;
    getAllPossibleMove(steps);   // 是红棋的possiblemove

    int minScore = 100000;
    while(steps.count())
    {
        Step* step = steps.back();
        steps.removeLast();

        fakeMove(step);
        int score = getMaxScore(level-1, minScore);
        unfakeMove(step);
        delete step;

        if(score <= curMaxScore)
        {
            while(steps.count())
            {
                Step* step = steps.back();
                steps.removeLast();
                delete step;
            }
            return score;
        }

        if(score < minScore)
        {
            minScore = score;
        }

    }
    return minScore;
}

Step* SingleGame::getBestMove()
{
    /*
        2.试着走一下
        3.评估走的结果
        4.取最好的结果作为参考
    */

    // 1.看看有那些步骤可以走
    QVector<Step*> steps;
    getAllPossibleMove(steps);

    // 2.试着走一下
    // 3.评估走的结果
    int maxScore = -100000;
    Step* ret = NULL;
    while(steps.count())
    {
        Step* step = steps.back();
        steps.removeLast();

        fakeMove(step);
        int score = getMinScore(_level-1, maxScore);
        unfakeMove(step);

        if(score > maxScore)
        {
            maxScore = score;
            if(ret) delete ret;
            ret = step;
        }
        else
        {
            delete step;
        }
    }

    // 4.取最好的结果作为参考
    return ret;
}


评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值