扑克牌游戏程序设计报告_第1页
扑克牌游戏程序设计报告_第2页
扑克牌游戏程序设计报告_第3页
扑克牌游戏程序设计报告_第4页
扑克牌游戏程序设计报告_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

湖南科技大学游戏程序设计报告游戏名称: 扑克牌游戏指导教师: 陈 林 书专业班级: 网络工程 班学 号: 0905020114姓 名: 刘隆乾程序名称:扑克牌游戏程序功能简介:1)创建一副扑克牌,可根据需要选择有大小王或者没有大小王的扑克牌。2)根据需要输入参与扑克牌游戏的人数。3)重新初始化整副扑克牌,清除所有打牌者的扑克牌,并显示。4)洗牌,并显示。5)发牌,并显示。6)去掉一张最上面的扑克牌,并显示7)清除所有打牌者的扑克牌,并显示。8)显示没有发出的扑克牌的情况。9)显示所有打牌者的扑克牌的情况。PS黑体字为自行增加的功能。对增加模块设计的分析及注解:由于对原代码很多地方觉得难以理解,且原代码有的地方用的是硬代码,所以新编写的程序只有洗牌的思路是按原代码的思路编写的,但还是改成了栈(Stack)的运行方式。这个程序的编写是充分利用C+的面向对象的特性来写的,封装性、隐蔽性、多态性等等都有很好体现,可以说,这个程序除了没有用继承性,其他都用到了。Class的本身就具有封装性和隐蔽性 ,模板类就是多态性的类型参数多态性。void InitMainMenu()void Menu1(int playernum);void Menu2(int playernum);int MainMenuSelect;MainMenuSelect = 1;docout endl;cout endl;cout *主菜单* endl;cout 1.有大小王的扑克牌(54张) endl;cout 2.无大小王的扑克牌(52张) endl;cout 3.退出本系统 endl;cout 请选择1-3 endl;cout * endl;cout 您的选择为: ;MainMenuSelect = GetInt(1, 3);cout endl;cout endl;switch (MainMenuSelect)case 1:cout 输入打牌人数: ;Menu1(GetInt(1, 9);break;case 2:cout 输入打牌人数: ;Menu2(GetInt(1, 9);break;while (MainMenuSelect != 3);程序运行后先选择是否需要有大小王的扑克牌。接着输入参加扑克牌游戏的人数。之所以想到将程序设计成可以选择参加扑克牌游戏的人数,是因为一开始设计程序时为了简单起见,使每个游戏参与者的扑克牌数都相同,这样就导致选择有大小王的扑克牌时(54张)就是三个人参加游戏,而选择没有大小王的扑克牌时(52张)就是四个人参加游戏。这样的设计是非常牵强的,好像在逃避将程序完善的任务,为了更好的解决这个问题,特将程序改为游戏参与者人数可以人为自由设置。人数设定的任意性是通过动态创建指针性数组来实现的。而添加7)、8)、9)功能都只是为了使得程序更加透明化,易于使用者清晰、明了程序的运行过程。以有大小王的扑克牌为例:void Menu1(int playernum)Deck dk54(54, playernum);/有大小王,共54张int MenuSelect;MenuSelect = 1;cout endl;cout endl;dk54.MakeDeck();dk54.ShowDeck();docout endl;cout endl;cout *54张* endl;cout 1.重新初始化整副牌,清除所有 endl;cout 打牌者的牌,并显示 endl;cout 2.洗牌,并显示 endl;cout 3.发牌,并显示 endl;cout 4.去掉一张最上面的牌,并显示 endl;cout 5.清除所有打牌者的牌,并显示 endl;cout 6.显示没有发出的牌的情况 endl;cout 7.显示所有打牌者的牌的情况 endl;cout 8.退出本级菜单 endl;cout 请选择1-8 endl;cout * endl;cout 您的选择为: ;MenuSelect = GetInt(1, 8);cout endl;cout endl;switch (MenuSelect)case 1:dk54.MakeDeck();/重新初始化整副牌,清除所有打牌者的牌dk54.ShowDeck();/显示break;case 2:dk54.ShuffleDeck(100);/洗100次牌dk54.ShowDeck();/显示break;case 3:dk54.SendDeck();/发牌dk54.ShowDeckOfPlayer();/显示所有打牌者的牌break;case 4:dk54.SendTopPoker();/去掉一张最上面的牌dk54.ShowDeck();/显示break;case 5:dk54.ClearAllPokersOfAllPlayers();/清除所有打牌者的牌dk54.ShowDeckOfPlayer();/显示所有打牌者的牌break;case 6:dk54.ShowDeck();/显示没有发出的牌的情况break;case 7:dk54.ShowDeckOfPlayer();/显示所有打牌者的牌的情况break;while(MenuSelect != 8);/ MenuSelect = 8时退出此级菜单大小王和普通牌都是Poker类,Tag是标志,可以根据Tag来区别是没有赋值的牌,还是王牌,还是一般的牌。NONE 表示没有赋值的扑克牌。COMM0N表示一般的牌,SPECIAL表示大小王牌。Suit也是标志,可以根据Suit来区别扑克牌的花色。SPADE表示黑桃,HEART表示红心,CLUB表示梅花,DIAMOND表示方块。Face同样也是标志,分别表示扑克牌的数字,从A到K。class Poker public:bool IsNone();void Clear();Poker &operator =(const Poker &pk);void MakeCard(int number);void ShowCard() const;Poker(const Poker &P);Poker();virtual Poker();private: enum CardTagNONE = 0, COMMON, SPECIAL;/扑克牌的类型:NONE:空COMM0N:一般的牌,SPECIAL:大小王enum SuitSPADE = 1, HEART, CLUB, DIAMOND;/扑克牌的花色(黑桃、红心、梅花、方块)enum FaceFA = 1, F2, F3, F4, F5, F6, F7, F8, F9, F10, FJ, FQ, FK;/扑克牌的数字(从A到K)enum JokerBigJoker = 14, SmallJoker = 15;CardTag m_CardTag;unionstructSuit m_Suit;Face m_Face; CommonCard;structJoker m_Joker; SpecialCard; m_Card; 主要问题及解决方法:主要问题一:如何唯一标志牌的属性。解决方法:这个程序用的是union联合型数据结构。虽然union联合型数据结构和struct差不多,而且一开始编写时用的就是struct,但后来通过查阅大量资料,觉得还是选用union联合型数据结构更为合理。因为union联合型数据结构中的所有变量成员,都是共用一个内存空间的。例如,union Aint i; float f; double d; A类型的结构,变量i、f、d共用一个内存地址,在某一时刻只能有一个变量有效。由于一张扑克牌,不能同时有两种不同性质,不能一会儿是大王,一会儿又变成黑桃K ,那样就乱套了,不合常理。因此,这与union联合型数据结构的特点是相符的,选用union联合型数据结构就可以完美解决这个问题。class Poker public:bool IsNone();void Clear();Poker &operator =(const Poker &pk);void MakeCard(int number);void ShowCard() const;Poker(const Poker &P);Poker();virtual Poker();private: enum CardTagNONE = 0, COMMON, SPECIAL;/扑克牌的类型:NONE:空COMM0N:一般的牌,SPECIAL:大小王enum SuitSPADE = 1, HEART, CLUB, DIAMOND;/扑克牌的花色(黑桃、红心、梅花、方块)enum FaceFA = 1, F2, F3, F4, F5, F6, F7, F8, F9, F10, FJ, FQ, FK;/扑克牌的数字(从A到K)enum JokerBigJoker = 14, SmallJoker = 15;CardTag m_CardTag;unionstructSuit m_Suit;Face m_Face; CommonCard;structJoker m_Joker; SpecialCard; m_Card;主要问题二:如何洗牌。解决方法:需要增加一些数组的功能,并通过重载,让Stack的对象具有随机存取的功能。因为在洗牌的时候,不仅要用到Stack的先进后出的性质,也要用到随机读取的功能。随机的实现,运用的是老师在短学期补充的生成随机数的方法:包含了头文件stdlib.h、time.h。 srand(unsigned)time(NULL);/time.h每个伪随机数都是通过在内部定义的一个特殊“数字压碎函数”由上一个伪随机数生成的,第一个伪随机数是由一个内部定义的变量生成的,该变量称为这个序列的种子。在默认情况下,在程序每次运行时种子由计算机初始化为同一个值(默认为1),为了避免这种破坏随机性的现象,可以用srand( )函数来选择自己的种子。代码srand(seed)将定量seed的值赋给内部的“种子”,函数rand( )使用该种子来初始化所产生的伪随机数序列,不同的种子会生成不同的结果。必须输入一个 seed的值的问题,可以使用计算机的系统时钟来解决,系统时钟以秒为单位跟踪当前的时间。在头文件中定义的函数time()以一个unsigned整数返回当前时间,可以作为rand( )函数的种子。这样就能保证每次都能生成不同的随机数了。 int Deck:GetRandInt(int min, int max)int n = rand();/stdlib.hn = n % (max - min + 1) + min; return n;利用计算机的系统时钟做种子只能解决每次生成不同的随机数的问题,而作为扑克牌,每次生成的随机数应该是有一个严格的范围的。所以设计了GetRandInt函数来解决这个问题,代码如上。但要完成洗牌不仅仅如此,洗牌需要将牌大致(随机函数)一分为二,然后交叉洗牌,重复N次。代码如下:void Deck:ShuffleDeck(int times)if (TOTALPAKER = 54 | TOTALPAKER = 52)if (TOTALPAKER = 54 & m_CurCardNumber = 54)| (TOTALPAKER = 52 & m_CurCardNumber = 52)for(int x=0; xtimes; x+)int split;/split是分开成两部分的位置,如上部分、下部分int i = 0, j = 0, k = 0;split = GetRandInt(20, 35);/得到一个在20到35范围之间的随机整数,包括20和35Deck topDeck(TOTALPAKER, m_PlayerNum);Deck bottomDeck(TOTALPAKER, m_PlayerNum);for (i=split; i=TOTALPAKER-1; i+)topDeck.m_CardStack.Push(m_CardStacki);/上部分for (i=0; i=split-1; i+)bottomDeck.m_CardStack.Push(m_CardStacki);/下部分m_CardStack.Clear();m_CurCardNumber = 0;int numCardsToMoveTop = 0;int numCardsToMoveBottom = 0;while (!m_CardStack.IsFull()numCardsToMoveTop = GetRandInt(2,7);/移动2到7张的牌到最上面numCardsToMoveBottom = GetRandInt(2,7);/移动2到7张的牌到最下面for (j=0; j=numCardsToMoveBottom; j+)if (!bottomDeck.m_CardStack.IsEmpty()m_CardStack.Push(bottomDeck.m_CardStack.Pop();m_CurCardNumber+;for (k=0; k=numCardsToMoveTop; k+)if (!topDeck.m_CardStack.IsEmpty()m_CardStack.Push(topDeck.m_CardStack.Pop();m_CurCardNumber+;elsecout 由于缺少了;cout (TOTALPAKER - m_CurCardNumber);cout 张牌,请您重新初始化整副牌! endl;cout endl;/处理最上面的一张牌主要问题三:如何发牌。解决方法:栈(stack),是一种先进后出的结构,原理类似于子弹匣,最先压入弹匣中的子弹最后一个弹出。局部变量在程序执行过程中动态行获得和释放栈空间。变量出栈的顺序与入栈的顺序相反,即最先分配单元的变量空间最后一个被释放。像主函数调用被调函数时,需要把局部变量压入栈,退出被调函数时,从最顶上的开始退栈。栈定义为只允许在一端进行插入和删除的线性表。递推算法,就是充分利用栈的性质的,只能从栈顶取,只能压入栈顶,具有单向性。而发牌的时候,就很像这个的过程。因此,洗牌选用了了栈(Stack)的运行方式。代码如下:#if !defined#define #include #include using namespace std;#if _MSC_VER 1000#pragma once#endif / _MSC_VER 1000template class Stackpublic:T &operator (int index);Stack &operator =(const Stack &st);int GetMaxSize() const;int GetCurSize() const;void Clear();T GetTop() const;bool IsEmpty() const;bool IsFull() const;T Pop();void Push(const T &item);Stack(int size);Stack(const Stack &S);virtual Stack();private:T *m_pMember;int m_MaxSize;int m_CurSize;template Stack:Stack()delete m_pMember;template Stack:Stack(int size)if (size 0)m_pMember = new Tsize;if (m_pMember = NULL)cout 内存分配失败! endl;exit(1);m_MaxSize = size;m_CurSize = 0;elsecout 栈大小必须大于0! endl;exit(1);template void Stack:Push(const T &item)if (IsFull()cout 栈已满 endl;exit(1);elseint CurPos = m_CurSize;m_pMemberCurPos = item;m_CurSize+;template T Stack:Pop()if (IsEmpty()cout 栈已空 endl;exit(1);elseT tmp;tmp = GetTop();m_CurSize-;return tmp;template bool Stack:IsFull() constreturn m_CurSize = m_MaxSize;template bool Stack:IsEmpty() constreturn m_CurSize = 0;template T Stack:GetTop() constif (IsEmpty()cout 栈已空 endl;exit(1);elseint CurPos = m_CurSize;return m_pMember-CurPos;template void Stack:Clear()m_CurSize = 0;template T &Stack:operator (int index)if (index = 0 & index m_CurSize)return m_pMemberindex;elsecout 下标越界 endl;exit(1);template Stack:Stack(const Stack &S)int n = S.m_MaxSize;m_MaxS

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论