【C++课设】21点小游戏C++

AI权益加码!Claude Code、Cursor等20+工具免费用! 购周边限时加赠Coding Plan Lite,畅享主流AI工具!学习进阶更高效! 阅读详情

二、实验内容

(1)问题描述:

21点小游戏,顾名思义,玩家需要通过纸牌上的点数,通过继续拿牌和不要牌,来增长自己的点数,当最接近21点,或者等于21时,胜利;但当玩家的点数超过21点时,即游戏失败。利用面向对象程序设计方法以及C++的编程思想来完成设计;

(2)功能要求

为了一个人也能玩游戏,需要设置一个机器人(庄家)在游戏里陪玩。
规定:J,K,Q取10,A的初始值为11(当加A超过21点,则A取1;当加A没超过21,A取11);
庄家(机器人)总分小于等于16的时候,必须再拿牌,整个牌局发牌随机,不能指定;且庄家第一张牌被隐藏,直到游戏结束;
①当庄家没有引爆(没有超过21点),则依次查看每位玩家,玩家未引爆,且总分比庄家大的时候,玩家赢;玩家总分与庄家相等,平局;玩家引爆或总分比庄家小,玩家输;
②当庄家引爆(超过21点),没有引爆的所有人赢,但是要依次查看每位玩家,当玩家没有超过21点时,即没有引爆,则玩家赢;当玩家也超过21点,则平局!

(3)算法分析

a.用户输入的数据需要通过一维数组和二维数组进行存储;
b.利用运算符的重载,将相关数据输出到用户界面;
c.按照循环语句的提示进行操作和执行;
paimiansheji.h:
①设计一个头文件"paimiansheji.h",在其中定义两个枚举型变量numtype和shapetype来分别记录纸牌的牌面的面值和纸牌的花色;
②设计一个结构体类型的变量Card记录面值和花色;
③重载运算符“<<”,以方便输出牌面信息;
wanjiasheji.h:
①设计一个头文件"wanjiasheji.h",首先在其中声明21点小游戏的类“Point21”,在类中声明公共变量和函数:Point21(); //无参构造函数 virtual ~Point21(){};//析构函数 void Game();
接着声明私有变量和函数;
②在类外定义在类中声明的函数;
Point21::Point21()//初始化扑克牌,发牌位置,庄家与各玩家手中的扑克牌数;
void Point21::Shuffle()//洗牌,通过产生随机数,交换随机数对应位置的牌和当前位置的牌
int Point21::GetTotalScore(Card gamer[21],int n) //定义返回第一手牌的总分值 的函数
void Point21::ShowStatus(int num,bool hideFirstCard)//显示当前玩家牌的状态
void Point21::Game()//主体
③定义主函数main,实现游戏;

三、概要设计

(1)用户输入玩家人数,和姓名;
(2)开始游戏后,默认自动发牌,显示庄家(机器人)(第一张牌隐藏)和玩家的牌面和总分;
(3)依次询问玩家是否要牌,输入1继续要排,输入0不要牌;
(4)当所有玩家选择完毕以后,显示输赢结果,结束游戏;
(5)用户选择是否继续游戏;
利用Visio2013画出流程功能图:
在这里插入图片描述

四、详细设计

头文件:paimiansheji.h
#include<iostream>
using namespace std;

typedef enum
{
	//牌面A,J=10,Q=10,K=10
	A=1,two, three, four, five, six, seven, eight,nine,ten,J,Q,K
}numtype;
//变量numtype的类型为枚举型enum 

typedef enum
	{
		//扑克牌的花色:clubs(梅花),diamonds(方块),hearts(红桃)和spades(黑桃)
		clubs,diamonds,hearts,spades
	}shapetype;
//变量shapetype的类型为枚举型enum 

struct Card
{
	numtype num;//面值数字
	shapetype shape;//花色形状
};
//定义一副牌的结构体


//重载运算符<<
//运用了const
ostream &operator<<(ostream &output,const Card &card )
{
	//输出花色
	if(card.shape==clubs)  output<<"梅花";
	if(card.shape==diamonds) output<<"方块";
	if(card.shape==hearts) output<<"红桃";
	if(card.shape==spades) output<<"黑桃";

	//输出面值
	if(card.num==A)
	{
		output<<"A";
	}
	else if(card.num==J)
	{
		output<<"J";
	}
	else if(card.num==Q)
	{
		output<<"Q";
	}
	else if(card.num==K)
	{
		output<<"K";
	}
	else cout<<(int)card.num;//强制转化面值为int型

	return output;

}
头文件:wanjiasheji.h
#include <iostream>
#include <ctime>
#define max_length 10 //玩家姓名长度不能大于10个字节 

