关闭

斗地主AI算法——第二章の数据结构

标签: C++算法ai斗地主棋牌算法
5176人阅读 评论(0) 收藏 举报
分类:


上一章我们已经确立了基本的业务逻辑处理流程。从本章开始,我们便进入开发阶段。

首先就是明确我们都需要哪些数据,且它们以怎样的形式存储。


首先从上一章反复提到的手牌权值结构说起,也就是F()的返回值,他包含了两个成员,①手牌总价值②需要打几手牌。

//手牌权值结构
struct HandCardValue
{
	int SumValue;        //手牌总价值
	int NeedRound;       // 需要打几手牌
};

这个不难理解吧,我们出牌的时候总是希望把牌划分成手数少且相对价值又大的组合方式,比如说AKQJ10,虽然都挺大,但你总不见得故意拆开出吧。


接下来就是组合牌型的数据结构,就算是上一章G()的返回值吧,因为G()主要返回的就是一个组合牌结构及出牌的序列

//牌型组合数据结构
struct CardGroupData
{
	//枚举类型
	CardGroupType cgType=cgERROR;
	//该牌的价值
	int  nValue=0;
	//含牌的个数
	int  nCount=0;
	//牌中决定大小的牌值,用于对比
	int nMaxCard=0;

};

说明一下nMaxCard,比如说99,他的nMaxCard就是9,比如说33366,他的nMaxCard就是3。被动出牌规则便是通过这个值进行判断是否可以出牌。

cgType是所有牌型的枚举,具体定义为:

//手牌组合枚举
enum CardGroupType
{ 
	cgERROR = -1,						            //错误类型
	cgZERO = 0,						                //不出类型
    cgSINGLE = 1,									//单牌类型
    cgDOUBLE = 2,									//对牌类型
    cgTHREE	= 3,									//三条类型
    cgSINGLE_LINE = 4,								//单连类型
    cgDOUBLE_LINE = 5,								//对连类型
    cgTHREE_LINE = 6,								//三连类型
    cgTHREE_TAKE_ONE = 7,							//三带一单
    cgTHREE_TAKE_TWO = 8,							//三带一对
	cgTHREE_TAKE_ONE_LINE = 9,						//三带一单连
	cgTHREE_TAKE_TWO_LINE = 10,						//三带一对连
    cgFOUR_TAKE_ONE	= 11,							//四带两单
    cgFOUR_TAKE_TWO	= 12,							//四带两对
    cgBOMB_CARD	= 13,							    //炸弹类型
    cgKING_CARD	= 14								//王炸类型
};

接下来便是两个主要的类,首先是游戏全局类,主要用于储存当前游戏的发展情况

//游戏全局类
class GameSituation 
{
public:
	//构造函数
	GameSituation::GameSituation()
	{
	}
	//析构函数
	virtual GameSituation::~GameSituation()
	{
	}

public:


	//地主玩家
	int nDiZhuID = -1;
	//本局叫分
	int nLandScore = 0;

	//当前地主玩家——还未确定
	int nNowDiZhuID = -1;
	//当前本局叫分——还未确定
	int nNowLandScore = 0;

	//三张底牌
	int DiPai[3] = { 0 };
	//已经打出的牌——状态记录,便于一些计算,值域为该index牌对应的数量0~4
	int value_aAllOutCardList[18] = { 0 };
	//三名玩家已经打出的手牌记录
	int value_aUnitOutCardList[3][18] = { 0 };
	//三名玩家已经剩余手牌个数
	int value_aUnitHandCardCount[3] = { 0 };
	//本局当前底分倍数
	int nMultiple = 0;
	//当前控手对象(用于区分是否可以自身任意出牌以及是否地主已经放弃出牌从而不去管队友)
	int nCardDroit = 0;
	//当前打出牌的类型数据,被动出牌时玩家根据这里做出筛选
	CardGroupData uctNowCardGroup;
	//本局游戏是否结束
	bool Over = false;


};

然后是自身手牌的数据类,这里重点说明的是手牌序列相关,大家可以看到,类成员里定义了很多,感觉蛮晕的。

首先,在我们出牌逻辑中,是没有花色的概念的,即我们后续所有的逻辑计算只需要考虑当前手牌权值部分即可,所以定义了vector <int> value_nHandCardList手牌序列

当我们要反馈出牌情况时,再根据返回的无花色出牌序列映射到自己有花色的手牌序列中,再返回有花色的出牌序列。这些下一章会给出实现方法。

而无花色value手牌序列为了便于计算又设立了状态记录的数组int value_aHandCardList[18]。因为后续算法肯定需要大量通过回溯法深度遍历出牌策略的操作。

这个在后续的算法里会看到,也就是说,当程序在做出牌逻辑计算时,受影响的是int value_aHandCardList[18],当然最终都会回溯到原点。当确定好了出牌的序列,返回无花色出牌序列vector <int> value_nPutCardList。最后通过处理无花色出牌序列,改变其他数组的值。

//手牌数据类
class HandCardData
{


public:
	//构造函数
	HandCardData::HandCardData()
	{
	}
	//析构函数
	virtual HandCardData::~HandCardData()
	{
	}

public:
	  //手牌序列——无花色,值域3~17
    vector <int> value_nHandCardList;

