2013-02-14 wcdj 大年初五,情人节
过年和家人玩扑克牌斗牛游戏(地道的发音是 Dou Ou),规则很简单,每个人发五张牌,如果三张牌之和是10,20或30则称为一个牛(Ou),其余两张牌相加之和模10,若没有牛则选最大的一张牌进行大小点比较,若大小点一样则再比较黑红梅方,玩家人数不限,一个人做庄,然后拿点零花钱,后面就看各自的运气了。
抽空将此游戏简单用代码实现了下,一些地方还可以优化。
// 2013-02-14 wcdj
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <vector>
#include <map>
#include <time.h>
using namespace std;
// 每人总共发5张牌
#define PK_NUM 5
// 扑克牌总共40张, 1到10, 黑红梅方
#define PK_TOTAL_NUM 40
const string pk[PK_TOTAL_NUM] = {
"1d","1c","1b","1a",
"2d","2c","2b","2a",
"3d","3c","3b","3a",
"4d","4c","4b","4a",
"5d","5c","5b","5a",
"6d","6c","6b","6a",
"7d","7c","7b","7a",
"8d","8c","8b","8a",
"9d","9c","9b","9a",
"10d","10c","10b","10a", };
const string pk_des[PK_TOTAL_NUM] = {
"黑桃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" };
typedef struct st_Player {
// 玩家名字
char szName[64];
// 玩家是否是庄家
bool bIsMasterPlayer;
// 玩家的游戏币数量
int iCoins;
// 玩家随机选取的扑克
string strPKList[PK_NUM];
// 玩家赢的次数
int iWinNum;
// 玩家输的次数
int iLoseNum;
// 最大扑克
int iMaxPK;
string strMaxPK;
string strMaxPKDes;
} stPlayer;
// 玩家的数量
int iPlayerNum = 0;
// 庄家只能有一个
bool bHasChoosedMasterPlayer = false;
// 玩家列表
vector<stPlayer> vecPlayer;
// 随机选牌用
string pk_bak[PK_TOTAL_NUM];
int iChoosed = 0;
// 扑克描述map
map<string, string> mapPK;
int PrintPlayerInfo(stPlayer &player)
{
if (player.bIsMasterPlayer)
printf("庄家【%s】:赢【%d】输【%d】剩余游戏币【%d】\n",
player.szName, player.iWinNum, player.iLoseNum, player.iCoins);
else
printf("玩家【%s】:赢【%d】输【%d】剩余游戏币【%d】\n",
player.szName, player.iWinNum, player.iLoseNum, player.iCoins);
printf("本局抽中的扑克:【");
for (int i = 0; i != PK_NUM; ++i)
{
if (i == PK_NUM-1)
printf("%s】", mapPK[player.strPKList[i]].c_str());
else
printf("%s\t", mapPK[player.strPKList[i]].c_str());
}
return 0;
}
int RandChoosePK(stPlayer &player)
{
for(int i = 0; i != PK_NUM; ++i, ++iChoosed)
{
// 要剔除已经选过的扑克
int r = rand() % (PK_TOTAL_NUM - iChoosed);
// 保存选出的扑克
player.strPKList[i] = pk_bak[r];
// 把最后一个元素提到选中的那个元素的位置, 为了效率不改变原数组的顺序
pk_bak[r] = pk_bak[PK_TOTAL_NUM - iChoosed - 1];
}
return 0;
}
int InitPlayerInfo(int idx, stPlayer &player)
{
printf("\n\n输入玩家%d的名字:", idx);
scanf("%s", player.szName);
player.bIsMasterPlayer = false;
if (bHasChoosedMasterPlayer == false)
{
printf("请选择是否当庄家? y/n:");
char szInput[64] = {0};
scanf("%s", szInput);
if (0 == strcmp(szInput, "y")) {
player.bIsMasterPlayer = true;
bHasChoosedMasterPlayer = true;
}
else
player.bIsMasterPlayer = false;
}
printf("请【%s】输入要下注的游戏币数量:", player.szName);
scanf("%d", &player.iCoins);
player.iWinNum = 0;
player.iLoseNum = 0;
player.iMaxPK = 0;
// 开始发牌
RandChoosePK(player);
PrintPlayerInfo(player);
return 0;
}
// 计算是否有牛, 有牛的规则是三张牌加起来等于10/20/30即可
int CalcNiu(stPlayer &player)
{
// C(3,5)==10, 即三张牌有10种组合情况
if ( (atoi(player.strPKList[0].c_str())+atoi(player.strPKList[1].c_str())+atoi(player.strPKList[2].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[3].c_str())+atoi(player.strPKList[4].c_str()))%10,
mapPK[player.strPKList[3]].c_str(), mapPK[player.strPKList[4]].c_str(),
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[2]].c_str());
}
else if ( (atoi(player.strPKList[0].c_str())+atoi(player.strPKList[1].c_str())+atoi(player.strPKList[3].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[2].c_str())+atoi(player.strPKList[4].c_str()))%10,
mapPK[player.strPKList[2]].c_str(), mapPK[player.strPKList[4]].c_str(),
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[3]].c_str());
}
else if ( (atoi(player.strPKList[0].c_str())+atoi(player.strPKList[1].c_str())+atoi(player.strPKList[4].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[2].c_str())+atoi(player.strPKList[3].c_str()))%10,
mapPK[player.strPKList[2]].c_str(), mapPK[player.strPKList[3]].c_str(),
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[4]].c_str());
}
else if ( (atoi(player.strPKList[0].c_str())+atoi(player.strPKList[2].c_str())+atoi(player.strPKList[3].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[1].c_str())+atoi(player.strPKList[4].c_str()))%10,
mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[4]].c_str(),
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[2]].c_str(), mapPK[player.strPKList[3]].c_str());
}
else if ( (atoi(player.strPKList[0].c_str())+atoi(player.strPKList[2].c_str())+atoi(player.strPKList[4].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[1].c_str())+atoi(player.strPKList[3].c_str()))%10,
mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[3]].c_str(),
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[2]].c_str(), mapPK[player.strPKList[4]].c_str());
}
else if ( (atoi(player.strPKList[1].c_str())+atoi(player.strPKList[2].c_str())+atoi(player.strPKList[3].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[0].c_str())+atoi(player.strPKList[4].c_str()))%10,
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[4]].c_str(),
mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[2]].c_str(), mapPK[player.strPKList[3]].c_str());
}
else if ( (atoi(player.strPKList[1].c_str())+atoi(player.strPKList[2].c_str())+atoi(player.strPKList[4].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[0].c_str())+atoi(player.strPKList[3].c_str()))%10,
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[3]].c_str(),
mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[2]].c_str(), mapPK[player.strPKList[4]].c_str());
}
else if ( (atoi(player.strPKList[1].c_str())+atoi(player.strPKList[3].c_str())+atoi(player.strPKList[4].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[0].c_str())+atoi(player.strPKList[2].c_str()))%10,
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[2]].c_str(),
mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[3]].c_str(), mapPK[player.strPKList[4]].c_str());
}
else if ( (atoi(player.strPKList[2].c_str())+atoi(player.strPKList[3].c_str())+atoi(player.strPKList[4].c_str())) % 10 == 0 )
{
printf("牛%d【%s\t%s】【%s\t%s\t%s】\n",
(atoi(player.strPKList[0].c_str())+atoi(player.strPKList[1].c_str()))%10,
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[1]].c_str(),
mapPK[player.strPKList[2]].c_str(), mapPK[player.strPKList[3]].c_str(), mapPK[player.strPKList[4]].c_str());
}
else
{
// 无牛, 则计算最大的扑克点数
for (int i = 0; i != PK_NUM; ++i)
{
if (atoi(player.strPKList[i].c_str()) > player.iMaxPK)
{
player.strMaxPK = player.strPKList[i];
player.strMaxPKDes = mapPK[player.strPKList[i]];
player.iMaxPK = atoi(player.strPKList[i].c_str());
}
// 如果点数一样大还要比较黑红梅方, 比如10a和10b
else if (atoi(player.strPKList[i].c_str()) == player.iMaxPK
&& strcmp(player.strPKList[i].c_str(), player.strMaxPK.c_str()) > 0)
{
player.strMaxPK = player.strPKList[i];
player.strMaxPKDes = mapPK[player.strPKList[i]];
player.iMaxPK = atoi(player.strPKList[i].c_str());
}
}
printf("无牛, 最大牌为【%s】【%s\t%s\t%s\t%s\t%s】\n",
player.strMaxPKDes.c_str(),
mapPK[player.strPKList[0]].c_str(), mapPK[player.strPKList[1]].c_str(), mapPK[player.strPKList[2]].c_str(),
mapPK[player.strPKList[3]].c_str(), mapPK[player.strPKList[4]].c_str());
}
return 0;
}
int main()
{
// 初始化相关参数
time_t rawtime;
struct tm * timeinfo;
time(&rawtime);
timeinfo = localtime(&rawtime);
printf("当前时间:%s", asctime(timeinfo));
srand((unsigned int)time(0));
printf("请输入玩家个数:");
scanf("%d", &iPlayerNum);
printf("当前玩家个数为:%d\n", iPlayerNum);
// 游戏开始,
char szGoOn[64] = "y";
while (0 == strcmp(szGoOn, "y"))
{
// 重置选牌范围
iChoosed = 0;
// 重置玩家信息
vecPlayer.clear();
// 重选庄家
bHasChoosedMasterPlayer = false;
// 重置扑克
for(int i = 0; i != PK_TOTAL_NUM; ++i)
{
// 随机选牌使用
pk_bak[i] = pk[i];
// 扑克描述
mapPK[pk[i]] = pk_des[i];
}
// 随机选牌
for (int i = 0; i != iPlayerNum; ++i)
{
stPlayer player;
InitPlayerInfo(i+1, player);
vecPlayer.push_back(player);
}
// 必须有一个庄家, 没有则重选
if (!bHasChoosedMasterPlayer)
{
printf("\n\n对不起, 游戏中必须有一个庄家, 游戏重新开始\n");
continue;
}
printf("\n\n-----------------------------------------------------\n");
// 开始斗牛, 计算每个玩家最大的牌
vector<stPlayer>::iterator iter = vecPlayer.begin();
for (; iter != vecPlayer.end(); ++iter)
{
if (iter->bIsMasterPlayer)
printf("庄家【%s】:", iter->szName);
else
printf("玩家【%s】:", iter->szName);
CalcNiu(*iter);
}
printf("-----------------------------------------------------\n");
printf("\n\n是否进行下一局呢? y/n:");
scanf("%s", szGoOn);
}
// Game Over
printf("斗牛游戏结束\n");
system("pause");
return 0;
}
上面代码使用CodeBlocks编译成功。
Code::Blocks下载地址:
http://www.codeblocks.org/downloads/binaries

这篇博客记录了作者在春节期间与家人玩扑克牌斗牛游戏的体验,并简单介绍了游戏规则。作者还分享了自己利用代码实现斗牛游戏的过程,提到了代码仍有优化空间。
443