using namespace std;
//声明21点的游戏类
class Point21
{
//公共变量 
public:
		//函数声明
		Point21();	//无参构造函数
		virtual ~Point21(){};//析构函数 
		void Game();
		
//私有变量		
private:
	Card PK[52];//54张牌减去大小王
	int startPosition;//发牌初始位
	Card gamers[8][21];
	//gamers[0]存放庄家的牌,gamers[1]到[7]存放玩家的牌 
	//设置庄家即是机器人,一个人也能玩
	 
	int numcards[8];	//庄家(numcards[0])及玩家的牌数
	char name[8][max_length];	//庄家及玩家姓名
	int numgamer;//玩家数
	
	void Shuffle();	//洗牌函数 
	
	int GetTotalScore(Card gamer[21],int n);	//返回第一手牌(第一次发牌)的总分值
	
	void ShowStatus(int num,bool hideFirstCard=false);
		//显示庄家(对应num=0)或玩家(对应num>0)的当前状态,要隐藏庄家机器人的第一次发的牌和分数 
	
	Card FirstCard()
	{
		return PK[startPosition++];
	}//发一张扑克牌
	
		
};

//初始化扑克牌,发牌位置,庄家与各玩家手中的扑克牌数
Point21::Point21()
{
	int nowPos=0;	//当前扑克牌位置
	
	char* str;
	
	for(int shapePos=0;shapePos<4;shapePos++)	//花色
	{
		for(int numPos=1;numPos<=13;numPos++)	//面值
		{
			PK[nowPos].shape=(shapetype)shapePos;	//花色
			PK[nowPos].num=(numtype)numPos;	//面值
			nowPos++;
		}
	}
	cout<<endl<<"请问有几个人参加游戏?(最多7个人):";
	str =new char[1];
	cin>>str;
	numgamer=atoi(str);
	//atoi函数与itoa()函数区别 
	
	while (numgamer<1||numgamer>7) //限制人数在1~7之间
	{
		cout<<endl<<"玩家人数限定在1~7个,请重新输入人数:";
	    cin>>str;
     	numgamer=atoi(str);
	}
	
	startPosition=0;	//发牌位置
	int i=0;	//临时变量
	//庄家numcards[0]及玩家numcards[1~7]手中的扑克牌张数
	for(i=0;i<=numgamer;i++) numcards[i]=0;
	
	strcpy(name[0],"庄家");
	
	for(i=1;i<=numgamer;i++)   //玩家姓名
	{
		cout<<"输入第"<<i<<"个玩家的姓名:";
		cin>>name[i];
	}
	cout<<"游戏开始"<<endl<<endl;
}

//洗牌,通过产生随机数,交换随机数对应位置的牌和当前位置的牌
void Point21::Shuffle()
{
	srand((unsigned)time(NULL));	//通过调用时间函数初始化随机数 
	for(int nowPos=51;nowPos>0;nowPos--)
	{
		int pos=rand()%(nowPos+1);	//产生0~nowPos之间的随机数
		
		Card temp;		//定义一个临时变量用于交换牌
		temp=PK[pos];
		PK[pos]=PK[nowPos];
		PK[nowPos]=temp;
	}
}
//定义返回第一手牌的总分值 的函数 
int Point21::GetTotalScore(Card gamer[21],int n)
{
	int pos;
	int totalScore=0;
	for(pos=0;pos<n;pos++)	//循环求最大分值(A的分值为11)
	{
		if(gamer[pos].num==A) totalScore+=11;	//A的分值为11
		else if(gamer[pos].num>ten)totalScore+=10;	//J,Q,K的分值为10
		else totalScore+=(int)gamer[pos].num;	//TWO~TEN分值为2~10
	}
	//分值大于21时,将A的分值改为1
	for(pos=0;totalScore>21&&pos<n;pos++)
	{
		if(gamer[pos].num==A) totalScore-=10;
	}
	return totalScore;
}

void Point21::ShowStatus(int num,bool hideFirstCard)
/*当num=0时,显示庄家当前状态,当num>0,显示第num个玩家的当前状态,
当hideFirstCard为真时,将隐藏首张扑克牌与总分,否则将显示首张牌与总分*/


