优化后的斗地主~自己写的~
程序代码:
#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; }