C++程序 :“21 点"纸牌游戏

  • 实验题目:
  • 代码:

实验题目:

​ “21点”是一个古老的扑克牌游戏,游戏规则是:各个参与者设法使自己的牌达到总分21而不超过这个数值。扑克牌的分值取它们的面值,A充当1分或者11分(由玩家自己选择一种分值),J.Q和K 人头牌都是10分。

​ 庄家对付1~7个玩家。在一局开始时,包括庄家在内的所有参与者都有两张牌。玩家可以看到他们的所有牌以及总分,而庄家有一张牌暂时是隐藏的。接下来,只要愿意,各个玩家都有机会依次再拿-张牌。 如果某个玩家的总分超过了21(称为“引爆”),那么这个玩家就了。在所有玩家都拿了额外的牌后,庄家将显示隐藏的牌。只要庄家的总分等于或小于16,那么他就必须再拿牌。如果庄家引爆了,那么还没有引爆的所有玩家都将获胜,引爆的玩家打成平局。否则,将余下的各玩家的总分与庄家的总分做比较,如果玩家的总分
大于庄家的总分,则玩家获胜。如果二者的总分相同,则玩家与庄家打成平局。

​ 编写程序实现游戏,计算机作为庄家,1~7个人作为普通玩家参与游戏。游戏程序运行输出如下所示。

多少人加人游戏?(1~7):2
输人第1位玩家的姓名:张三
输入第2位玩家的姓名:李四
游戏开始
庄家:<隐藏>梅花7
张三:红桃7方块J总分值17
李四:红桃J红桃3总分值13张三,你想再要一一张牌吗(y, n)?n
李四,你想再要一张牌吗(y, n)?y
李四:红桃J红桃3梅花10总分值23
李四引爆!
庄家:方块10梅花7总分值17张三,唉,你打平局了!
李四,对不起,你输了!
你想再玩一次吗 (y, n)?

代码:

结构图:

utilitty.h 部分

