題目說明:
洗撲克牌的原理其實與亂數排列是相同的,都是將一組數字(例如1~N)打亂重新排列,只不過洗撲克牌多了一個花色判斷的動作而已。
題目解析:
初學者通常會直接想到,隨機產生1~N的隨機數並將之存入陣列中,后來產生的隨機數存入陣列前必須先檢查陣列中是否已有重復的數字,如果有這個數就不存入,再重新產生下一個數,運氣不好的話,重復的次數就會很多,程式的執行速度就很慢了,這不是一個好方法。
以1~52的隨機數排列為例好了,可以將陣列先依序由1到52填入,然后遍歷陣列,並隨機產生1~52的隨機數,將產生的隨機數當作索引取出陣列值,並與目前陣列走訪到的值相交換,如此就不用擔心隨機數重復的問題了,陣列遍歷完畢后,所有的數字也就重新排列了。
至於如何判斷花色?這只是除法的問題而已,取商數判斷花色,取余數判斷數字,您可以直接看程式比較清楚。
程序代碼:
#include <gtest/gtest.h> #include <vector> #include <time.h> using namespace std; void ShuffleCard(vector<int>& cards) { srand(time(0)); unsigned int nCount = cards.size(); for (unsigned int i = 0; i < nCount; ++i) { int nRand = rand() % nCount; int nTemp = cards[i]; cards[i] = cards[nRand]; cards[nRand] = nTemp; } } void InitCard(vector<int>& cards) { for (int i=1; i<=52; ++i) { cards.push_back(i); } } void ShowCard(const vector<int>& cards) { unsigned int nCount = cards.size(); for (unsigned int i = 0; i < nCount; ++i) { switch ((cards[i]-1) / 13) { case 0: wcout << L"桃"; break; case 1: wcout << L"心"; break; case 2: wcout << L"磚"; break; case 3: wcout << L"梅"; break; } unsigned int nValue = cards[i] % 13; wcout << nValue << L" "; if ((i+1) % 13 == 0) { wcout << endl; } } wcout << endl; } TEST(Algo, tShuffleCard) { vector<int> Cards; InitCard(Cards); ShuffleCard(Cards); ShowCard(Cards); ShuffleCard(Cards); ShowCard(Cards); }