斗地主项目总结

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

斗地主项目总结

一,设计过程

1,由于我没有玩过斗地主,设计初期,没有一点思路。先写了一个界面,完成了洗牌,分牌,出牌功能。

牌值数组:i nt Pai[54] = {1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,6,6,6,6,

7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10,11,11,11,11,12,12,12,12,13,13,13,13,14,15};

在程序内部,操作的是1-15之间的牌值。之后在显示的时候才通过转换函数:

char paiChange (int n)将其转换为‘J’‘Q’之类的字符,并显示到屏幕上。

并通过一个保存三个玩家牌值数组名的指针数组实现三人轮流出牌:

int *WanJia[] = {JiaPai, YiPai, BingPai};//玩家名称数组

while(1)

{

…………………………………………..

// DoPai为出牌函数

if(DoPai (WanJia[i % 3], WanJiaPaiShu[i % 3], i % 3, &ComPai, nBool))

{

break;

}

nPaiAay[i % 3] = ComPai;

i++;

}这样就实现了三人轮流出牌。

然后,用一个临时数组保存玩家出的牌:

for (i = 0; ZhuoMian[i]; i++);//找到最后一个位置

ZhuoMian[i] = ary[nPaiIndex - 1];//从玩家牌值数组中拷贝

ZhuoMianCount ++;//临时数组长度加1

ary[nPaiIndex - 1] = 30;//把玩家牌值数组中相应的牌值赋为30

(*nCount) --;//把玩家牌值数组长度减1

…………………………………………..

关键:每次操作后,都要进行排序

2,增加了判定牌型的函数。

int ComparePai (int ZhuoMian[], int ZhuoMianCount, char **cPaiType);

完成单牌,对子,三张,顺子,双顺子,三顺子,三带一. . . . . .等的判定。

难点:牌之间的比较。

起初是直接用两个玩家的牌进行比较,后来发现这样很容易出错。重写了。

后来,我想到了为每个牌型规定一定比较数,这个数的结构是这样的:

例:三带一的比较数都是300开始的。‘8、8、8、4’的比较数是306.

最高位是权限位,后面的是用于比较大小的牌面值。在比较的时候,通过

//实现权限比对,10 ~ 10000之间的权限一样,10000以上的权限最高

//例如:103可以和106比较,但是禁止和504比较,10000以上的可以通吃

if ((nCompZM > *ComPai && nCompZM / 100 == *ComPai / 100 &&

nCompZM > 100)|| nCompZM / 10000 > *ComPai / 10000 ||

(*ComPai == 0 && nCompZM >100))

进行比较。

然后个玩家出牌后,都调用比较函数ComparePai进行比较,并且返回一个比较数,如果比上家大,就和上家的比较数进行交换,大不过,就保持不变。这样就实现了牌的比较。

3,增加了出完牌后,两家都不要的处理方式。

思路是:用一个三元素数组保存三个玩家出牌后,返回的比较数。如果三次都不变,就让第一个出牌的人,继续条件出牌(不用继续比较)。

具体实现:int nPaiAay[3] = {0};

nPaiAay[i % 3] = ComPai;

if (i >= j) //实现其余两家不要,本家继续随便出牌

{

for (j = i; j - i < 3; j++)

{

if (nPaiAay[j % 3] != nPaiAay[j % 3 +1] || nPaiAay[j % 3] == 10)

{

break;

}

}

if (j - i >= 3 && ComPai != 0 )

{

ComPai = 0;

}

}

4,增加了对输入错误和Pass等的判定功能。

难点:由于我用的是动态出牌,也就是输入牌值对应的下标后,相应的牌就会从数组中消失(其实不是消失,只是没赋值为30,数组长度减1)。

于是在输入错误之后,要把牌重新返回到玩家手中。

for (i = 0; ZhuoMian[i]; i++)

{

(*nCount) ++;//现把数组长度加一

ary[(*nCount) - 1] = ZhuoMian[i]; //把牌重新拷贝回去

}

以上:初期设计大体结束。

二,AI设计

1,牌面分析

由于原计划没有想过弄这个东西,后来时间比较充足就搞了。所以没有什么计划,想到一点写一点。结构也比较乱,代码比较长。

思路是:在机器人出牌之前,现把它手中的牌进行分析,把结果保存到一个结构体中,然后根据上家出牌返回的比较数,来选择其要出的牌。

首先写了一个用于保存牌面分析结果的结构体:

牌型大体分为,单牌,对子,三张,顺子,双顺子,炸弹,对王。

通过以上牌型的组合,可实现斗地主中所有的牌型。

typedef struct

{

DANPAI danpai[20];//单牌

DUIZI duizi[10];//对子

SANBUDAI sanbudai[7];//以下略。。。

ZHADAN zhadan[4];

WUSHUNZI wushunzi[5];

LIUSHUNZI liushunzi[6];

QISHUNZI qishunzi[7];

DUIW ANG duiwang[1];

SANDAIYI sandaiyi;

SANDAIER sandaier;

SIDAIER sidaier;

SANSHUANGSHUNZI sanshuangshunzi[3];

SISHUANGSHUNZI sishuangshunzi[2];

BASHUNZI bashunzi[2];

JIUSHUNZI jiushunzi[2];

}PAIXING;

然后开始写牌面分析函数

//AI判断对子

int AnalyseDUIZI (PAIXING *paixing, int PaiDemo[], int *PaiCount);

//AI判断顺子

int AnalyseSHUNZI (PAIXING *paixing, int PaiDemo[], int *PaiCount, int n);

//AI判断三张

int AnalyseSANZHANG (PAIXING *paixing, int PaiDemo[], int *PaiCount);

//AI判断炸弹

int AnalyseZHADAN (PAIXING *paixing, int PaiDemo[], int *PaiCount);

//AI判断单牌

int AnalyseDANPAI (PAIXING *paixing, int PaiDemo[], int *PaiCount);

相关文档
最新文档