前邊一篇文章介紹了斗地主一般的發牌思路,今天我就分享一下有點難度的的分配發牌算法,歡迎各位提意見!
需求是這樣的:每局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個炸彈,將炸彈的基數預留出來,在隨機出每個玩家應該分配的炸彈數,把炸彈發給玩家,後其他牌隨機發出即可。
下邊請看具體代碼:
/*************************************************************************/ /***********斗地主發牌邏輯中級算法****************************************/ /*************************************************************************/ #include "stdafx.h" #include#include #include #include #include #include // 定義在該標准頭文件中random_shuffle()定義在標准的頭文件中。 //因為所有的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 new_arr_vc; vector other_card_vc; vector 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< = 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< = 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< = 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< 測試部分效果如下:有不明白的也可以問我,有更好的方法的可以吐槽,大家互相學習,謝謝!