{

	cout<<endl<<name[num]<<":";	//显示庄家或玩家姓名
	
	//根据庄家的状态隐藏或显示庄家首张牌的花色
	if(hideFirstCard)cout<<"<**庄家首张牌被隐藏**>";//隐藏首张牌
	else if(gamers[num][0].shape==clubs) cout<<"梅花";		
	else if(gamers[num][0].shape==diamonds) cout<<"方块";	
	else if(gamers[num][0].shape==hearts) cout<< "红桃";
	else if(gamers[num][0].shape==spades) cout<<"黑桃";	
	//输出庄家首张牌的面值
	if(hideFirstCard)  cout<<"";
	else if(gamers[num][0].num==A) cout<<"A ";	//A表示A
	else if(gamers[num][0].num==J) cout<<"J ";
	else if(gamers[num][0].num==Q) cout<<"Q ";	
	else if(gamers[num][0].num==K) cout<<"K ";
	else cout<<(int)gamers[num][0].num;
	for(int i=1;i<numcards[num];i++)
	{
	if(gamers[num][i].shape==clubs) cout<<"梅花";		

	else if(gamers[num][i].shape==diamonds) cout<<"方块";	

		else if(gamers[num][i].shape==hearts) cout<< "红桃";	

		else if(gamers[num][i].shape==spades) cout<<"黑桃";

//输出面值
		if (gamers[num][i].num==A) cout<<"A";
		else if(gamers[num][i].num==J) cout<<"J";
		else if(gamers[num][i].num==Q) cout<<"Q";
		else if(gamers[num][i].num==K) cout<<"K";
		else cout<<(int)gamers[num][i].num;
	}
	if(!hideFirstCard)
		cout<<"   总分值"<<GetTotalScore(gamers[num],numcards[num]);
	cout<<endl;
	if(GetTotalScore(gamers[num],numcards[num])>21)
		cout<<endl<<name[num]<<"引爆(超过21点啦 ! 结束啦)!"<<endl; 
}
void Point21::Game()
{
	Shuffle();	//洗牌
	int i,j;
	//为庄家发两张牌
	for(i=0;i<2;i++)
		gamers[0][numcards[0]++]=FirstCard();
		
	ShowStatus(0,true);	//显示庄家状态,隐藏首张牌与总分
	//向各玩家发牌并显示
	for(i=1;i<=numgamer;i++)
	{
		for(j=0;j<2;j++)
		gamers[i][numcards[i]++]=FirstCard();
		ShowStatus(i);
	}
	cout<<endl;
	//依次向各玩家发额外的牌
	for(i=1;i<=numgamer;i++)
	{
		char p;
		cout<<endl<<name[i]<<",你还想再要一张牌吗?如果要请输入1,不要请输入0:";
		cin>>p;
		//玩家选择再要一张牌,如果玩家没有引爆则继续发牌
		//switch(p)
		//{
		while(p!='1' && p!='0')
		{
			cout<<"你的输入不正确,请重新输入。"<<endl;
			cout<<name[i]<<",你还想再要一张牌吗?如果要请输入1,不要请输入0:";
			cin>>p;
		}
		
		while (GetTotalScore(gamers[i],numcards[i])<=21&&p=='1')
		{
			gamers[i][numcards[i]++]=FirstCard();
			ShowStatus(i);
			//玩家引爆则跳出循环
			if(GetTotalScore(gamers[i],numcards[i])>21) break;
			cout<<endl<<name[i]<<",你想再要一张牌吗?如果要请输入1,不要请输入0:";
			cin>>p;
		}	
		//}
	}
	ShowStatus(0);	//显示庄家
	//庄家总分小于等于16,必须再拿牌
	while(GetTotalScore(gamers[0],numcards[0])<=16)
	{
		gamers[0][numcards[0]++]=FirstCard();	//为庄家发1张牌
		ShowStatus(0);	//显示庄家
	}
	cout<<endl;
	//庄家引爆,没有引爆的所有人赢
	if(GetTotalScore(gamers[0],numcards[0])>21)
	{
		for(i=1;i<=numgamer;i++)
		{	//依次查看每位玩家
			if(GetTotalScore(gamers[i],numcards[i])<=21)
				cout<<name[i]<<",恭喜你,庄家引爆,而你没有超过21点,你赢了!"<<endl;//玩家没有引爆
			else cout<<name[i]<<",唉,可惜超过21点了,打了平局!"<<endl;//玩家引爆
		}
	}
	else
	{//庄家没有引爆,依次查看每位玩家
		for(i=1;i<=numgamer;i++)
		{//总分比庄家大
			if(GetTotalScore(gamers[i],numcards[i])<=21&&GetTotalScore(gamers[i],numcards[i])>GetTotalScore(gamers[0],numcards[0]))
			{//玩家未引爆,且总分比庄家大,玩家赢
				cout<<name[i]<<",恭喜你,你最接近21点,你赢了!"<<endl;		
			}
			else if(GetTotalScore(gamers[i],numcards[i])==GetTotalScore(gamers[0],numcards[0]))
			{//玩家总分与庄家相等,平局
				cout<<name[i]<<",唉,可惜了你与庄家总分相同,打了平局!"<<endl;
			}
			else
			{//玩家引爆或总分比庄家小,玩家输
				cout<<name[i]<<",对不起,你输了!(爆了或者庄家更接近21点)"<<endl;		
			}
		}
	}
}


主文件main:
#include "paimiansheji.h"

#include "wanjiasheji.h"
int main()
{		
	char AgainGame;
	do
	{
		Point21 newGame;	
		newGame.Game();
		cout<<endl<<endl<<"***************************************************";
		cout<<endl<<"你想再玩一次吗,再玩请输入1,退出请输任意内容并回车:";
		
		cin>>AgainGame;
		cout<<endl<<"***************************************************";
	} while(AgainGame=='1');
	return 0;
}

五、程序运行结果测试与分析

结果测试
i.一位玩家:
在这里插入图片描述
ii.二位玩家(多位玩家以此类推)
在这里插入图片描述

分析:

i.重载运算符时报错,后发现输入错误解决;
在这里插入图片描述
ii.赋值判断语句错误;
在这里插入图片描述
iii.还有一些也是属于粗心导致的语法错误,经过细心纠察最终得以解决;

六、结论与心得

完整资源免费:
https://download.csdn.net/download/orangechenz/10730956

21小游戏C++版) cout 阅读详情

相关推荐

c++小游戏大集结【免费复制源码】

1.狼人杀 这是一个小游戏,感兴趣的可以看看 代码如下: #include<bits/stdc++.h> #include<cstdio> #include<cstdlib> #include<ctime> #include<windows.h> using namespace std; struct IDname { int geshu; string NAME; }; I...

1 17万+

C++小游戏21扑克牌

在本篇文章中,我们将介绍如何使用C++编程语言创建一个简单的扑克牌21游戏。玩家的目标是使手中的牌的数之和尽可能接近21,但不能超过21。以上是一个简单的扑克牌21游戏实现。然后,玩家可以选择是否继续抽取更多的牌,直到他们决定停止或超过21。最后,比较玩家和庄家的数,以确定胜负。类管理游戏的流程,包含了游戏的开始、玩家抽牌、庄家抽牌和判断胜负等功能。类表示一张牌,具有花色和数信息,并能返回牌的数值。类表示玩家,包含了玩家的手牌和计算手牌数的功能。对象,并具有抽取牌和洗牌的功能。

CodeRoarX的博客 835

[内附完整源码和文档] 基于mfc实现21小游戏

1.系统的介绍 1.1 计的目的与意义 21游戏是一款经典的扑克牌游戏,由古至今衍生的各种各样的规则和玩法,游戏计旨在为平淡的生活带来乐趣,以及最重要的,通过对游戏计来实现练习,实际操作,学习他人程序优,通过研究,了解需求并计程序,掌握题的基本步骤和方法。 1.2 本计的主要内容 程序使用较为简单的游戏规则:玩家与电脑对战,使用一副没有大小王的扑克,游戏开始后,起始发两张手牌,玩家可根据所持牌的数选择继续要牌或开牌,使得自己牌的数尽可能接近但不超过21,玩家最多可要5张牌,开牌

LEMFOooO的博客 1741

C++扑克牌21游戏

我们需要创建一个Card类表示单张扑克牌,Card类包含两个私有成员变量:面值和花色。玩家的手牌将存储在Hand类中,每个Hand对象包含一个std::vector,其中存储了该手牌中的每张牌。每张牌有一个数,2到10的牌面值等于它的数,J、Q和K的牌面值为10,A的牌面值可以是1或者11。每个玩家的初始牌面数量为两张,玩家可以从牌堆中抽取额外的牌,直到他们决定停止或他们超过21。扑克牌21是一种经典的纸牌游戏,玩家需要通过抽取牌来使手中的牌总数接近21但不超过21,否则就输掉比赛。

DarcyCode的博客 641

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

