斗地主游戲之洗牌算法


  斗地主之類的游戲大家都玩過,有沒有想過,游戲是如何給我們發牌的呢?

  我們先將問題做一下抽象:我們將撲克牌抽象為數字,那么洗牌的問題就轉化為

給定一個長度為54的整型數列,請將其順序隨機打亂,保證每個數出現在任意一個位置的概率相同。

朴素的想法——抽牌

每次隨機從牌堆中選一個位置抽牌,如果該位置的牌已被抽走,則繼續隨機選取位置,直到將所有牌抽完。

  顯然,這種做法時間復雜度很高。那么不妨稍微優化下。

每次隨機從牌堆中選一個位置抽牌,然后將該位置后面的牌依次向前移動一個位置,下一次從新牌堆(數量-1)中抽取,循環到抽完所有牌為止。

  這樣也能完成要求,單這樣的做法,對於數據規模比較小的數據可以接受,但數據量一旦變大,反而不如不優化的算法效率高。我們還得繼續想辦法優化。

每次隨機從牌堆中選一個位置抽牌,然后將最后一張牌移動到被選擇的位置,下一次從新牌堆(數量-1)中抽取,循環到抽完所有牌為止。

  這樣優化完以后,時間復雜度降低到了O(N),應該能滿足要求了。

經典的洗牌算法——交換

  上面的算法需要額外的輔助空間,那么能不能就地洗牌呢?答案當然是可以的。

還是每次隨機一個位置,然后將該位置上的牌與 i 位置上的牌交換,直到 i 遍歷玩所有位置為止。

 1 void MySwap(int &x, int &y)  
 2 {  
 3     int temp = x;  
 4     x = y;  
 5     y = temp;  
 6 }  
 7   
 8 void Shuffle(int n)  
 9 {  
10     for(int i=n-1; i>=1; i--)  
11     {  
12         MySwap(num[i], num[rand()%(i+1)]);  
13     }  
14 }  
洗牌算法

  該洗牌算法的時間復雜度為O(N),空間復雜度為O(N)。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM