前言:欢迎转载,但请注明出处http://blog.csdn.net/jiadabin,因为原文可能会改动部分不足,最好从原文处阅读,同时也欢迎大家来点评丶吐槽!让我们大家共同进步......
前边一篇文章介绍了斗地主一般的发牌思路,今天我就分享一下有点难度的的分配发牌算法,欢迎各位提意见!
需求是这样的:每局3个玩家手中至少有一个玩家手中有一个炸弹并且是随机发出的。
解决思路是这样的:
其实54张牌我们可以定义成一个这样的数组如下(其中元素为十六进制的数,括号内为十进制数)
static int card_arr[] = { 0x01(1 方块A), 0x11(17 梅花), 0x21(33 红桃), 0x31(49 黑桃),//A 0x02(2 方块2), 0x12(18 梅花), 0x22(34 红桃), 0x32(50 黑桃),//2 0x03(3 方块3), 0x13(19 梅花), 0x23(35 红桃), 0x33(51 黑桃),//3 0x04(4 方块4), 0x14(20 梅花), 0x24(36 红桃), 0x34(52 黑桃),//4 0x05(5 方块5), 0x15(21 梅花), 0x25(37 红桃), 0x35(53 黑桃),//5 0x06(6 方块6), 0x16(22 梅花), 0x26(38 红桃), 0x36(54 黑桃),//6 0x07(7 方块7), 0x17(23 梅花), 0x27(39 红桃), 0x37(55 黑桃),//7 0x08(8 方块8), 0x18(24 梅花), 0x28(40 红桃), 0x38(56 黑桃),//8 0x09(9 方块9), 0x19(25 梅花), 0x29(41 红桃), 0x39(57 黑桃),//9 0x0A(10 方块10), 0x1A(26 梅花), 0x2A(42 红桃), 0x3A(58 黑桃),//10 0x0B(11 方块J), 0x1B(27 梅花), 0x2B(43 红桃), 0x3B(59 黑桃),//J 0x0C(12 方块Q), 0x1C(28 梅花), 0x2C(44 红桃), 0x3C(60 黑桃),//Q 0x0D(13 方块K), 0x1D(29 梅花), 0x2D(45 红桃), 0x3D(61 黑桃),//K 0x0E(14小王), 0x0F(15大王) };
54张牌有了,下边我们针对这样的一副牌可以看出:1-13个数字就可以代表A-K了,所以我们就可以以这为基数,留下炸弹牌的基数,那么他另外的三张同值牌也就有了。
用一句来说也就是:先随机出1-N个炸弹,将炸弹的基数预留出来,在随机出每个玩家应该分配的炸弹数,把炸弹发给玩家,后其他牌随机发出即可。
下边请看具体代码:
<pre name="code" class="cpp">/*************************************************************************/ /***********斗地主发牌逻辑中级算法****************************************/ /*************************************************************************/ #include "stdafx.h" #include <iostream> #include <time.h> #include <iomanip> #include <vector> #include <set> #include <algorithm> // 定义在该标准头文件中random_shuffle()定义在标准的头文件<algorithm.h>中。 //因为所有的STL算法都是在名字空间std::中声明的所以你要注意正确地声 //明数据类型。random_shuffle()有两个参数第一个参数是指向序列首元 //素的迭代器第二个参数则指向序列最后一个元素的下一个位置。 using namespace std; void main() { //存储54张牌的数组 int card_arr[54] ={1,17,33,49,2,18,34,50,3,19,35,51,4,20,36,52,5,21,37,53,6,22,38,54,7,23,39,55,8,24,40,56,9,25,41,57, 10,26,42,58,11,27,43,59,12,28,44,60,13,29,45,61,14,15}; srand(time(NULL) + 1); //初始化随机数发送器 设置随机函数的启动数值 int bomb_num = rand() % 3; if (bomb_num == 0){ bomb_num =2; } //创建3个vector容器来装牌,注意容器是先进先出的。 vector<int> new_arr_vc; vector<int> other_card_vc; vector<int> last_all_cards; new_arr_vc.clear(); // 装炸弹基数牌 other_card_vc.clear();// 装除炸弹之外的牌 last_all_cards.clear();// 装所有洗好的牌 //new_arr_vc 0-12 共13个数字(玩家炸弹基数) for (int i = 0; i < 13; i++){ new_arr_vc.push_back(i); } random_shuffle(new_arr_vc.begin(), new_arr_vc.end()); //随机函数 将其打乱 for (int i = 12; i >=0; i--){ cout<<setw(3)<<new_arr_vc[i]; } cout<<endl; // 假设当炸弹数目为一个时 other_card_vc.size= (13-1)*4 =48 留四张牌凑一个炸弹 // 假设当炸弹数目为两个时 other_card_vc.size= (13-2)*4 =44 留八张牌凑两个炸弹 int othersize = 0; //调试时牌打印所用 for (int i = 0; i< 13 - bomb_num; i++){ for(int k=0; k < 4; k++){ other_card_vc.push_back(card_arr[new_arr_vc[bomb_num+i]*4+k]);//new_arr_vc[bomb_num+i] 跳过要保留为炸弹基数的牌值 cout<<setw(3)<<"other_card["<<othersize<<"]"<<other_card_vc[othersize]<<" pock base: "<<new_arr_vc[bomb_num+i]<<" "; othersize++; } cout<<endl; } cout<<endl; cout<<setw(3)<<"other_card_vc.size="<<other_card_vc.size()<<endl; other_card_vc.push_back(card_arr[52]); // 加入小王 other_card_vc.push_back(card_arr[53]); // 加入大王 random_shuffle(other_card_vc.begin(), other_card_vc.end()); //随机函数 将其打乱 cout<<setw(3)<<"other_card_vc.size="<<other_card_vc.size()<<endl; // 随机玩家炸弹数 unsigned int b_num1 = 0; unsigned int b_num2 = 0; unsigned int b_num3 = 0; int flag = rand() % 3; switch(bomb_num) { case 0: b_num1 = 0; b_num2 = 0; b_num3 = 0; break; case 1: if (flag == 0){ b_num1 = 1; b_num2 = 0; b_num3 = 0; }else if (flag == 1){ b_num1 = 0; b_num2 = 1; b_num3 = 0; }else{ b_num1 = 0; b_num2 = 0; b_num3 = 1; } break; case 2: if (flag == 0){ b_num1 = rand() % 3; b_num2 = rand() % 3; if (b_num1 + b_num2 >= 3){ b_num1--; b_num2--; } b_num3 = bomb_num - b_num1 - b_num2; }else if (flag == 1){ b_num1 = rand() % 3; b_num3 = rand() % 3; if (b_num1 + b_num3 >= 3){ b_num1--; b_num3--; } b_num2 = bomb_num - b_num1 - b_num3; }else{ b_num2 = rand() % 3; b_num3 = rand() % 3; if (b_num2 + b_num3 >= 3){ b_num2--; b_num3--; } b_num1 = bomb_num - b_num2 - b_num3; } break; case 3: if (flag == 0){ b_num1 = rand() % 4; b_num2 = rand() % 4; if (b_num1 + b_num2>=4 && b_num1 + b_num2<=5){ b_num1--; b_num2--; }else if (b_num1 + b_num2 >= 6){ b_num1 = b_num1 - 2; b_num2 = b_num2 - 2; }else{ //.... } b_num3 = bomb_num - b_num1 - b_num2; }else if (flag == 1){ b_num1 = rand() % 4; b_num3 = rand() % 4; if (b_num1 + b_num3>=4 && b_num1 + b_num3<=5){ b_num1--; b_num3--; }else if (b_num1 + b_num3 >= 6){ b_num1 = b_num1 - 2; b_num3 = b_num3 - 2; }else{ //.... } b_num2 = bomb_num - b_num1 - b_num3; }else{ b_num2 = rand() % 4; b_num3 = rand() % 4; if (b_num2 + b_num3>=4 && b_num2 + b_num3<=5){ b_num2--; b_num3--; }else if (b_num2 + b_num3 >= 6){ b_num2 = b_num2 - 2; b_num3 = b_num3 - 2; }else{ //.... } b_num1 = bomb_num - b_num2 - b_num3; } break; default: break; } // 打印3个玩家分配到的炸弹数 cout<<setw(3)<<"----player1:b_num1="<<b_num1<<"----"<<endl; cout<<setw(3)<<"----player2:b_num2="<<b_num2<<"----"<<endl; cout<<setw(3)<<"----player3:b_num3="<<b_num3<<"----"<<endl; int bomb_tmp = 0; int other_card = 0; for (int i = 0; i < 54;){ if (last_all_cards.size() < 17){ // 该判断是为了预留出炸弹的位置 if (last_all_cards.size() < b_num1 * 4){ // 满足条件分配炸弹 new_arr_vc[bomb_tmp]得到炸弹基数 for (int j = 0; j < 4; j++){ last_all_cards.push_back(card_arr[new_arr_vc[bomb_tmp] * 4 + j]); cout<<setw(3)<<"player1["<<i<<"]**zhang**:"<<last_all_cards[i]<<endl; i++; } bomb_tmp++; }else{ last_all_cards.push_back(other_card_vc[other_card]); other_card++; cout<<setw(3)<<"player1["<<i<<"]zhang:"<<last_all_cards[i]<<endl; i++; } }else if (last_all_cards.size() >= 17 && last_all_cards.size() < 34){ // 该判断是为了预留出炸弹的位置 if (last_all_cards.size() < b_num2 * 4 + 17){ // 满足条件分配炸弹 for (int j = 0; j < 4; j++){ last_all_cards.push_back(card_arr[new_arr_vc[bomb_tmp] * 4 + j]); cout<<setw(3)<<"player2["<<i<<"]**zhang**:"<<last_all_cards[i]<<endl; i++; } bomb_tmp++; }else{ last_all_cards.push_back(other_card_vc[other_card]); other_card++; cout<<setw(3)<<"player2["<<i<<"]zhang:"<<last_all_cards[i]<<endl; i++; } }else if (last_all_cards.size() >= 34 && last_all_cards.size() < 51){ // 该判断是为了预留出炸弹的位置 if (last_all_cards.size() < b_num3 * 4 + 34){ // 满足条件分配炸弹 for (int j = 0; j < 4; j++){ last_all_cards.push_back(card_arr[new_arr_vc[bomb_tmp] * 4 + j]); cout<<setw(3)<<"player3["<<i<<"]**zhang**:"<<last_all_cards[i]<<endl; i++; } bomb_tmp++; }else{ last_all_cards.push_back(other_card_vc[other_card]); other_card++; cout<<setw(3)<<"player3["<<i<<"]zhang:"<<last_all_cards[i]<<endl; i++; } }else{ // 加入三张公共牌 last_all_cards.push_back(other_card_vc[other_card]); other_card++; cout<<setw(3)<<"common["<<i<<"]zhang:"<<last_all_cards[i]<<endl; i++; } } cout<<"last_all_cards size ="<<last_all_cards.size()<<endl; // 将54张牌打印出看效果 for (int i = 53; i >= 0; i--){ cout<<setw(3)<<last_all_cards[i]; } cout<<endl; system("pause"); }