几个小时写了个uno
  • 板块灌水区
  • 楼主czm708033
  • 当前回复13
  • 已保存回复13
  • 发布时间2022/9/12 13:32
  • 上次更新2023/10/27 11:52:40
查看原帖
几个小时写了个uno
94046
czm708033楼主2022/9/12 13:32

【失踪人口回归】

高联延期了,在家考学校的考试,闲得无聊,重拾C++写了uno,格式奇丑,漏洞百出,敬请谅解! 话不多说,上代码

#include<iostream>
#include<ctime>
#include<cstdlib>
#include<queue>
#include<algorithm>
#include<winsock2.h>
#include<conio.h>
using namespace std;
const char CARDCOLOR[5]={'r','g','b','y','n'};
int PlayerNumber;
int CyclePoint=1;//1:clockwise -1:anticlockwise
int NowPlayerIndex=0;//Which player is playing now
int TotalPlusCards=0;//How many cards the next player need draw
bool GameOver=false,StartGame=true;
void ChangePlayer();//Change to the next player
void Print(int);//Print the screen
void Control();//Player's operation
void SetColor(int,int);
void AutoPlay(int);//Computer player
struct card{
	int type;//1:Number 2:Tool 3:Trump
	int data;//0~9:Number 10:Reverse 11:+2 12:ban 13:change 14:+4
	char color;//r g b y n(not color)
	card():type(),data(),color(){}
	card(int _type,int _data,char _color):type(_type),data(_data),color(_color){}
}IQIT[108],LastCard;//InputQueueInitTemporary
class inputqueue{
	private:
		queue<card> Q;
	public:
		void Shuffle(){//reset the queue
			while ( !Q.empty() )	Q.pop();
			int n=0;
			for ( int i=0 ; i<4 ; i++ )	IQIT[n++]=card(1,0,CARDCOLOR[i]);//"0"
			for ( int i=1 ; i<=12 ; i++ )//"1"-"9","Reverse","+2","ban"
				for ( int j=0 ; j<4 ; j++ )
					for ( int k=1 ; k<=2 ; k++ )	IQIT[n++]=card(i/10+1,i,CARDCOLOR[j]);
			for ( int i=13 ; i<=14 ; i++ )//"changecolor","+4"
				for ( int j=1 ; j<=4 ; j++ )	IQIT[n++]=card(3,i,CARDCOLOR[4]);
			random_shuffle(IQIT,IQIT+n);
			for ( int i=0 ; i<108 ; i++ )	Q.push(IQIT[i]);
		}
		card Give(){
			if ( Q.empty() )//If queue is empty, then shuffle
				Shuffle();//There is a bug: it can't remove cards which is in player's hand
			IQIT[0]=Q.front();
			Q.pop();
			return IQIT[0];
		}
}InputQueue;
struct player{
	card Cards[1024];
	int CardsNumber=0;
	void DrawCards(){//If player can't or don't want to play cards, then draw cards
		TotalPlusCards+=(TotalPlusCards==0)?1:0;//No plus cards, then only draw one card
		while ( TotalPlusCards-- )	Cards[++CardsNumber]=InputQueue.Give();//Draw cards
		TotalPlusCards=0;
	}
	bool PlayCard(int index){//Give an index and then play it
		if ( index<=0 || index>CardsNumber )	return false;//ineffective index
		LastCard=Cards[index];
		for ( int i=index ; i<CardsNumber ; i++ )	Cards[i]=Cards[i+1];
		CardsNumber--;
		if ( LastCard.type==2 && LastCard.data==11 )	TotalPlusCards+=2;//"+2"
		if ( LastCard.type==3 ){
			if ( LastCard.data==14 )	TotalPlusCards+=4;
			cout<<endl<<"请输入改的颜色:r/红、g/绿、b/蓝、y/黄"<<endl; 
			while ( 1 ){
				char r=getch();
				bool BreakWhileCycle=false;
				for ( int i=0 ; i<4 ; i++ )
					if ( r==CARDCOLOR[i] ){
						LastCard.color=r;
						BreakWhileCycle=true;
						break;
					}
				if ( BreakWhileCycle )
					break;
				cout<<"您的输入不符合条件,请重新输入!"<<endl;
			}
		}
		if ( LastCard.type==2 && LastCard.data==10 )	CyclePoint=-CyclePoint;//"Reverse"
		if ( LastCard.type==2 && LastCard.data==12 )	ChangePlayer();//"ban"
		if ( !CardsNumber )	GameOver=true;
		CheckHasNumber();
		return true;
	}
	bool ThisCardCanBePlayed(int index){
		if ( StartGame )	return true;
		if ( LastCard.type<3 ){
			if ( LastCard.data==11 && TotalPlusCards )
				return (Cards[index].data==11 || Cards[index].data==14)?true:false;//"+2"
			return (Cards[index].data==13//"changecolor"
			||Cards[index].data==14//"+4"
			||Cards[index].data==LastCard.data//same data
			||Cards[index].color==LastCard.color//same color
			)?true:false;
		}
		if ( LastCard.data==13 )	return ((Cards[index].color==LastCard.color) || (Cards[index].type==3))?true:false;//Change color
		if ( LastCard.data==14 && TotalPlusCards )	return (Cards[index].data==14)?true:false;//When you need play a "+4"
			else if (Cards[index].data==13//"changecolor"
				||Cards[index].data==14//"+4"
				||Cards[index].color==LastCard.color//same color
			)	return true;
		return false;
	}
	bool CanPlay(){
		if ( StartGame )
			return true;
		for ( int i=1 ; i<=CardsNumber ; i++ )
			if ( ThisCardCanBePlayed(i) )
				return true;
		return false;
	}
	void CheckHasNumber(){
		bool HaveNumber=false;
		for ( int i=1 ; i<=CardsNumber ; i++ )
			if ( Cards[i].data<10 ){
				HaveNumber=true;
				break;
			}
		if ( !HaveNumber ){
			int temp=TotalPlusCards;
			TotalPlusCards=0;
			do{
				DrawCards();
			}while ( Cards[CardsNumber].data>=10 );// Draw cards until get a digital card
			TotalPlusCards=temp;
		}
	}
}Player[20];//Less than 20 computers
int main(){
	srand(time(NULL));
	system("color F0");
	InputQueue.Shuffle();
	cout<<"请输入玩家数:";
	cin>>PlayerNumber;
	int StartCardsNumber;
	cout<<"请输入初始手牌数:";
	cin>>StartCardsNumber;
	for ( int i=0 ; i<PlayerNumber ; i++ ){//Give everyone cards
		TotalPlusCards=StartCardsNumber;
		Player[i].DrawCards();
		Player[i].CheckHasNumber();
	}
	Control();//You go first
	StartGame=false;
	while ( !GameOver ){
		if ( NowPlayerIndex )	Print(1);
		ChangePlayer();
		Sleep(1000);
		for ( int i=1 ; i<=20 ; i++ )	if ( kbhit() )	getch();//Ignore keyboard while others playing 
		if ( NowPlayerIndex==0 )	Control();//Player
		else	AutoPlay(NowPlayerIndex);//Computer
	}
	Print(1);
	cout<<"恭喜"<<NowPlayerIndex<<"号玩家获得胜利!"<<endl; 
	if ( !NowPlayerIndex )	MessageBox(nullptr,"恭喜您,获得胜利!","胜利!",MB_OK);
	else	MessageBox(nullptr,"很可惜您失败了!","失败!",MB_OK);
	return 0;
}
void ChangePlayer(){
	NowPlayerIndex+=CyclePoint;
	if ( NowPlayerIndex>=PlayerNumber )
		NowPlayerIndex=0;
	if ( NowPlayerIndex<0 )
		NowPlayerIndex=PlayerNumber-1;
}
void SetColor(char color){
	WORD data;
	switch ( color ){
		case 'r':data=((15&0x0f)<<4)+(4&0x0f);break;
		case 'g':data=((15&0x0f)<<4)+(2&0x0f);break;
		case 'b':data=((15&0x0f)<<4)+(1&0x0f);break;
		case 'y':data=((15&0x0f)<<4)+(6&0x0f);break;
		default:data=((15&0x0f)<<4)+(0&0x0f);break;
	}
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),data);
}
void Print(int NowChoice){
	system("cls");
	cout<<"对手编号:";
	for ( int i=1 ; i<PlayerNumber ; i++ ){
		if ( i==NowPlayerIndex ){
			WORD data;
			data=((0&0x0f)<<4)+(15&0x0f);
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),data);
		}
		cout<<i<<'\t';
		SetColor('n');
	}
	cout<<endl<<"对手牌数:";
	for ( int i=1 ; i<PlayerNumber ; i++ )	cout<<Player[i].CardsNumber<<'\t';
	cout<<endl;
	cout<<"当前出牌:";
	if ( LastCard.type==3 ){
		if ( LastCard.data==13 )	cout<<"改色";
		else	cout<<"+4";
		cout<<",调";
		SetColor(LastCard.color);
		switch ( LastCard.color ){
			case 'r':cout<<"红";break;
			case 'g':cout<<"绿";break;
			case 'b':cout<<"蓝";break;
			case 'y':cout<<"黄";break;
			default:cout<<"ERROR";
		}
	}
	else{
		SetColor(LastCard.color);
		if ( LastCard.type==1 )	cout<<LastCard.data;
		else
			switch ( LastCard.data ){
				case 10://"reverse". This character can tell you who is the next
					if ( CyclePoint==1 )	cout<<"<";
					else	cout<<">";
					break;
				case 11://"+2"
					cout<<"+2";break;
				case 12://"ban"
					cout<<"#";break;
			}
	}
	SetColor('n');
	cout<<"\n\n\n\n\n\n";//5 empty lines
	for ( int i=1 ; i<=Player[0].CardsNumber ; i++ ){
		if ( NowChoice==i )	cout<<"--> ";
		else	cout<<"    ";
		SetColor(Player[0].Cards[i].color);
		if ( Player[0].Cards[i].data<10 )	cout<<Player[0].Cards[i].data;
		else if ( Player[0].Cards[i].data==10 )	cout<<"<>";
		else if ( Player[0].Cards[i].data==11 )	cout<<"+2";
		else if ( Player[0].Cards[i].data==12 )	cout<<"#";
		else if ( Player[0].Cards[i].data==13 )	cout<<"调色板";
		else if ( Player[0].Cards[i].data==14 )	cout<<"+4";
		SetColor('n');
		cout<<endl;
	}
	cout<<"--------------------------------------------------"<<endl;
	cout<<"帮助:ws移动当前选择,回车键出牌,空格键摸牌(不能出牌时自动摸牌)"<<endl;
	cout<<"#代表ban,<>代表reverse。"<<endl; 
}
void Control(){
	int NowChoice=1;
	Print(1);
	if ( !Player[0].CanPlay() ){//Auto draw cards
		Player[0].DrawCards();
		return;
	}
	while ( 1 ){
		bool Operation=false;
		char r=getch();
		switch( r ){
			case 'w'://Move up the arrow
				if ( NowChoice!=1 ){
					NowChoice--;
					Print(NowChoice);
				}
				break;
			case 's'://Move down the arrow
				if ( NowChoice!=Player[0].CardsNumber ){
					NowChoice++;
					Print(NowChoice);
				}
				break;
			case 13://Play the card
				if ( Player[0].ThisCardCanBePlayed(NowChoice) ){
					Player[0].PlayCard(NowChoice);
					Operation=true;//An effective operation
				}
				else
					MessageBox(nullptr,"你不能打出这张牌!","出牌失败",MB_OK);
				break;
			case 32://Draw cards
				Player[0].DrawCards();
				Operation=true;
				break;
		}
		if ( Operation )
			break;
	}
}
void AutoPlay(int player){
	if ( !Player[player].CanPlay() ){
		Player[player].DrawCards();
		return;
	}
	for ( int i=1 ; i<=Player[player].CardsNumber ; i++ )
		if ( Player[player].ThisCardCanBePlayed(i) ){//A stupid computer who can only play the first card
			if ( Player[player].Cards[i].type<3 ){//Card which needn't be operatored can be played same as player
				Player[player].PlayCard(i);
				break;
			}
			char ChangeToColor;
			for ( int j=1 ; j<=Player[player].CardsNumber ; j++ )//A stupid computer who can only change color to the color of its first card  
				if ( Player[player].Cards[j].color!='n' ){
					ChangeToColor=Player[player].Cards[j].color;
					break;
				}
			Player[player].Cards[i].color=ChangeToColor;
			LastCard=Player[player].Cards[i];
			if ( LastCard.data==14 )
				TotalPlusCards+=4;
			for ( int j=i ; j<Player[player].CardsNumber ; j++ )	Player[player].Cards[j]=Player[player].Cards[j+1];
			Player[player].CardsNumber--;
			break;
		}
	Player[player].CheckHasNumber();
}

按照我们在学校玩的版本玩的,似乎确凿和标准玩法不同(例如+4没有质疑、相同牌能抢(然而偷懒没写)之类的) 可以复制粘贴在Windows环境下试试!

2022/9/12 13:32
加载中...