目录
题目
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)</