C++扑克牌随机洗牌抽牌算法

C++扑克牌随机洗牌抽牌算法

目录

题目

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)</
  • 1
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值