【失踪人口回归】
高联延期了,在家考学校的考试,闲得无聊,重拾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环境下试试!