纸牌游戏21点实验设计报告.docx
《纸牌游戏21点实验设计报告.docx》由会员分享,可在线阅读,更多相关《纸牌游戏21点实验设计报告.docx(27页珍藏版)》请在冰豆网上搜索。
纸牌游戏21点实验设计报告
湖北第二师范学院
《面向对象程序设计》
课程设计报告书
题目:
纸牌游戏——“21点”
院系:
计算机学院
专业:
网络工程
姓名:
李林
学号:
0850311013
同组人员:
陈易俊、吴鑫、易龙、张帅
指导老师:
张琪
设计时间:
2011年2月26日~2011年3月19日
1.课程设计目的
在VisualC++6.0或者C++Builder6.0环境中编译运行纸牌游戏——“21点”,通过编程练习、程序调试、程序纠错等过程训练,真正掌握所学知识、提高编程水平。
2.问题描述
“21点”是一个古老的扑克牌游戏,游戏规则是:
各个参与者设法使自己的牌达到总分21而不超过这个数值。
扑克牌的分值取它们的面值,A充当1分或者11分(由玩家自己选择一种分值),J.Q和K人头牌都是10分。
庄家对付1到7个玩家。
在一局开始时,包括庄家在内的所有参与者都有两张牌。
玩家可以看到他们的所有牌以及总分,而庄家有一张牌暂时是隐蔽的。
接下来,只有愿意,各个玩家都有机会依次再拿一张牌。
如果某个玩家的总分超过了21(称为“引爆”),那么这个玩家就输了。
在所有玩家都拿了额外的牌后,庄家将显示隐藏的牌。
只要庄家的总分等于或小于16,那么他就必须再拿牌,如果庄家引爆了,那么还没有引爆的所有玩家都将获胜。
引爆的玩家打成平局。
否则,将余下的各玩家的总分与庄家的总分做比较,如果玩家的总分大于庄家的总分,则玩家获胜。
如果二者的总分相同,则玩家与庄家打成平局。
(1)将所有的函数与相应的数据封装到类中,并改写主程序,使程序简化。
(2)序中一共有13张扑克牌可以随机抽取,大于10的点数为10,A根据情况点数不同,当前点数小于11时为11点,大于10时则为1点。
(3)要求庄家永远不会暴庄,即庄家可以查看下一张牌,若大于21点,则拒绝,当然,在游戏规则上不能泄露这点秘密。
(4)将界面的提示说明全部设计为中文界面,界面的解释详细友好,可以吸引更多的玩家。
3.需求分析
设计程序的的主要目的是编写程序模拟游戏。
游戏为纸牌游戏——“21点,”也叫"BlackJack"即黑杰克,该游戏适用于手机,也是网上比较流行的小游戏之一。
游戏以计算机作为庄家,1—7个人作为普通玩家参与游戏。
可用字符代表扑克牌面值(A,2,3,4,5,6,7,8,9,10,J,Q,K)和花色(梅花C,方块D,红心H,黑桃S),模拟实质扑克进行游戏。
方便大众在空闲时一个人就可以达到多人娱乐的效果!
四.概要设计
4.1 系统中类类型定义及系统各类类成员功能说明
“21点游戏”程序中的类
类
基类
说明
Card
无
一张扑克牌
Hand
无
一手牌,Card对象集合
Deck
Hand
一副牌它具有Hand所不具备的额外功能,如洗牌和发牌
GenericPalayer
Hand
一个抽象玩家,具有庄家和玩家的共同元素
Player
GenericPalayer
普通玩家
House
GenericPalayer
庄家
Game
无
一个游戏
4.2系统各类间关系
Card类
成员
说明
rankm-Rank
牌的面值。
Rank是13个面值等级的枚举
suitm-Suit
牌的花色。
Suit是4花色的枚举
boolm-IsFace
标示牌是否正面朝上的状态,正面朝上为true,否则false
intGetVable()
返回牌面值所对应的分值
Hand类
成员
说明
vectorm-Cards
牌面向量,存储指向Card对象指针
voidAdd(Card*pCard)
向手中添加一张牌,即将一个指向Card的指针添加到向量m-Cards中
voidClear()
清除手中所有牌,即删除向量m-Card中的所有指针删除所有动态创建Card对象
intGetTotal()const
返回这首派总值
GenericPalayer类(抽象类)
成员
说明
sringm-Name
通用玩家的名字
vrtualboolIsHitting
()const=0
指出通用玩家是否想要另一张牌,纯属函数
boolIsBusted()const
指出通用玩家是否引爆
voidBust()const
宣布通用玩家引爆
Player类
成员
说明
vrtualboolIsHitting
()const
指出玩家是否想要另一张牌
voidWin()const
宣布玩家获胜
voidLose()const
宣布玩家失败
voidPush()const
宣布玩家获得平局
House类
成员
说明
vrtualboolIsHitting
()const
指出玩家是否再拿一张牌
Deck类
成员
说明
voidPopulate()
创建一共52张的标准扑克牌
voidShuffle()
洗牌
voidDeal(Hand&Hand)
将一张牌发到一手中
voidAdditionalCards(GenericPalayer&GenericPalayer)
只要通用玩家可以并且想要另一张牌,则在给他发一张牌
Game类
成员
说明
Deckm-Deck
一副牌
Housem-House
庄家
vectorm-Player
普通玩家的集合,Player对象的一个向量
voidPlay()
玩一局游戏
五.详细设计
5.1数据类型定义及伪代码描述
1.首先定义表示扑克牌花色与面值的枚举类型,这样程序可读性更强
2.其次,方法Game()用来运行游戏,下面为用伪代码描述的整个游戏的流程:
洗牌
给庄家和玩家发最初的二张牌
隐藏庄家的第一张牌
显示庄家和玩家手中的牌
依次向玩家发额外的牌
显示庄家的第一张牌
给庄家发额外的牌
if(庄家引爆)
没有引爆的玩家人赢
引爆的玩家平局
else
for(每个玩家)
if(玩家没有引爆且玩家的总分比庄家大)宣布玩家赢
elseif(玩家的总分与庄家相等)宣布平局
else宣布玩家赢
5.2系统主要子程序详细设计(加注释的源程序)
(1)新建头文件Card.h,为一张单独的扑克牌定义Card类。
#ifndef_Card_h_
#define_Card_h_
#include
usingnamespacestd;
classCard
{
public:
enumrank{ACE=1,TWO,THREE,FOUR,FIVE,SIX,SEVEN,EIGHT,NINE,TEN,JACK,QUEEN,KING};
enumsuit{CLUBS,DIAMONDS,HEARTS,SPADES};
Card(rankr=ACE,suits=SPADES,boolifu=true);
//friendostream&operator<<(ostream&os,constCard&aCard);
intGetValue()const;
voidFlip();
rankm_Rank;
suitm_Suit;
boolm_IsFaceUp;
};
#endif
(2)新建头cpp文件Card.cpp,实现Card类。
#include"Card.h"
Card:
:
Card(rankr,suits,boolifu):
m_Rank(r),m_Suit(s),m_IsFaceUp(ifu)
{}
intCard:
:
GetValue()const
{intvalue=0;
if(m_IsFaceUp)
{value=m_Rank;
if(value>10)value=10;
}
returnvalue;
}
voidCard:
:
Flip()
{m_IsFaceUp=!
(m_IsFaceUp);
}
(3)新建头文件Hand.h,为纸牌的集合定义Hand类。
#ifndef_Hand_h_
#define_Hand_h_
#include"Card.h"
#include
usingnamespacestd;
classHand
{public:
Hand();
virtual~Hand();
voidAdd(Card*pCard);
voidClear();
intGetTotal()const;
public:
vectorm_Cards;};
#endif
(4)新建Cpp文件Hand.cpp,实现Hand类。
#include"Hand.h"
Hand:
:
Hand()
{m_Cards.reserve(7);}
Hand:
:
~Hand()
{Clear();}
voidHand:
:
Add(Card*pCard)
{m_Cards.push_back(pCard);}
voidHand:
:
Clear()
{vector:
:
iteratoriter=m_Cards.begin();
for(iter=m_Cards.begin();iter!
=m_Cards.end();++iter)
{delete*iter;
*iter=0;
}
m_Cards.clear();
}
intHand:
:
GetTotal()const
{if(m_Cards.empty())return0;
if(m_Cards[0]->GetValue()==0)
return0;
inttotal=0;
vector:
:
const_iteratoriter;
for(iter=m_Cards.begin();iter!
=m_Cards.end();++iter)
total+=(*iter)->GetValue();
boolcontainsAce=false;
for(iter=m_Cards.begin();iter!
=m_Cards.end();++iter)
if((*iter)->GetValue()==Card:
:
ACE)
containsAce=true;
if(containsAce&&total<=11)
total+=10;
returntotal;
}
(5)新建头文件GenericPlayer.h,为通用玩家定义抽象的GenericPlayer类。
#ifndef_GenericPlayer_h_
#define_GenericPlayer_h_
#include"Hand.h"
#include
usingnamespacestd;
classGenericPlayer:
publicHand
{
public:
friendostream&operator<<(ostream&os,constGenericPlayer&aGenericPlayer);
GenericPlayer(conststring&name="");
virtual~GenericPlayer();
virtualboolIsHitting()const=0;
boolIsBusted()const;
voidBust()const;
stringm_Name;
};
#endif
(6)新建cpp文件GenericPlayer.cpp,实现GenericPlayer类的成员函数。
//#include"stdafx.h"
#include"GenericPlayer.h"
GenericPlayer:
:
GenericPlayer(conststring&name):
m_Name(name)
{
}
GenericPlayer:
:
~GenericPlayer()
{
}
boolGenericPlayer:
:
IsBusted()const
{
return(GetTotal()>21);
}
voidGenericPlayer:
:
Bust()const
{
cout<\n";
}
(7)新建头文件PlayerHouse.h,从GenericPlayer类派生Player类和House类。
#ifndefPlayerHouse_h
#definePlayerHouse_h
#include"GenericPlayer.h"
#include
usingnamespacestd;
classPlayer:
publicGenericPlayer
{public:
Player(conststring&name="");
virtual~Player();
virtualboolIsHitting()const;
voidWin()const;
voidLose()const;
voidPush()const;
};
classHouse:
publicGenericPlayer
{public:
House(conststring&name="庄家");
virtual~House();
virtualboolIsHitting()const;
voidFlipFirstCard();
};
#endif
(8)新建cpp文件PlayerHouse.cpp,实现Player类和House类的成员函数。
#include"PlayerHouse.h"
Player:
:
Player(conststring&name):
GenericPlayer(name)
{}
Player:
:
~Player()
{}
boolPlayer:
:
IsHitting()const
{cout<(Y/N):
";
charresponse;
cin>>response;
return(response=='y'||response=='Y');
}
voidPlayer:
:
Win()const
{cout<\n";}
voidPlayer:
:
Lose()const
{cout<\n";}
voidPlayer:
:
Push()const
{cout<\n";}
House:
:
House(conststring&name):
GenericPlayer(name)
{}
House:
:
~House()
{}
boolHouse:
:
IsHitting()const
{return(GetTotal()<=16);}
voidHouse:
:
FlipFirstCard()
{if(!
(m_Cards.empty()))
m_Cards[0]->Flip();
elsecout<<"没有扑克牌翻动!
\n";
}
(9)新建头文件Deck.h,从Hand类派生Deck类,表示一副牌。
#ifndefDeck_h
#defineDeck_h
#include"Hand.h"
#include"GenericPlayer.h"
#include
usingnamespacestd;
classDeck:
publicHand
{public:
Deck();
virtual~Deck();
voidPopulate();
voidShuffle();
voidDeal(Hand&aHand);
voidAdditionalCards(GenericPlayer&aGenericPlayer);
};
#endif
(10)新建cpp文件Deck.cpp,实现Deck类的成员函数。
#include"Deck.h"
#include
Deck:
:
Deck()
{m_Cards.reserve(52);
Populate();
}
Deck:
:
~Deck()
{}
voidDeck:
:
Populate()
{Clear();
for(ints=Card:
:
CLUBS;s<=Card:
:
SPADES;++s)
for(intr=Card:
:
ACE;r<=Card:
:
KING;++r)
Add(newCard(static_cast:
rank>(r),static_cast:
suit>(s)));
}
voidDeck:
:
Shuffle()
{random_shuffle(m_Cards.begin(),m_Cards.end());}
voidDeck:
:
Deal(Hand&aHand)
{if(!
m_Cards.empty())
{aHand.Add(m_Cards.back());
m_Cards.pop_back();
}
else
{cout<<"Outofcards.Unabletodeal.";}
}
voidDeck:
:
AdditionalCards(GenericPlayer&aGenericPlayer)
{cout<while(!
(aGenericPlayer.IsBusted())&&aGenericPlayer.IsHitting())
{Deal(aGenericPlayer);
cout<if(aGenericPlayer.IsBusted())aGenericPlayer.Bust();
}
}
(11)新建头文件Game.h定义Game类表示21点游戏。
#ifndef_Game_h_
#define_Game_h_
#include"Deck.h"
#include"PlayerHouse.h"
#include
#include
#include
usingnamespacestd;
classGame
{public:
Game(constvector&names);
~Game();
voidPlay();
private:
Deckm_Deck;
Housem_House;
vectorm_Players;
};
#endif
(12)新建cpp文件Game.cpp,实现Game类的成员函数。
#include"Game.h"
#include
#include
usingnamespacestd;
Game:
:
Game(constvector&names)
{
vector:
:
const_iteratorpName;
for(pName=names.begin();pName!
=names.end();++pName)
m_Players.push_back(Player(*pName));
srand(time(0));
m_Deck.Populate();
m_Deck.Shuffle();
}
Game:
:
~Game()
{}
voidGame:
:
Play()
{
//将最初的两张牌发给每一个人
vector:
:
iteratorpPlayer;
for(inti=0;i<2;++i)
{
for(pPlayer=m_Players.begin();pPlayer!
=m_Players.end();++pPlayer)
m_Deck.Deal(*pPlayer);
m_Deck.Deal(m_House);
}
//隐藏庄家的第一张牌
m_House.FlipFirstCard();
//显示每个人的一张牌
for(pPlayer=m_Players.begin();pPlayer!
=m_Players.end();++pPlayer)
cout<<*pPlayer<cout<//向玩家发额外的牌
for(pPlayer=m_Players.begin();pPlayer!
=m_Players.end();++pPlayer)
m_Deck.AdditionalCards(*pPlayer);
//显示庄家的第一张牌
m_House.FlipFirstCard();
cout<//向庄家发额外的牌
m_Deck.AdditionalCards(m_House);
if(m_House.IsBusted())
{
//仍然在玩的所有人都获胜
for(pPlayer=m_Players.begin();pPlayer!
=m_Players.end();++pPlayer)
if(!
(pPlayer->IsBusted()))pPlayer->Win();
}
else
{
//将仍然在玩的各个玩家与庄家做比较
for(pPlayer=m_Players.begin();pPlayer!
=m_Players.end();++pPlayer)
if(!
(pPlayer->IsBusted()))
{
if(pPlayer->GetTotal()>m_House.GetTotal())pPlayer->Win();
elseif(pPlayer->GetTotal()Lose();
elsepPlayer->Push();
}
}
//删除每个人的牌
for(pPlayer=m_Players.begin();pPlayer!
=m_Players.end();++pPlayer)
pPlayer->Clear();
m_House.Clear();
}
(13)新建cpp文件Main.cpp编写游戏程序的主函数,并实现重载的operator<<()函数.
#include"Game.h"
#include
#include
usingnamespacestd;
//函数原型
ostream&operator<<(ostream&os,constCard&aCard);
ostream&operator<<(ostream&os,constGenericPlayer&aGenericPlayer);
intmain()
{
cout<<