目录
题目
4个人甲乙丙丁一起玩扑克牌,其中1-10各种花色纸牌分别为1-10,J、Q、K被记为11、12、13,大王小王都记为20.四种花色(方块、梅花、红桃、黑桃)分别被记为A、B、C、D。如红桃K表示为13C,分值13;方块5表示为5A,分值5;大王表示为20K,分值20;小王表示为20Q,分值20。
游戏过程如下:
1、洗牌:54张牌随机组合
2、4人排序:随机产生4人的拿牌顺序,拿牌顺序与出牌顺序相同。
3、分派:按拿牌顺序每人轮流拿牌,每人拿13张,最后两张留在桌面。
4、出牌:从第一个拿牌的人开始出牌(随即出牌),每一轮4人出牌,牌最大的获取当前轮次的四张牌。大小判定规则,纸牌分值大>纸牌分值小,相同指派分值,按照黑桃>红桃>梅花>方块。
算法思想
洗牌、四人排序以及随机出牌都是随机且不重复抽取。如果用随机函数直接随机生成数字然后再判定是否重复,这样算法复杂且时间复杂度高,可以逆向思考为生成一个随机排列的序号数组,然后顺序输出随机排列的序号数组。
牌面的大小判定可以先用一个循环判定数字大小,然后因为由字符的ASCII码值判定花色大小。
代码解析
- 构建对象Player(玩家)
Player的属性有名字、手中拥有的牌、出牌顺序、分数;
构造函数,在玩家对象被声明的时候,就要赋予玩家名字,将其分数置为0
Player(string name) //构造函数
{p_name = name;p_score = 0;}
对象声明
//玩家
class Player
{
private:
string p_name; //玩家的名字
int p_card_index[13]; //牌面的序号
vector<int> p_s_index; //随机的出牌顺序
int p_score; //玩家的得分
public:
Player(string name) //构造函数
{p_name = name;p_score = 0;}
string getName(){return p_name;}; // 查看名字
void saveCard(int n,int i){p_card_index[n] = i;}; //将第n轮分到了序号为i的牌保存下来
int getCard(int i); //第i轮随机出牌。输出出牌序号
int showCard(int i){return p_card_index[i];} //第i轮分到的牌
void addScore(int s){p_score += s;}; //分数增加s分
int getScore(){return p_score;}; //查看此时的分数
};
C++11的标准库中有一个函数shuffle()
函数原型:
template <class RandomAccessIterator, class URNG>
void shuffle (RandomAccessIterator first, RandomAccessIterator last, URNG&& g);
函数功能:
使用随机生成器g对元素[first, last)的容器内部元素进行随机排列
函数参数:
| first, last | g |
|---|---|
| 顺序容器迭代器的开头和结尾 | 随机数生成器的一个实例 |
card_index.push_back(i),向容器末尾添加新元素i。
seed = chrono::system_clock::now().time_since_epoch().count(),用seed来初始化生成器,避免出现重复的排列。
#include <algorithm> // std::move_backward
#include <random> // std::default_random_engine
#include <chrono> // std::chrono::system_clock
//将扑克牌顺序打乱
void rand_cards(vector<int>& card_index) //洗牌
{
for(int i=0; i<54; i++)
card_index.push_back(i);
//card_index[i]=i;
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(card_index.begin(),card_index.end(),default_random_engine(seed));
}
void rand_players(vector<int>& s_players) //四人排序
{
for(int i=0; i<4; i++)
s_players.push_back(i);
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(s_players.begin(),s_players.end(),default_random_engine(seed));
}
int Player::getCard(int i)//对象的成员函数,生成每个玩家的随机出牌顺序
{
for(int i=0; i<13; i++)
p_s_index.push_back(i);
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(p_s_index.begin(),p_s_index.end(),default_random_engine(seed));
return p_card_index[p_s_index[i]];//根据生成的顺序从自己所拥有的牌中抽取
}
分牌,将打乱顺序的牌按照之间随机的四人分派顺序分配给玩家。
void deal_cards(Player* p,vector<int> s_players,vector<int> card_index)//分牌
{
int t=0; //记录轮次
for(int i=0; i<52; i++)
{
if(i%4==0&&i!=0)//每过4人就到了下一轮
t++;
p[s_players[i%4]].saveCard(t,card_index[i]);
}
}
玩家出牌并比较各自的牌大小,最大的拿分
void play_cards(Player* p) //出牌
{
for(int i=0;i<13;i++)
{
int win = Compare_cards(i,p); //找出第i轮胜利者
int score = 0;
for(int j=0;j<4;j++) //算出总分
score += getValue(p[j].getCard(i));
p[win].addScore(score);
}
}
int Compare_cards(int i,Player p[])//比较第i轮四个人谁赢
{
int p_num[4]; //四个人第i轮的牌面序号
for(int j=0; j<4; j++)
p_num[j] = p[j].getCard(i);
int maxp[4]= {1,0,0,0}; //假设最大的是第一个人
int maxj=0;
for(int j=1; j < 4; j++) //选出数字最大者
{
if(getValue(p_num[j]) > getValue(p_num[maxj]))//若比最大者大,则更改记录
{ maxp[maxj] = 0;maxp[j] = 1;maxj = j;}
else if(getValue(p_num[j]) == getValue(p_num[maxj]))//若相等,则加入记录
maxp[j] = 1;
}
for(int j=0; j<4; j++) //选出字母最大者
if(maxp[j])
{int bigger = Bigger_pattern(p_num[j], p_num[maxj]);
if(p_num[j] == bigger)
maxj = j;}
return maxj;
}
int Bigger_pattern(int a,int b) //a,b为花色序号,只比较花色
{
string a_s,b_s; //序号转化为牌面
a_s = cards[a];
b_s = cards[b];
char a_ch,b_ch;//牌面转化为花色
a_ch = a_s[a_s.length()-1];
b_ch = b_s[b_s.length()-1];
switch(a_ch)//花色为K、Q单独讨论,为A~D直接用ASCII码计算
{
case 'K':
return a;
case 'Q':
if(b_ch=='K')
return b;
else
return a;
case 'D':
case 'C':
case 'B':
case 'A':
return (a_ch-b_ch)?a:b;
default:cout<<"pattern error"<<endl;break;
}
}
完整代码
#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<random>
#include<chrono>
using namespace std;
//卡牌
const string cards[54] {"1A","2A","3A","4A","5A","6A","7A","8A","9A","10A","11A","12A","13A","1B","2B","3B","4B","5B","6B","7B","8B","9B","10B","11B","12B","13B","1C","2C","3C","4C","5C","6C","7C","8C","9C","10C","11C","12C","13C","1D","2D","3D","4D","5D","6D","7D","8D","9D","10D","11D","12D","13D","20K","20Q"};
//玩家
class Player
{
private:
string p_name;//玩家的名字
int p_card_index[13];//牌面的序号
vector<int> p_s_index;//随机的出牌顺序
int p_score;//玩家的得分
public:
Player(string name) //构造函数
{p_name = name;p_score = 0;};
string getName(){return p_name;};//查看名字
void saveCard(int n,int i){p_card_index[n] = i;};//第n轮分到了序号为i的牌
int getCard(int i);//第i轮出牌序号
int showCard(int i){return p_card_index[i];};//第i轮拿到的牌
void addScore(int s){p_score += s;};//分数增加s分
int getScore(){return p_score;};//查看此时的分数
};
int getValue(int i);//将卡牌序号转化为分数
int Compare_cards(int i,Player* p_play);//比较第i轮四个人谁赢
int Bigger_pattern(int a,int b);//两个花色比较
int win_player(Player p[]);//最终胜利的人
void rand_cards(vector<int>& card_index);//洗牌
void rand_players(vector<int>& s_players);//四人排序
void deal_cards(Player* p,vector<int> s_players,vector<int> card_index);//分牌
void play_cards(Player* p);//出牌
void show(Player p_play[4]);//展示结果
int main()
{
Player p_play[4]={Player("甲"),Player("乙"),Player("丙"),Player("丁")};//四个人玩
vector<int> card_index;//54张牌
vector<int> s_players;//四人分牌顺序
rand_players(s_players);//四人排序
rand_cards(card_index);//洗牌
deal_cards(p_play,s_players,card_index);//分牌
play_cards(p_play);//出牌
show(p_play);//展示结果
return 0;
}
int getValue(int i)//将卡牌序号转化为分数
{
string s = cards[i];
int value = 0;
for(int i = 0; i<s.length()-1; i++)
value = value*10 + s[i]-'0';
return value;
}
int Compare_cards(int i,Player p[])//比较第i轮四个人谁赢
{
int p_num[4]; //四个人第i轮的牌面序号
for(int j=0; j<4; j++)
{
p_num[j] = p[j].getCard(i);
}
int maxp[4]= {1,0,0,0}; //假设最大的是第一个人
int maxj=0;
for(int j=1; j < 4; j++) //选出数字最大者
{
if(getValue(p_num[j]) > getValue(p_num[maxj]))
{maxp[maxj] = 0;maxp[j] = 1;maxj = j;}
else if(getValue(p_num[j]) == getValue(p_num[maxj]))
maxp[j] = 1;
}
//选出字母最大者
for(int j=0; j<4; j++)
if(maxp[j])
{int bigger = Bigger_pattern(p_num[j], p_num[maxj]);
if(p_num[j] == bigger)
maxj = j; }
return maxj;
}
int Bigger_pattern(int a,int b) //a,b为花色序号,只比较花色
{
string a_s,b_s;
a_s = cards[a];
b_s = cards[b];
char a_ch,b_ch;
a_ch = a_s[a_s.length()-1];
b_ch = b_s[b_s.length()-1];
switch(a_ch)
{
case 'K':
return a;
case 'Q':
if(b_ch=='K')
return b;
else
return a;
case 'D':
case 'C':
case 'B':
case 'A':
return (a_ch-b_ch)?a:b;
default:cout<<"pattern error"<<endl;break;
}
}
int win_player(Player p[]) //最终胜利的人
{
int maxi=0,maxScore=p[0].getScore(); //假设第一个人是最终胜利者
for(int i=1;i<4;i++)
{
int score = p[i].getScore();
if(score > maxScore)
{ maxScore = score;
maxi = i;}
}
return maxi;
}
void rand_cards(vector<int>& card_index) //洗牌
{
for(int i=0; i<54; i++)
card_index.push_back(i);
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(card_index.begin(),card_index.end(),default_random_engine(seed));
}
void rand_players(vector<int>& s_players) //四人排序
{
for(int i=0; i<4; i++)
s_players.push_back(i);
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(s_players.begin(),s_players.end(),default_random_engine(seed));
}
void deal_cards(Player* p,vector<int> s_players,vector<int> card_index) //分牌
{
int t=0;
for(int i=0; i<52; i++)
{
if(i%4==0&&i!=0)
t++;
p[s_players[i%4]].saveCard(t,card_index[i]);
}
}
void play_cards(Player* p) //出牌
{
for(int i=0;i<13;i++)
{
int win = Compare_cards(i,p); //找出第i轮胜利者
int score = 0;
for(int j=0;j<4;j++) //算出总分
score += getValue(p[j].getCard(i));
p[win].addScore(score);
}
}
void show(Player p[4]) //展示结果
{
for(int i = 0;i<4;i++)
{
cout<<p[i].getName();
for(int j = 0;j<13;j++)
{
cout<<cards[p[i].showCard(j)];
if(j==12)cout<<endl;
else cout<<" , ";
}
}
cout<<"得分:"<<endl;
for(int i =0;i<4;i++)
cout<<p[i].getName()<<" "<<p[i].getScore()<<endl;
cout<<"得分最多:"<<p[win_player(p)].getName();
}
int Player::getCard(int i)//生成随机出牌顺序
{
for(int i=0; i<13; i++)
p_s_index.push_back(i);
unsigned seed = chrono::system_clock::now().time_since_epoch().count();
shuffle(p_s_index.begin(),p_s_index.end(),default_random_engine(seed));
return p_card_index[p_s_index[i]];
}
版权声明:本文为weixin_43690010原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。