![]() |
#2
flyingcloude2009-11-23 21:16
|

#include <iostream>
#include <ctime>
using namespace std;
#define NULL 0
typedef struct tagNODE
{
bool bOut; //默认为false
int iSize;//牌的大小
int iValue;//牌的值 1-54
char cPai[20]; //棋牌字符
tagNODE * pNext;//后驱指针
}T_NODE;
class CPaiList
{
protected:
T_NODE * m_pHead; //头节点
T_NODE * m_pTail;
public:
CPaiList();
~CPaiList();
bool ADDNODE(char * pszPai , int iSize, int iValue);//创建棋牌
//bool ADDNODE(char * pszPai , int iValue);
bool DELNODE(int iSequence);//删除已出棋牌
void ShowList();
T_NODE * GETNODE();
};
class CPaiShow : public CPaiList
{
public:
// void ADDpai();//随机抽取13颗牌(不算大小花)
void DELpai();//出牌即删牌
bool Steup(int iValue);//设置选择或取消
int ShowPai();//运算是否可出牌
void ShowOuting(); //显示选中将要出的牌
void ShowCate(int iValue);//出牌类型
void InitPai(); //默认一副牌
void TakePai(int arrPai[]);//分牌
void SizePai(int iValue , int & iSize , char * szTmp , char * pszPaiA);//判断牌的大小和牌名
};
CPaiList::CPaiList()
{
m_pHead = NULL;
m_pTail = NULL;
}
CPaiList::~CPaiList()//释放空间
{
T_NODE * pCulNode = m_pHead;
T_NODE * pPreNode;
while (pCulNode)
{
pPreNode = pCulNode->pNext;
delete pCulNode;
pCulNode = pPreNode;
}
}
bool CPaiList::ADDNODE(char * pszPai, int iSize , int iValue)//创建牌
{
T_NODE * pNew = new T_NODE;
if (pNew == NULL)
{
return false;
}
strcpy(pNew->cPai , pszPai);
pNew->iSize = iSize;
pNew->iValue = iValue;
pNew->pNext = NULL;
pNew->bOut = false;
if (m_pHead == NULL)
{
m_pHead = pNew;
}
else
{
m_pTail->pNext = pNew;
}
m_pTail = pNew;
return true;
}
bool CPaiList::DELNODE(int iValue)//删除牌
{
T_NODE * pCulNode = m_pHead;
T_NODE * pPreNode = m_pHead;
while (pCulNode)
{
if (pCulNode->iValue == iValue)
{
if (pCulNode == m_pHead)//当前节点等于头节点
{
m_pHead = pCulNode->pNext;
}
else
{
pPreNode->pNext = pCulNode->pNext;
}
delete pCulNode;
return true;
}
pPreNode = pCulNode;
pCulNode = pCulNode->pNext;
}
return false;
}
void CPaiList::ShowList()
{
T_NODE * pCulNode = m_pHead;
while(pCulNode)
{
cout << pCulNode->cPai << "(" << pCulNode->iValue << ")" << '\t' ;
pCulNode = pCulNode->pNext;
}
}
T_NODE * CPaiList::GETNODE()
{
return m_pHead;
}
#define PAINUMS 54 //54张牌
#define REN 4 //4个人打牌
int CPaiShow::ShowPai()//判断选中的牌是否符合标准
{
T_NODE * pCulNode = m_pHead;
T_NODE * pTwoNode = m_pHead;
int iTmpA = 0 , iTmpB = 0 , iTmpC = 0 , iCount = 0;
while (pCulNode)//用每张牌来判断
{
if (pCulNode->bOut == true)
{
++iCount;//选中的牌数
T_NODE * pPreNode = pCulNode;
while (pPreNode)
{
if (pPreNode->bOut == true && pPreNode != pCulNode)
{
if (pCulNode->iSize == pPreNode->iSize )//判断选中的牌中有几个对子
{
++iTmpA;
}
if (pCulNode->iSize - pPreNode->iSize == 1)//前一张比后一张小1,判断单顺子
{
++iTmpB;
}
if (pTwoNode->iSize != pCulNode->iSize && pCulNode->iSize - pPreNode->iSize == 1)//判断双顺子
{
++iTmpC;
}
}
pPreNode = pPreNode->pNext;
}
}
pTwoNode = pCulNode;
pCulNode = pCulNode->pNext;
}
//-----------------------------------------------
int iTmp = 0;
if (iCount == 1)//单颗
{
iTmp = 1;
}
if (iCount == 2 && iTmpA == 1)//两张一对
{
iTmp = 2;
}
if (iCount == 4 && iTmpA == 3)//三带一
{
iTmp = 3;
}
if (iCount == 4 && iTmpA == 6)//四颗一样的是炸弹
{
iTmp = 4;
}
if (iCount >= 5 && iTmpB + 1 == iCount)//单顺子必须大等于五颗牌
{
iTmp = 5;
}
if (iCount >= 4 && iTmpC + 2 == iCount)//双顺子必须大等于四颗牌
{
iTmp = 6;
}
return iTmp;
}
void CPaiShow::DELpai()
{
T_NODE * pCulNode = m_pHead;
T_NODE * pPreNode;
while (pCulNode)
{
pPreNode = pCulNode->pNext;
if (pCulNode->bOut)
{
DELNODE(pCulNode->iValue);
}
pCulNode = pPreNode;
}
}
bool CPaiShow::Steup(int iValue)//选牌或取消
{
T_NODE * pCulNode = m_pHead;
while (pCulNode)
{
if (pCulNode->iValue == iValue)
{
if (pCulNode->bOut)
{
pCulNode->bOut = false;//如果该牌被选择,则取消
}
else
{
pCulNode->bOut = true;//如果该牌未被选择,则选中
}
return true;
}
pCulNode = pCulNode->pNext;
}
return false;
}
void CPaiShow::ShowOuting()
{
T_NODE * pCulNode = m_pHead;//显示
while (pCulNode)
{
if (pCulNode->bOut == true)
{
cout << "选中的牌有:" << pCulNode->cPai << endl;
}
pCulNode = pCulNode->pNext;
}
}
void CPaiShow::ShowCate(int iValue)
{
if (iValue)
{
cout << "出牌成功" << endl;
switch (iValue)
{
case 1 :
cout << "您出的是单张" << endl;
break;
case 2 :
cout << "您出的是对子" << endl;
break;
case 3 :
cout << "您出的是三带一" << endl;
break;
case 4 :
cout << "您出的是炸弹" << endl;
break;
case 5 :
cout << "您出的是单顺子" << endl;
break;
case 6 :
cout << "您出的是双顺子" << endl;
break;
}
}
else
{
cout << "选牌不对,请重选~" << endl;
}
}
void CPaiShow::InitPai() //默认一副牌打乱数字
{
bool bFlag[PAINUMS] = {0};
int arrPai[PAINUMS];
int iWhile = PAINUMS , iArr = 0 , iPai = 0 ;
srand( time(0) );
while (iWhile)
{
iPai = rand() % PAINUMS + 1;
if (!bFlag[iPai-1])
{
bFlag[iPai-1] = true;
arrPai[iArr] = iPai;
--iWhile;
++iArr;
}
}
TakePai(arrPai);
}
void CPaiShow::TakePai(int arrPai[])//分牌并按顺序插牌
{
char szTmp[10];
char * pszPaiA[] = {"红桃","黑桃","方块","草花"};
int iSize;
int iSets = PAINUMS / 54 * 2;//用总的牌数除一套牌的牌数再加二得大小花的数量
for (int i = 1 ; i <= PAINUMS ; ++i)//所有的牌数减去大小头
{
if (i % 4 == 1)//1代表坐位,如1号坐是1,2号坐是2,3号坐是3,4号坐是4
{
int iPaiA = arrPai[i-1] / 13;
if (iPaiA > 3)//防止下标越界
{
iPaiA = 3;
}
SizePai(arrPai[i-1] , iSize , szTmp , pszPaiA[iPaiA]);
//SizePai(arrPai[i-1] , iSize , szTmp , "草花");
//-----------------------开始排序插牌------------------
int iTmp = 1;
T_NODE * pPreNode = m_pHead;//定义当前节点
T_NODE * pCulNode = m_pHead;//定义尾节点
while (pPreNode)
{
if (iSize > pPreNode->iSize)//做一个循环当牌值大于第一个牌的时候操作并退出
{
T_NODE * pNewNode = new T_NODE;//创建一个新节点
if (pPreNode == m_pHead)//如果当前节点是头节点,则让新节点为头节点
{
m_pHead = pNewNode;
}
else//否则尾节点的后驱指针等于当前节点
{
pCulNode->pNext = pNewNode;
}
pNewNode->pNext = pPreNode;//新节点的后驱指针等于当前节点
strcpy(pNewNode->cPai , szTmp);//将新节点赋值
pNewNode->iValue = arrPai[i-1];
pNewNode->bOut = false;
pNewNode->iSize = iSize;
iTmp = 0;//将临时变量赋0,让它不能创建
break;//退出,这里很重要!
}
pCulNode = pPreNode;
pPreNode = pPreNode->pNext;
}
if (iTmp == 1)
{
ADDNODE(szTmp , iSize , arrPai[i-1]);//添加牌
}
//---------------------插牌结束-----------------------------
}
}
}
void CPaiShow::SizePai(int iValue , int & iSize , char * szTmp , char * pszPaiA)//求牌大小和牌名
{
if (iValue > PAINUMS - PAINUMS / 54 * 2)//一套牌54张,用54减去大小头的数量得剩下的数量
{
for (int i=1; i <= PAINUMS / 54 * 2; ++i)
{
if (i % 2 == 0)
{
strcpy(szTmp , "大花");
iSize = 17;
}
else
{
strcpy(szTmp , "小花");
iSize = 16;
}
}
}
else
{
strcpy(szTmp , pszPaiA);
iSize = iValue % 13;
char szValue[10];
sprintf(szValue , "%d" , iSize);
switch (iSize)
{
case 11:
strcat(szTmp , "J");
break;
case 12:
strcat(szTmp , "Q");
break;
case 0:
iSize = 13;
strcat(szTmp , "K");
break;
case 1:
iSize = 14;
strcat(szTmp , "A");
break;
case 2:
strcat(szTmp , "2");
iSize = 15;
break;
default:
strcat(szTmp , szValue);
}
}
}
int main()
{
int iValue;
char szOut[2];
CPaiShow obj;
obj.InitPai();
obj.ShowList();
while (1)
{
cout << endl;
cout << "请输入您想选择或取消的牌:";
cin >> iValue;
if (obj.Steup(iValue))
{
cout << "操作成功" << endl;
}
else
{
cout << "没有此牌" << endl;
}
obj.ShowOuting();//显示选中的牌。
cout << "按Y键确认出牌,否则请按其他键:";
cin >> szOut;
if (strcmp(szOut , "Y") == 0 || strcmp(szOut , "y") == 0)
{
obj.ShowCate(obj.ShowPai());//显示出牌信息
//---------------------------------------------------------------
obj.DELpai();//删除选中牌
//----------------------------------------------------------------------------------
}
if (obj.GETNODE() == NULL)//如果牌都出光了,就退出游戏
{
cout << "游戏结束" << endl;
break;
}
obj.ShowList();
}
return 0;
}
#include <ctime>
using namespace std;
#define NULL 0
typedef struct tagNODE
{
bool bOut; //默认为false
int iSize;//牌的大小
int iValue;//牌的值 1-54
char cPai[20]; //棋牌字符
tagNODE * pNext;//后驱指针
}T_NODE;
class CPaiList
{
protected:
T_NODE * m_pHead; //头节点
T_NODE * m_pTail;
public:
CPaiList();
~CPaiList();
bool ADDNODE(char * pszPai , int iSize, int iValue);//创建棋牌
//bool ADDNODE(char * pszPai , int iValue);
bool DELNODE(int iSequence);//删除已出棋牌
void ShowList();
T_NODE * GETNODE();
};
class CPaiShow : public CPaiList
{
public:
// void ADDpai();//随机抽取13颗牌(不算大小花)
void DELpai();//出牌即删牌
bool Steup(int iValue);//设置选择或取消
int ShowPai();//运算是否可出牌
void ShowOuting(); //显示选中将要出的牌
void ShowCate(int iValue);//出牌类型
void InitPai(); //默认一副牌
void TakePai(int arrPai[]);//分牌
void SizePai(int iValue , int & iSize , char * szTmp , char * pszPaiA);//判断牌的大小和牌名
};
CPaiList::CPaiList()
{
m_pHead = NULL;
m_pTail = NULL;
}
CPaiList::~CPaiList()//释放空间
{
T_NODE * pCulNode = m_pHead;
T_NODE * pPreNode;
while (pCulNode)
{
pPreNode = pCulNode->pNext;
delete pCulNode;
pCulNode = pPreNode;
}
}
bool CPaiList::ADDNODE(char * pszPai, int iSize , int iValue)//创建牌
{
T_NODE * pNew = new T_NODE;
if (pNew == NULL)
{
return false;
}
strcpy(pNew->cPai , pszPai);
pNew->iSize = iSize;
pNew->iValue = iValue;
pNew->pNext = NULL;
pNew->bOut = false;
if (m_pHead == NULL)
{
m_pHead = pNew;
}
else
{
m_pTail->pNext = pNew;
}
m_pTail = pNew;
return true;
}
bool CPaiList::DELNODE(int iValue)//删除牌
{
T_NODE * pCulNode = m_pHead;
T_NODE * pPreNode = m_pHead;
while (pCulNode)
{
if (pCulNode->iValue == iValue)
{
if (pCulNode == m_pHead)//当前节点等于头节点
{
m_pHead = pCulNode->pNext;
}
else
{
pPreNode->pNext = pCulNode->pNext;
}
delete pCulNode;
return true;
}
pPreNode = pCulNode;
pCulNode = pCulNode->pNext;
}
return false;
}
void CPaiList::ShowList()
{
T_NODE * pCulNode = m_pHead;
while(pCulNode)
{
cout << pCulNode->cPai << "(" << pCulNode->iValue << ")" << '\t' ;
pCulNode = pCulNode->pNext;
}
}
T_NODE * CPaiList::GETNODE()
{
return m_pHead;
}
#define PAINUMS 54 //54张牌
#define REN 4 //4个人打牌
int CPaiShow::ShowPai()//判断选中的牌是否符合标准
{
T_NODE * pCulNode = m_pHead;
T_NODE * pTwoNode = m_pHead;
int iTmpA = 0 , iTmpB = 0 , iTmpC = 0 , iCount = 0;
while (pCulNode)//用每张牌来判断
{
if (pCulNode->bOut == true)
{
++iCount;//选中的牌数
T_NODE * pPreNode = pCulNode;
while (pPreNode)
{
if (pPreNode->bOut == true && pPreNode != pCulNode)
{
if (pCulNode->iSize == pPreNode->iSize )//判断选中的牌中有几个对子
{
++iTmpA;
}
if (pCulNode->iSize - pPreNode->iSize == 1)//前一张比后一张小1,判断单顺子
{
++iTmpB;
}
if (pTwoNode->iSize != pCulNode->iSize && pCulNode->iSize - pPreNode->iSize == 1)//判断双顺子
{
++iTmpC;
}
}
pPreNode = pPreNode->pNext;
}
}
pTwoNode = pCulNode;
pCulNode = pCulNode->pNext;
}
//-----------------------------------------------
int iTmp = 0;
if (iCount == 1)//单颗
{
iTmp = 1;
}
if (iCount == 2 && iTmpA == 1)//两张一对
{
iTmp = 2;
}
if (iCount == 4 && iTmpA == 3)//三带一
{
iTmp = 3;
}
if (iCount == 4 && iTmpA == 6)//四颗一样的是炸弹
{
iTmp = 4;
}
if (iCount >= 5 && iTmpB + 1 == iCount)//单顺子必须大等于五颗牌
{
iTmp = 5;
}
if (iCount >= 4 && iTmpC + 2 == iCount)//双顺子必须大等于四颗牌
{
iTmp = 6;
}
return iTmp;
}
void CPaiShow::DELpai()
{
T_NODE * pCulNode = m_pHead;
T_NODE * pPreNode;
while (pCulNode)
{
pPreNode = pCulNode->pNext;
if (pCulNode->bOut)
{
DELNODE(pCulNode->iValue);
}
pCulNode = pPreNode;
}
}
bool CPaiShow::Steup(int iValue)//选牌或取消
{
T_NODE * pCulNode = m_pHead;
while (pCulNode)
{
if (pCulNode->iValue == iValue)
{
if (pCulNode->bOut)
{
pCulNode->bOut = false;//如果该牌被选择,则取消
}
else
{
pCulNode->bOut = true;//如果该牌未被选择,则选中
}
return true;
}
pCulNode = pCulNode->pNext;
}
return false;
}
void CPaiShow::ShowOuting()
{
T_NODE * pCulNode = m_pHead;//显示
while (pCulNode)
{
if (pCulNode->bOut == true)
{
cout << "选中的牌有:" << pCulNode->cPai << endl;
}
pCulNode = pCulNode->pNext;
}
}
void CPaiShow::ShowCate(int iValue)
{
if (iValue)
{
cout << "出牌成功" << endl;
switch (iValue)
{
case 1 :
cout << "您出的是单张" << endl;
break;
case 2 :
cout << "您出的是对子" << endl;
break;
case 3 :
cout << "您出的是三带一" << endl;
break;
case 4 :
cout << "您出的是炸弹" << endl;
break;
case 5 :
cout << "您出的是单顺子" << endl;
break;
case 6 :
cout << "您出的是双顺子" << endl;
break;
}
}
else
{
cout << "选牌不对,请重选~" << endl;
}
}
void CPaiShow::InitPai() //默认一副牌打乱数字
{
bool bFlag[PAINUMS] = {0};
int arrPai[PAINUMS];
int iWhile = PAINUMS , iArr = 0 , iPai = 0 ;
srand( time(0) );
while (iWhile)
{
iPai = rand() % PAINUMS + 1;
if (!bFlag[iPai-1])
{
bFlag[iPai-1] = true;
arrPai[iArr] = iPai;
--iWhile;
++iArr;
}
}
TakePai(arrPai);
}
void CPaiShow::TakePai(int arrPai[])//分牌并按顺序插牌
{
char szTmp[10];
char * pszPaiA[] = {"红桃","黑桃","方块","草花"};
int iSize;
int iSets = PAINUMS / 54 * 2;//用总的牌数除一套牌的牌数再加二得大小花的数量
for (int i = 1 ; i <= PAINUMS ; ++i)//所有的牌数减去大小头
{
if (i % 4 == 1)//1代表坐位,如1号坐是1,2号坐是2,3号坐是3,4号坐是4
{
int iPaiA = arrPai[i-1] / 13;
if (iPaiA > 3)//防止下标越界
{
iPaiA = 3;
}
SizePai(arrPai[i-1] , iSize , szTmp , pszPaiA[iPaiA]);
//SizePai(arrPai[i-1] , iSize , szTmp , "草花");
//-----------------------开始排序插牌------------------
int iTmp = 1;
T_NODE * pPreNode = m_pHead;//定义当前节点
T_NODE * pCulNode = m_pHead;//定义尾节点
while (pPreNode)
{
if (iSize > pPreNode->iSize)//做一个循环当牌值大于第一个牌的时候操作并退出
{
T_NODE * pNewNode = new T_NODE;//创建一个新节点
if (pPreNode == m_pHead)//如果当前节点是头节点,则让新节点为头节点
{
m_pHead = pNewNode;
}
else//否则尾节点的后驱指针等于当前节点
{
pCulNode->pNext = pNewNode;
}
pNewNode->pNext = pPreNode;//新节点的后驱指针等于当前节点
strcpy(pNewNode->cPai , szTmp);//将新节点赋值
pNewNode->iValue = arrPai[i-1];
pNewNode->bOut = false;
pNewNode->iSize = iSize;
iTmp = 0;//将临时变量赋0,让它不能创建
break;//退出,这里很重要!
}
pCulNode = pPreNode;
pPreNode = pPreNode->pNext;
}
if (iTmp == 1)
{
ADDNODE(szTmp , iSize , arrPai[i-1]);//添加牌
}
//---------------------插牌结束-----------------------------
}
}
}
void CPaiShow::SizePai(int iValue , int & iSize , char * szTmp , char * pszPaiA)//求牌大小和牌名
{
if (iValue > PAINUMS - PAINUMS / 54 * 2)//一套牌54张,用54减去大小头的数量得剩下的数量
{
for (int i=1; i <= PAINUMS / 54 * 2; ++i)
{
if (i % 2 == 0)
{
strcpy(szTmp , "大花");
iSize = 17;
}
else
{
strcpy(szTmp , "小花");
iSize = 16;
}
}
}
else
{
strcpy(szTmp , pszPaiA);
iSize = iValue % 13;
char szValue[10];
sprintf(szValue , "%d" , iSize);
switch (iSize)
{
case 11:
strcat(szTmp , "J");
break;
case 12:
strcat(szTmp , "Q");
break;
case 0:
iSize = 13;
strcat(szTmp , "K");
break;
case 1:
iSize = 14;
strcat(szTmp , "A");
break;
case 2:
strcat(szTmp , "2");
iSize = 15;
break;
default:
strcat(szTmp , szValue);
}
}
}
int main()
{
int iValue;
char szOut[2];
CPaiShow obj;
obj.InitPai();
obj.ShowList();
while (1)
{
cout << endl;
cout << "请输入您想选择或取消的牌:";
cin >> iValue;
if (obj.Steup(iValue))
{
cout << "操作成功" << endl;
}
else
{
cout << "没有此牌" << endl;
}
obj.ShowOuting();//显示选中的牌。
cout << "按Y键确认出牌,否则请按其他键:";
cin >> szOut;
if (strcmp(szOut , "Y") == 0 || strcmp(szOut , "y") == 0)
{
obj.ShowCate(obj.ShowPai());//显示出牌信息
//---------------------------------------------------------------
obj.DELpai();//删除选中牌
//----------------------------------------------------------------------------------
}
if (obj.GETNODE() == NULL)//如果牌都出光了,就退出游戏
{
cout << "游戏结束" << endl;
break;
}
obj.ShowList();
}
return 0;
}