#ifndef __UTILITY_H__                // 如果没有定义__UTILITY_H__
#define __UTILITY_H__               // 那么定义__UTILITY_H__// 实用程序工具包#ifdef _MSC_VER                       // 表示是Visual C++
#if _MSC_VER == 1200              // 表示Visual C++6.0// 标准库头文件
#include <string.h>                   // 标准串和操作
#include <iostream.h>             // 标准流操作
#include <limits.h>                   // 极限
#include <math.h>                 // 数据函数
#include <fstream.h>              // 文件输入输出
#include <ctype.h>                    // 字符处理
#include <time.h>                 // 日期和时间函数
#include <stdlib.h>                   // 标准库
#include <stdio.h>                    // 标准输入输出
#include <iomanip.h>              // 输入输出流格式设置
#include <stdarg.h>               // 支持变长函数参数
#include <assert.h>                   // 支持断言#else                                // 其它版本的Visual C++// ANSI C++标准库头文件
#include <string>                 // 标准串和操作
#include <iostream>                   // 标准流操作
#include <limits>                 // 极限
#include <cmath>                  // 数据函数
#include <fstream>                    // 文件输入输出
#include <cctype>                 // 字符处理
#include <ctime>                      // 日期和时间函数
#include <cstdlib>                    // 标准库
#include <cstdio>                 // 标准输入输出
#include <iomanip>                    // 输入输出流格式设置
#include <cstdarg>                    // 支持变长函数参数
#include <cassert>                    // 支持断言
using namespace std;                // 标准库包含在命名空间std中#endif                             // _MSC_VER == 1200
#else                               // 非Visual C++ // ANSI C++标准库头文件
#include <string>                 // 标准串操作
#include <iostream>                   // 标准流操作
#include <limits>                 // 极限
#include <cmath>                  // 数据函数
#include <fstream>                    // 文件输入输出
#include <cctype>                 // 字符处理
#include <ctime>                      // 日期和时间函数
#include <cstdlib>                    // 标准库
#include <cstdio>                 // 标准输入输出
#include <iomanip>                    // 输入输出流格式设置
#include <cstdarg>                    // 支持变长函数参数
#include <cassert>                    // 支持断言
using namespace std;                // 标准库包含在命名空间std中#endif                             // _MSC_VER// 实用函数
char GetChar(istream &inStream = cin); // 从输入流inStream中跳过空格及制表符获取一字符
bool UserSaysYes();     // 当用户肯定回答(yes)时, 返回true, 用户否定回答(no)时,返回false// 函数模板
template <class ElemType >
void Swap(ElemType &e1, ElemType &e2);  // 交换e1, e2之值
template<class ElemType>
void Display(ElemType elem[], int n);   // 显示数组elem的各数据元素值// 实用类
class Timer;            // 计时器类Timer
class Error;            // 通用异常类
class Rand;             // 随机数类Randchar GetChar(istream &in)            // 从输入流in中跳过空格及制表符获取一字符
{char ch;                       // 临时变量while ((ch = in.peek()) != EOF // 文件结束符(peek()函数从输入流中接受1// 字符,流的当前位置不变)&& ((ch = in.get()) == ' ' // 空格(get()函数从输入流中接受1字符,流// 的当前位置向后移1个位置)|| ch == '\t'));           // 制表符return ch;                        // 返回字符
}bool UserSaysYes() // 当用户肯定回答(yes)时, 返回true, 用户否定回答(no)时,返回false
{char ch;                                   // 用户回答字符bool initialResponse = true;              // 初始回答do{  // 循环直到用户输入恰当的回答为止if (initialResponse) cout << "(y, n)?"; // 初始回答else cout << "用y或n回答:";                // 非初始回答while ((ch = GetChar()) == '\n');      // 跳过空格,制表符及换行符获取一字符initialResponse = false;               // 非初始回答} while (ch != 'y' && ch != 'Y' && ch != 'n' && ch != 'N');while (GetChar() != '\n');                    // 跳过当前行后面的字符if (ch == 'y' || ch == 'Y') return true;   // 肯定回答返回trueelse return false;                         // 否定回答返回false
}template <class ElemType >
void Swap(ElemType &e1, ElemType &e2)   // 交换e1, e2之值
{ElemType temp;                     // 临时变量temp = e1; e1 = e2; e2 = temp;        // 循环赋值实现交换e1, e2
}template<class ElemType>
void Show(ElemType elem[], int n)       // 显示数组elem的各数据元素值
{for (int i = 0; i < n; i++){ // 显示数组elemcout << elem[i] << "  ";       // 显示elem[i]}cout << endl;                        // 换行
}// 计时器类Timer
class Timer
{
private:
// 数据成员clock_t startTime;public:
//  方法声明Timer(){ startTime = clock(); }            // 构造函数, 由当前时间作为开始时间构造对象double ElapsedTime() const              // 返回已过的时间{clock_t endTime = clock();                              // 结束时间return (double)(endTime - startTime) / (double)CLK_TCK;  // 计算已过时间}void Reset(){ startTime = clock(); } // 重置开始时间
};// 通用异常类Error
#define MAX_ERROR_MESSAGE_LEN 100
class Error
{
private:
// 数据成员char message[MAX_ERROR_MESSAGE_LEN]; // 异常信息public:
//  方法声明Error(char mes[] = "一般性异常!"){ strcpy(message, mes); }    // 构造函数 void Show() const{ cout << message << endl; }               // 显示异常信息
};// 随机数类Rand
class Rand
{
public:
//  方法声明static void SetRandSeed(){ srand((unsigned)time(NULL)); }   // 设置当前时间为随机数种子static int GetRand(int n){ return rand() % n; }              // 生成0 ~ n-1之间的随机数static int GetRand(){ return rand(); }                        // 生成0 ~ n-1之间的随机数
};#endif

card.h 部分

// 文件路径名: game_of_21_point\card.h
#ifndef __CARD_H__              // 如果没有定义__CARD_H__
#define __CARD_H__              // 那么定义__CARD_H__typedef enum
{   // 扑克牌面值:ACE(A),TWO(2)~TEN(10),JACK(J), QUEEN(Q), KING(K)ACE = 1, TWO, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING
} RankType;typedef enum
{   // 扑克牌花色:CLUBS(梅花), DIAMONDS(方块), HEARTS(红桃)和SPADES(黑桃)CLUBS, DIAMONDS, HEARTS, SPADES
} SuitType;struct Card
{   // 扑克牌结构体RankType rank;                                 // 扑克牌面值SuitType suit;                                  // 扑克牌花色
};ostream& operator<<(ostream& outStream, const Card &card)   // 重载<<运算符
{// 输出花色if (card.suit == CLUBS) outStream << " 梅花";           // CLUBS表示梅花else if (card.suit == DIAMONDS) outStream << " 方块";   // DIAMONDS表示方块else if (card.suit == HEARTS) outStream << " 红桃";      // HEARTS表示红桃else if (card.suit == SPADES) outStream << " 黑桃";        // SPADES表示黑桃// 输出面值if (card.rank == ACE) outStream << "A";                   // ACE表示Aelse if (card.rank == JACK) outStream << "J";            // JACK表示Jelse if (card.rank == QUEEN) outStream << "Q";          // QUEEN表示Qelse if (card.rank == KING) outStream << "K";          // KING表示Kelse cout << (int)card.rank;                            // (int)card.rank为分值return outStream;
}#endif

game_of_21_point.h 部分

// 文件路径名: game_of_21_point\game_of_21_point.h
#ifndef __GAME_OF_21_POINT_H__              // 如果没有定义__GAME_OF_21_POINT_H__
#define __GAME_OF_21_POINT_H__              // 那么定义__GAME_OF_21_POINT_H__#include "card.h"            // 扑克牌#define LEN_OF_MAX_NAME 21    // 最大姓名长度// 21点游戏类GameOf21Point声明
class GameOf21Point
{
private:
// 数据成员:Card deck[52];      // 一副扑克牌int dealPos;        // 发牌位置Card hands[8][21];   // hand[0]存储庄家手中的扑克牌, hand[1~7]存储各位玩家手中的扑克牌int numOfCard[8];    // 庄家(numOfCard[0])及玩家(numOfCard[1~7])手中的扑克牌数char name[8][LEN_OF_MAX_NAME]; // 庄家与玩家姓名int numOfPlayer;  // 玩家人数// 辅助函数void Shuffle();       // 洗牌, 将扑克牌混在一起以便产生一种随机的排列int GetTotalScore(Card hand[21], int n);// 返回一手扑克牌的总分值void ShowStatus(int num, bool hideFirstCardAndTotalScore = false); // 显示庄家(对应num=0)或玩家(对应num>0)的当前状态Card DealOneCard(){ return deck[dealPos++]; }    // 发一张扑克牌public:
// 方法声明:GameOf21Point();            // 无参数的构造函数virtual ~GameOf21Point(){}   // 析构函数void Game();             // 运行游戏
};// 21点游戏类GameOf21Point的实现部分
GameOf21Point::GameOf21Point()  // 初始化扑克牌,发牌位置,庄家与各玩家手中的扑克牌数
{int curPos = 0;               // 当前扑克牌位置      for (int suitPos = 0; suitPos < 4; suitPos++){    // 花色for (int rankPos = 1; rankPos <= 13; rankPos++){    // 面值deck[curPos].suit = (SuitType)suitPos;    // 花色deck[curPos].rank = (RankType)rankPos;    // 面值curPos++;                                // 下一个位置}}cout << "多少人加入游戏?(1~7):"; cin >> numOfPlayer;           // 玩家人数 while (numOfPlayer < 1 || numOfPlayer > 7)        {   // 限制人数在1~7之间cout << "人数只能在1~7之间, 请重新输入人数:";cin >> numOfPlayer;       // 玩家人数 }dealPos = 0;              // 发牌位置int i;                       // 临时变量for (i = 0; i <= numOfPlayer; i++) numOfCard[i] = 0; //  庄家(numOfCard[0])及玩家(numOfCard[1~7])手中的扑克牌数strcpy(name[0], "庄家");  // 庄家for (i = 1; i <= numOfPlayer; i++){ // 玩家姓名cout << "输入第" << i << "位玩家的姓名:";cin >> name[i];}cout << "游戏开始" << endl;
}void GameOf21Point::Shuffle()  // 洗牌, 将扑克牌混在一起以便产生一种随机的排列组合
{Rand::SetRandSeed();               // 设置当前时间为随机数种子for (int curPos = 51; curPos > 0; curPos--){ // 产生随机的位置为curPos的扑克牌int pos = Rand::GetRand(curPos + 1); // 生成0~curPos之间的随机数Swap(deck[pos], deck[curPos]);   // 交换deck[pos]与deck[curPos]}
}int GameOf21Point::GetTotalScore(Card hand[21], int n) // 返回一手扑克牌的总分值
{int pos;                           // 临时变量int totalScore = 0;                 // 总分值for (pos = 0; pos < n; pos++){  // 循环求最大分值(A的分值为11)if (hand[pos].rank == ACE) totalScore += 11; // A的分值为11else if (hand[pos].rank > TEN) totalScore += 10;// J,Q,K的分值为10else totalScore += (int)hand[pos].rank;          // TWO~TEN的分值为2~10}for (pos = 0; totalScore > 21 && pos < n; pos++){   // 分值大于21时, 将A的分值改为1if (hand[pos].rank == ACE) totalScore -= 10; // A的分值由11分改为1分}return totalScore;                  // 返回总分
}void GameOf21Point::ShowStatus(int num, bool hideFirstCardAndTotalScore)
// 当num=0时,显示庄家当前状态,当num>0时,显示第num个玩家的当前状态,当
//  hideFirstCardAndTotalScore为真时,将隐藏首张扑克牌与总分, 否则将显示首张扑克牌与总分
{cout << name[num] << ":";            // 显示庄家或玩家姓名 if (hideFirstCardAndTotalScore) cout << " <隐藏>"; // 隐藏首张扑克牌else cout << hands[num][0];                         // 显示首张扑克牌for (int i = 1; i < numOfCard[num]; i++)cout << hands[num][i];            // 显示庄家或玩家手中的扑克牌if (!hideFirstCardAndTotalScore)cout << " 总分值" << GetTotalScore(hands[num], numOfCard[num]); // 显示庄家或玩家总分cout << endl;if (GetTotalScore(hands[num], numOfCard[num]) > 21)cout << name[num] << "引爆!" << endl;
}void GameOf21Point::Game() // 运行游戏
{Shuffle();     // 洗牌, 将扑克牌混在一起以便产生一种随机的排列int i, j;     // 临时变量for (i = 0; i < 2; i++) hands[0][numOfCard[0]++] = DealOneCard();       // 为庄家发两张扑克牌ShowStatus(0, true);                                // 显示庄家状态,隐藏首张扑克牌与总分for (i = 1; i <= numOfPlayer; i++){  // 向各玩家发扑克牌,显示各玩家发扑克牌手中的扑克牌for (j = 0; j < 2; j++) hands[i][numOfCard[i]++] = DealOneCard();   // 为玩家i发两张扑克牌ShowStatus(i);                                 // 显示玩家i}cout << endl;for (i = 1; i <= numOfPlayer; i++){  // 依次向玩家发额外的牌cout << name[i] << ", 你想再要一张牌吗";if (UserSaysYes()){  // 玩家再要一张牌hands[i][numOfCard[i]++] = DealOneCard();  // 为玩家i发1张扑克牌ShowStatus(i);                             // 显示玩家i}}  ShowStatus(0);                                      // 显示庄家while (GetTotalScore(hands[0], numOfCard[0]) <= 16){ // 庄家总分小于等于16, 必须再拿牌hands[0][numOfCard[0]++] = DealOneCard();        // 为庄家发1张扑克牌ShowStatus(0);                                  // 显示庄家}cout << endl;if (GetTotalScore(hands[0], numOfCard[0]) > 21){  // 庄家引爆, 没有引爆的所有人赢for (i = 1; i <= numOfPlayer; i++){    // 依次查看每位玩家if (GetTotalScore(hands[i], numOfCard[i]) <= 21) cout << name[i] << ", 恭喜你, 你赢了!" << endl;       // 玩家没有引爆else cout << name[i] << ", 唉, 你打平局了!" << endl; // 玩家引爆}}else{  // 庄家没有引爆for (i = 1; i <= numOfPlayer; i++){ // 依次查看每位玩家if (GetTotalScore(hands[i], numOfCard[i]) <= 21 &&       // 未引爆GetTotalScore(hands[i], numOfCard[i]) > GetTotalScore(hands[0], numOfCard[0])// 总分比庄家大){   // 玩家未引爆, 且总分比庄家大, 玩家赢cout << name[i] << ", 恭喜你, 你赢了!" << endl;     }else if (GetTotalScore(hands[i], numOfCard[i]) == GetTotalScore(hands[0], numOfCard[0])){    // 玩家总分与庄家相等, 平局cout << name[i] << ", 唉, 你打平局了!" << endl;       }else { // 玩家引爆或总分比庄家小, 玩家输cout << name[i] << ", 对不起, 你输了!" << endl;}}}
}#endif

main.cpp 部分

// 文件路径名:game_of_21_point\main.cpp
#include "utility.h"                  // 实用程序软件包
#include "game_of_21_point.h"         // 21点游戏int main(void)                          // 主函数main(void)
{do{GameOf21Point objGame;          //  21点游戏对象objGame.Game();                  // 运行游戏cout << "你想再玩一次吗";} while (UserSaysYes());           // 肯定回符循环, 直到得到否定回答为止system("PAUSE");                 // 调用库函数system()return 0;                           // 返回值0, 返回操作系统
}

C++程序 :“21 点“纸牌游戏相关推荐

  1. 21点纸牌游戏完整代码

    一共六大类: 第一类: public class Card {private int num;private int type;public Card(int num,int color){this. ...

  2. blackjack算法java_[CareerCup] 8.1 Implement Blackjack 实现21点纸牌

    8.1 Design the data structures for a generic deck of cards. Explain how you would subclass the data ...

  3. 玩纸牌游戏计算机教案,第5课 用计算机娱乐”教学设计

    [教学目标] ·学会用"CD唱机"播放音乐 ·学会用计算机播放影碟 ·初步了解多媒体计算机的功能 [教学内容] ·鼠标单击.双击.拖动操作 ·CD唱机的应用 ·金山影霸的应用 [教 ...

  4. 纸牌游戏21点设计制作(C语言)

    纸牌游戏21点设计制作 (C语言) 我是编程爱好者.早期使用windows时就被扫雷游戏,钻石棋游戏,红心大战游戏迷住.相信大家也都玩过吧.在学习VB6编程时就编制过钻石棋和红心大战那样的纸牌游戏.都 ...

  5. c语言数据结构设计纸牌游戏,求一用数据结构c++编写的纸牌游戏程序

    需求: 1.一副没有J.Q.K.A.大小王的扑克牌(40张牌),编号为1-40张牌.第一回合,从40张牌中给双方各随机抽取5张牌,抽出的牌在原数组里删除.第二回合,从剩下30张牌中给双方各随机抽取5张 ...

  6. 用C#做一个简单纸牌游戏的程序

    小子不才学C#没多久,想做个窗体纸牌游戏玩,但是窗体应用懂得不多,只能在控制命令台上进行游戏设计,希望有大神能帮我设计这个窗体程序,或者推荐好的窗体设计资料,谢谢了,控制命令台程序如下: namesp ...

  7. NYOJ 614 纸牌游戏

    纸牌游戏 时间限制:1000 ms  |  内存限制:65535 KB 难度:2 描述 设2n张牌分别标记为1,2,-,n,n+l,-,2n,初始时这2n张牌按其标号从小到大排列. 经一次洗牌后,原来 ...

  8. 纸牌游戏炸金花设计制作(C语言)

    纸牌游戏炸金花设计制作 (C语言) 我是编程爱好者.早期使用windows时就被扫雷游戏,钻石棋游戏,红心大战游戏迷住.相信大家也都玩过吧.在学习VB6编程时就编制过钻石棋和红心大战那样的游戏.都是标 ...

  9. 纸牌游戏梭哈设计制作(C语言)

    纸牌游戏梭哈设计制作 (C语言) 我是编程爱好者.早期使用windows时就被扫雷游戏,钻石棋游戏,红心大战游戏迷住.相信大家也都玩过吧.在学习VB6编程时就编制过钻石棋和红心大战那样的纸牌游戏.都是 ...

最新文章

  1. 看BAT技术面试官如何挑选Java程序员
  2. 解决莫名其妙出现connection closed的错误
  3. 更新WordPress4.0访问速度慢问题解决办法
  4. qt高亮快捷键_QtCreator中常用快捷键总结
  5. ipa去除时间锁_【解密了!】影响沸石分子筛转轮去除效率的因素
  6. mysql group 条件,mysql - mysql group by,两个条件,限制1 - SO中文参考 - www.soinside.com...
  7. Scrapy 1.6 中文文档校对活动 | ApacheCN
  8. 系统无声音,播放器有声音
  9. Zookeeper-03-集群
  10. Git(二):Git的安装配置与基本使用
  11. oracle 索引-1无效,oracle 索引失效原因及解決方法
  12. 数据挖掘项目实战—Kaggle入门竞赛:房价预测之EDA与特征工程
  13. 33. Element tagName 属性
  14. 【纪中集训2019.3.23】Deadline
  15. Windows部署KMS服务器
  16. Android应用签名、打包实际操作
  17. chrome(谷歌浏览器)固定到任务栏,点击之后出现两个图标-原因及解决办法
  18. 利用Python实现腾讯校园招聘状态查询
  19. linux常用格式化命令,linux格式化命令【使用方案】
  20. 网站SEO其实很简单,新手必看!!!

热门文章

  1. 百度云限速Tampermonkey油猴插件
  2. java自我进阶书籍
  3. (TIP-2019)基于判别特征学习的跨视角步态识别
  4. 控制用计算机论文,计算机电子控制技术及应用论文
  5. 手把手教程序员如何追到女神(附详细教程)
  6. 5秒钟读懂二阶龙格-库塔法的问题 电通期末不用愁
  7. EMLOG采集插件 最新资源采集 一键显示资源1.1
  8. mysql存储过程与函数、触发器、游标、变量等知识点详解
  9. 电脑全屏时任务栏没有隐藏,解决办法
  10. 解码投资浪潮,跨链 DeFi 如何成为下一块淘金地?