	  //手牌序列——状态记录,便于一些计算,值域为该index牌对应的数量0~4
	int value_aHandCardList[18] = { 0 };

	  //手牌序列——有花色,按照从大到小的排列  56,52:大王小王……4~0:红3黑3方3花3
	vector <int> color_nHandCardList;
	  //手牌个数
	int nHandCardCount = 17 ;
	  //玩家角色地位       0:地主    1:农民——地主下家   2:农民——地主上家
	int nGameRole = -1;
	  //玩家座位ID 
	int nOwnIndex = -1;
	//玩家要打出去的牌类型
	CardGroupData uctPutCardType;
	//要打出去的牌——无花色
	vector <int> value_nPutCardList;
	//要打出去的牌——有花色
	vector <int> color_nPutCardList;

	HandCardValue uctHandCardValue;


};


最后定义一些极限值

//最多手牌
#define HandCardMaxLen 20
//价值最小值
#define MinCardsValue -25
//价值最大值
#define MaxCardsValue 106


那么目前所需要的数据基本制定完毕,接下来是手牌中类成员函数的实现方法。


敬请关注下一章:斗地主AI算法——第三章の数据处理




2
1
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

斗地主AI算法——第一章の业务逻辑

转眼间快到了五月,帝都的天气也变的非常梦幻。 时而酷暑炎热,时而狂风席卷。 而不管外面如何,我们也只能在办公室里茕茕无依的撸着代码,无可奈何的负着韶华。 世界是寂寞的,寂寞到不只是寂寞,而是死一般的寂...
  • sm9sun
  • sm9sun
  • 2017-04-26 15:27
  • 7734

斗地主AI算法实现 一(拆牌)

源代码下载                   ps: 前面已经写了几篇地主游戏的基本算法实现,今天来讲讲单...
  • pql925
  • pql925
  • 2016-05-23 19:42
  • 4917

斗地主AI算法——第三章の数据处理

上一章我们定义了基本的数据结构,相信大家看到手牌类里面那么多出牌序列时一定会比较愤慨。。。 其实一开始写的时候我也是觉得很脑残,不过后续开发证明了这样的结构还是可以的,因为只要我封装了一层数据转换,...
  • sm9sun
  • sm9sun
  • 2017-04-26 16:53
  • 2983

数据结构课程设计——斗地主代码

  • 2011-03-03 15:05
  • 3.08MB
  • 下载

斗地主AI算法——第五章の总值计算

本章算是比较重点的一章,前一章已经对各个牌型做出了价值定义,本章主要实现计算手牌总价值模块函数。 根据之前的思路,我们设定一下输入输出: 输入:手牌数据类(主要用手牌个数nHandCardCount以...
  • sm9sun
  • sm9sun
  • 2017-04-26 19:48
  • 2594

斗地主AI算法——第四章の权值定义

第一章业务逻辑结尾部分我提到了权值的计算方法: ①每个单牌都有一个基础价值②组合牌型的整体价值与这个基础价值有关,但显然计算规则不完全一样。③整手牌可以分成若干个组合牌,但分法不唯一。 当时,我说了...
  • sm9sun
  • sm9sun
  • 2017-04-26 18:04
  • 3055

斗地主AI算法——第十五章の测试模块

前面已经完成了整个工程大部分模块,接下来进入整合联调以及模拟测试模块。 测试模块主要任务就是代替服务器给出我们需要的数据。因为我们本来的计划是封装成类库通过服务器调用获取,其调用的接口无非就是叫分、被...
  • sm9sun
  • sm9sun
  • 2017-04-27 17:48
  • 1856

斗地主AI算法——第十三章の主动出牌(2)

上一章我们已经搭好了出牌算法的基本框架,本章主要实现优先处理的三带、飞机等牌型。 首先定义一些基本变量: //暂存最佳的价值 HandCardValue BestHandCardValue; B...
  • sm9sun
  • sm9sun
  • 2017-04-27 16:26
  • 1933

斗地主AI算法——第十章の被动出牌(4)

上一章已经说明了单顺的实现方法,双顺、三不带顺牌型实现方法与单牌基本类似。改动的地方除了上一章说的枚举牌类型,出牌时value_nPutCardList的处理,回溯时value_aHandCardLi...
  • sm9sun
  • sm9sun
  • 2017-04-27 14:41
  • 1873

斗地主AI算法——第八章の被动出牌(2)

上一章我们已经搭好了被动出牌的基本架子,本章我们主要解决面对不同牌型分支的出牌策略问题。 在这里我把出牌逻辑分为四个阶段,也就是策略的优先级。分别是:【直接打光手牌】→【同类型牌压制】→【炸弹王炸压制...
  • sm9sun
  • sm9sun
  • 2017-04-27 11:13
  • 2171
    个人资料
    • 访问:157139次
    • 积分:3297
    • 等级:
    • 排名:第11941名
    • 原创:166篇
    • 转载:2篇
    • 译文:0篇
    • 评论:36条
    博客专栏
    文章分类
    最新评论