C++程序 :“21 "纸牌游戏实验题目:代码: 实验题目: ​ “21”是一个古老的扑克牌游戏游戏规则是:各个参与者法使自己的牌达到总分21而不超过这个数值。扑克牌的分值取它们的面值,A充当1分或者11分(由玩家自己选择一种分值),J.Q和K 人头牌都是10分。 ​ 庄家对付1~7个玩家。在一局开始时,包括庄家在内的所有参与者都有两张牌。玩家可以看到他们的所有牌以及总分,而庄家有一张牌暂时是隐藏的。接下来,只要愿意,各个玩家都有机会依次再拿-张牌。 如果某个玩家的总分超

唯一的博客 5518

C++小游戏:扑克牌21

21扑克牌游戏:程序说明:该程序是模拟21扑克牌游戏,玩家最多可以要5张牌,但是如果牌的数之和超过21,则自动出局,在不超过21的情况下,玩家与庄家比牌的大小,大者为赢家程序片...

李肖遥的专栏 2198

c++编写手机小游戏代码_C++编写的21小游戏代码

#include#include#includeusing namespace std;#define NUM 1000int j=2;//定义为全局变量int randNum[NUM];//因为rand()函数有一定的缺陷,所以在程序中定义了randNum数组来存放随机数//即使使用了种子函数srand(),由于程序运行时间比较短,也不太好置种子。因此使用数组来存放随机数class Poker...

weixin_39782394的博客 1127

C语言小游戏:和电脑玩21游戏

初学C++,或者说初学面向对象的编程思想,便写了一个模拟21游戏的程序,与电脑对弈,似乎没有感觉到电脑的无脑,换言之,虽然我用了很简单的策略判断,但在这个游戏中,电脑仍然表现出一定智能。这里先卖个关子,大家可以自己找找源代码,看看我用了什么策略。 先来看看运行效果: 输了,再看一个赢的: 你可以在此链接下载本工程的源代码,然后直接打开exe文件先玩一下试试:此打开网页。本次是在C-Free5...

我的blog屋 4044

c++21小游戏(极简)

c++21游戏

我的博客 2938

Python 21小游戏源码项目实战下载

Python凭借其简洁的语法和强大的第三方库支持,在游戏开发领域逐渐崭露头角,尤其适合快速原型开发与中小型2D项目。相较于C++或C#,Python降低了入门门槛,同时借助pygame这一成熟多媒体框架,开发者可高效实现图形渲染、事件响应、音效播放等核心功能。本章以21(Blackjack)小游戏为实践载体,明确项目技术栈:基于pygame构建显示界面与交互逻辑,整合事件驱动机制与时间控制模块,完成从牌组管理到状态流转的完整闭环。通过本项目,读者将系统掌握pygame。

weixin_42462474的博客 619

C++小游戏(原创)

#include #include #include using namespace std; double shanghai[20]={0.6,1.1,2,3.16,5.5,7,10,20,50,100,146.23,254.13,312,403,601,1023}; double bosshealth[20]={2,3,4,5.9,8,14,19,32,73,157,200,403,801,1

songyu005615的博客 4万+

21小游戏C++代码

#include #include #include using namespace std; #define NUM 1000 int j=2;//定义为全局变量 int randNum[NUM];//因为rand()函数有一定的缺陷,所以在程序中定义了randNum数组来存放随机数                  //即使使用了种子函数srand(),由于程序运行时间比较短,也

鲁家志的专栏 8102

Cocos Creator 21游戏开发实战:从零到发布微信小游戏

游戏开发中,状态机是管理复杂逻辑的核心计模式,它通过定义有限状态和状态转换规则,确保游戏流程清晰可控。在Cocos Creator等游戏引擎中,结合模块化项目架构,状态机能有效提升代码可维护性。其技术价值在于分离游戏逻辑与表现,便于调试和扩展,广泛应用于回合制游戏、角色状态管理等场景。本文以21游戏为例,详细拆解了基于状态机的游戏逻辑实现,并深入探讨了针对微信小游戏的性能优化策略,特别是通过图集制作和分包加载来优化资源管理,有效控制包体大小,为小游戏开发提供完整实践路径。

weixin_33831673的博客 435
上一篇: 【EasyUI表单提交】解决使用EasyUI的表单验证和提交的问题
下一篇: 【mysql】错误号码:2003 can't connect to mysql server on 'localhost'解决方案
OrangeChenZ
博客等级 码龄8年 92粉丝 43原创
评论 6
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

OrangeChenZ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值