//utility.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; // 随机数类Rand
char 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; // 肯定回答返回true
else 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++)
{ // 显示数组elem
cout << 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(); } // 重置开始时间
};
#define MAX_ERROR_MESSAGE_LEN 100
class Error// 通用异常类Error
{
private:
// 数据成员
char message[MAX_ERROR_MESSAGE_LEN]; // 异常信息
public:
// 方法声明
Error(char mes[] = "一般性异常!"){ strcpy(message, mes); }
// 构造函数
void Show() const{ cout << message << endl; } // 显示异常信息
};
class Rand// 随机数类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
#ifndef __CARD_H__
#define __CARD_H__
#include<iostream.h>
typedef enum//扑克牌面值
{
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&output,Card&card)
{
//输出花色
if(card.suit==CLUBS)
output<<"梅花";
else if(card.suit==DIAMONDS)
output<<"方块";
else if(card.suit==HEARTS)
output<<"红桃";
else if(card.suit==SPADES)
output<<"黑桃";
//输出面值
if(card.rank==ACE)
output<<"A";
else if(card.rank==JACK)
output<<"J";
else if(card.rank==QUEEN)
output<<"Q";
else if(card.rank==KING)
output<<"k";
else
output<<int(card.rank);
output<<" ";
return output;
}
#endif
//game_of_21_point.h
#include"card.h"//扑克牌
#include"utility.h"
#ifndef __GAME_OF_21_POINT_H__
#define __GAME_OF_21_POINT_H__
#define LEN_OF_MAX_NAME 21
class GameOf21Point//21点游戏类
{
private:
Card deck[52];//一副扑克牌
int dealPos;//发牌位置
Card hands[8][21];//hands[0]存储庄家手中的牌,hands[1-7]玩家
int numOfCard[8];//每位手中的牌数
char name[8][LEN_OF_MAX_NAME];//庄家与玩家姓名
int numOfPlayer;//玩家人数
public:
GameOf21Point();
~GameOf21Point(){}
void Shuffle();//洗牌,将扑克牌混在一起以便产生一种随机的排列
int GetTotalScore(Card hand[21],int n);//还回一手牌的总分值
void ShowStatus(int num,bool hideFirstCardAndTotalScore=false);//显示庄家与玩家的当前状态
Card DealOneCard(){return deck[dealPos++];}//发一张扑克牌
void Game();//运行游戏
};
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)
{
cout<<"人数只能在1-7人之间,请重新输入人数:";
cin>>numOfPlayer;
}
dealPos=0;//发牌位置
int i;
for(i=0;i<=numOfPlayer;i++)//庄家和玩家手中的扑克牌数量
numOfCard[i]=0;
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--)
{
int pos=Rand::GetRand(curPos+1);//0~curpos之间的随机数
Swap(deck[pos],deck[curPos]);//交换两张牌
}
}
int GameOf21Point::GetTotalScore(Card hands[21],int n)
{
int pos;
int totalScore=0;
for(pos=0;pos<n;pos++)
{
if(hands[pos].rank==ACE)
totalScore+=11;
else if(hands[pos].rank>TEN)
totalScore+=10;
else
totalScore+=int(hands[pos].rank);
}
for(pos=0;totalScore>21&&pos<n;pos++)
{
if(hands[pos].rank==ACE)//A的分值由11改为1分
totalScore-=10;
}
return totalScore;
}
void GameOf21Point::ShowStatus(int num,bool 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();
ShowStatus(i);
}
cout<<endl;
for(i=1;i<=numOfPlayer;i++)
{
cout<<name[i]<<",你想再要一张牌吗";
if(UserSaysYes())
{
hands[i][numOfCard[i]++]=DealOneCard();
ShowStatus(i);//不隐藏第1张牌
}
}
ShowStatus(0);
while(GetTotalScore(hands[0],numOfCard[0])<=16)
{
hands[0][numOfCard[0]++]=DealOneCard();
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
#include"game_of_21_point.h"
void main()
{
system("color 4b");
do
{
GameOf21Point objGame;
objGame.Game();
cout<<"你想在玩一次吗";
}while(UserSaysYes());
system("pause");
}