इस पृष्ठ पर
वीडियो पोकर विश्लेषण के लिए मेरी कार्यप्रणाली
मुझसे समय-समय पर एक सवाल पूछा जाता है कि मैं अपने वीडियो पोकर प्रोग्राम को एक मिनट से भी कम समय में पे टेबल का मूल्यांकन कैसे करवाता हूँ। यह पृष्ठ इसी प्रश्न का उत्तर देने का प्रयास करेगा।
मेरे मूल प्रोग्राम में सभी 2,598,960 शुरुआती हाथों को लूप करने और फिर सभी 32 संभावित तरीकों से कार्ड त्यागने के लिए एक क्रूर बल विधि का उपयोग किया गया था, जिसमें सभी पाँच कार्ड त्यागने पर सभी 1,533,939 प्रतिस्थापन कार्डों को लूप करना भी शामिल था। यह लगभग 1998 की बात है। उस समय मेरे कंप्यूटर पर, मैंने अनुमान लगाया था कि इसे पूरा करने में एक वर्ष से अधिक समय लगेगा। आज ऐसा प्रोग्राम केवल लगभग एक महीने का समय लेगा। हालाँकि, दो शॉर्टकट से आप समय को लगभग एक महीने से घटाकर लगभग तीन सेकंड कर सकते हैं। इसे कैसे करें, यह नीचे बताया गया है।
कुछ दिनों तक चलने वाले समय को कम करने के लिए, आप सौदे पर समान हाथों का विश्लेषण करने से बच सकते हैं। उदाहरण के लिए, यदि शुरुआती हाथ चार इक्के और एक बादशाह थे, तो इससे कोई फर्क नहीं पड़ता कि बादशाह किस सूट का था। बादशाह को एक मनमाना सूट सौंपने और परिणामों को चार से गुणा करने से कुछ समय की बचत होगी। इसी तर्क का उपयोग करके, विभिन्न प्रकार के शुरुआती हाथों की संख्या 2,598,960 से घटाकर 134,459 की जा सकती है। निम्नलिखित तालिकाएँ रैंक के अनुसार प्रत्येक वर्ग के हाथों के लिए सूट और संबंधित भार को व्यवस्थित करने के तरीके दर्शाती हैं।
पाँच सिंगलटनसभी संयोजनों (13,5) = 1,287 संभावित तरीकों से लूप करके 13 में से 5 अलग-अलग रैंक चुनें। रैंकों के प्रत्येक संयोजन के लिए, सूट (1 से 4 तक क्रमांकित) और भारांक इस प्रकार निर्धारित करें। उदाहरण के लिए, पहली पंक्ति प्रत्येक सिंगलटन रैंक के लिए 1 के सूट को निर्धारित करती है। चार संभावित सूट हैं, इसलिए इसे चार बार करने के बजाय, एक बार करें और परिणामों को 4 के भारांक से गुणा करें।
पाँच अद्वितीय रैंक
| गाओ. 1 | गाओ. 2 | गाओ. 3 | गाओ. 4 | गाओ।5 | class="data-heading">वजन|
|---|---|---|---|---|---|
| 1 | 1 | 1 | 1 | 1 | 4 |
| 2 | 1 | 1 | 1 | 1 | 12 |
| 1 | 2 | 1 | 1 | 1 | 12 |
| 1 | 1 | 2 | 1 | 1 | 12 |
| 1 | 1 | 1 | 2 | 1 | 12 |
| 1 | 1 | 1 | 1 | 2 | 12 |
| 2 | 2 | 1 | 1 | 1 | 12 |
| 2 | 1 | 2 | 1 | 1 | 12 |
| 2 | 1 | 1 | 2 | 1 | 12 |
| 2 | 1 | 1 | 1 | 2 | 12 |
| 1 | 2 | 2 | 1 | 1 | 12 |
| 1 | 2 | 1 | 2 | 1 | 12 |
| 1 | 2 | 1 | 1 | 2 | 12 |
| 1 | 1 | 2 | 2 | 1 | 12 |
| 1 | 1 | 2 | 1 | 2 | 12 |
| 1 | 1 | 1 | 2 | 2 | 12 |
| 2 | 3 | 1 | 1 | 1 | 24 |
| 2 | 1 | 3 | 1 | 1 | 24 |
| 2 | 1 | 1 | 3 | 1 | 24 |
| 2 | 1 | 1 | 1 | 3 | 24 |
| 1 | 2 | 3 | 1 | 1 | 24 |
| 1 | 2 | 1 | 3 | 1 | 24 |
| 1 | 2 | 1 | 1 | 3 | 24 |
| 1 | 1 | 2 | 3 | 1 | 24 |
| 1 | 1 | 2 | 1 | 3 | 24 |
| 1 | 1 | 1 | 2 | 3 | 24 |
| 1 | 1 | 2 | 2 | 3 | 24 |
| 1 | 2 | 1 | 2 | 3 | 24 |
| 1 | 2 | 2 | 1 | 3 | 24 |
| 1 | 1 | 2 | 3 | 2 | 24 |
| 1 | 2 | 1 | 3 | 2 | 24 |
| 1 | 2 | 2 | 3 | 1 | 24 |
| 1 | 1 | 3 | 2 | 2 | 24 |
| 1 | 2 | 3 | 1 | 2 | 24 |
| 1 | 2 | 3 | 2 | 1 | 24 |
| 1 | 3 | 1 | 2 | 2 | 24 |
| 1 | 3 | 2 | 1 | 2 | 24 |
| 1 | 3 | 2 | 2 | 1 | 24 |
| 3 | 1 | 1 | 2 | 2 | 24 |
| 3 | 1 | 2 | 1 | 2 | 24 |
| 3 | 1 | 2 | 2 | 1 | 24 |
| 4 | 4 | 1 | 2 | 3 | 24 |
| 4 | 1 | 4 | 2 | 3 | 24 |
| 4 | 2 | 3 | 4 | 1 | 24 |
| 4 | 1 | 2 | 3 | 4 | 24 |
| 1 | 4 | 4 | 2 | 3 | 24 |
| 1 | 4 | 2 | 4 | 3 | 24 |
| 1 | 4 | 2 | 3 | 4 | 24 |
| 2 | 3 | 4 | 4 | 1 | 24 |
| 2 | 3 | 4 | 1 | 4 | 24 |
| 1 | 2 | 3 | 4 | 4 | 24 |
जोड़ा
जोड़ी के लिए एक रैंक चुनने के सभी 13×combin(12,3)=2,860 संभावित तरीकों से लूप करें, और तीन सिंगलटन के लिए शेष 12 में से तीन रैंक चुनें। रैंक के प्रत्येक संयोजन के लिए, सूट (संख्या 1 से 4 तक) और भारांक इस प्रकार निर्धारित करें। उदाहरण के लिए, पहली पंक्ति जोड़ी के सूट को 1 और 2 पर सेट करती है, और सभी सिंगलटन के सूट को 1 पर। जोड़ी के सूट चुनने के लिए combin(4,2)=6 तरीके हैं, और जोड़ी के किसी एक सूट के बराबर सिंगलटन के लिए सूट चुनने के 2 तरीके हैं, जिसका भारांक 6×2=12 है।
जोड़ा
| जोड़ी 1 | जोड़ी 2 | गाओ. 1 | गाओ. 2 | गाओ. 3 | वज़न |
|---|---|---|---|---|---|
| 1 | 2 | 1 | 1 | 1 | 12 |
| 1 | 2 | 1 | 1 | 2 | 12 |
| 1 | 2 | 1 | 2 | 1 | 12 |
| 1 | 2 | 2 | 1 | 1 | 12 |
| 1 | 2 | 1 | 1 | 3 | 24 |
| 1 | 2 | 1 | 3 | 1 | 24 |
| 1 | 2 | 3 | 1 | 1 | 24 |
| 1 | 2 | 1 | 3 | 3 | 24 |
| 1 | 2 | 3 | 1 | 3 | 24 |
| 1 | 2 | 3 | 3 | 1 | 24 |
| 1 | 2 | 3 | 3 | 3 | 12 |
| 1 | 2 | 1 | 2 | 3 | 24 |
| 1 | 2 | 1 | 3 | 2 | 24 |
| 1 | 2 | 3 | 1 | 2 | 24 |
| 1 | 2 | 3 | 4 | 4 | 12 |
| 1 | 2 | 4 | 3 | 4 | 12 |
| 1 | 2 | 4 | 4 | 3 | 12 |
| 1 | 2 | 1 | 3 | 4 | 24 |
| 1 | 2 | 3 | 1 | 4 | 24 |
| 1 | 2 | 3 | 4 | 1 | 24 |
दो जोड़ी
दो जोड़ों के लिए 13 में से दो रैंक चुनने के लिए सभी combin(13,2)×11=858 संभावित तरीकों से गुजरें, और सिंगलटन के लिए 11 में से एक रैंक छोड़ दें। रैंकों के प्रत्येक संयोजन के लिए, सूट (संख्या 1 से 4) और भार को निम्नानुसार सेट करें। उदाहरण के लिए, पहली पंक्ति पहली जोड़ी के सूट को 1 और 2 पर सेट करती है, दूसरी जोड़ी के सूट को 3 और 4 पर और सिंगलटन के सूट को 1 पर सेट करती है। पहली जोड़ी के लिए सूट चुनने के लिए combin(4,2)=6 तरीके हैं। दूसरी जोड़ी में अन्य दो सूट हैं, इसलिए उन्हें चुनने के लिए केवल एक 1 है। सिंगलटन के पास पहली जोड़ी में से कोई भी सूट हो सकता है, इसलिए दो संभावनाएं हैं। इस प्रकार पहली पंक्ति में भार 6×1×2=12 है।
दो जोड़ी
| जोड़ी 1 कार्ड 1 | जोड़ी 1 कार्ड 2 | जोड़ी 2 कार्ड 1 | जोड़ी 2 कार्ड 2 | गाओ. 1 | वज़न |
|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 1 | 12 |
| 1 | 2 | 3 | 4 | 3 | 12 |
| 1 | 2 | 1 | 3 | 1 | 24 |
| 1 | 2 | 1 | 3 | 2 | 24 |
| 1 | 2 | 1 | 3 | 3 | 24 |
| 1 | 2 | 1 | 3 | 4 | 24 |
| 1 | 2 | 1 | 2 | 1 | 12 |
| 1 | 2 | 1 | 2 | 3 | 12 |
तीन हास्य अभिनेता
सभी 13×combin(12,2)=858 संभावित तरीकों से गुजरें, जिसमें एक तरह के तीन के लिए 13 में से एक रैंक और अन्य 12 रैंक से दो सिंग्टन चुनने के 66 तरीके शामिल हैं। रैंक के प्रत्येक संयोजन के लिए, सूट (संख्या 1 से 4) और भारांक को इस प्रकार सेट करें। उदाहरण के लिए, पहली पंक्ति एक तरह के तीन के सूट को 1, 2 और 3 पर सेट करती है, और दो सिंगलटन के सूट को एक तरह के तीन में दर्शाए गए तीन सूट में से दो के बराबर सेट करती है। एक तरह के तीन के लिए 4 में से 3 सूट चुनने के लिए combin(4,3)=4 तरीके हैं, पहले सिंगलटन के लिए उन तीनों में से एक सूट चुनने के 3 तरीके हैं, और दूसरे सिंगलटन के लिए एक सूट चुनने के 2 तरीके हैं। इस प्रकार पहली पंक्ति के लिए भारांक 4×3×2=24 है।
तीन हास्य अभिनेता
| 3 प्रकार कार्ड 1 | 3 प्रकार कार्ड 2 | 3 प्रकार कार्ड 3 | गाओ. 1 | गाओ. 2 | वज़न |
|---|---|---|---|---|---|
| 1 | 2 | 3 | 1 | 2 | 24 |
| 1 | 2 | 3 | 1 | 4 | 12 |
| 1 | 2 | 3 | 4 | 1 | 12 |
| 1 | 2 | 3 | 1 | 1 | 12 |
| 1 | 2 | 3 | 4 | 4 | 4 |
पूरा घर
एक तरह के तीन के लिए 13 में से एक रैंक चुनने के सभी 13×12=156 संभावित तरीकों और जोड़ी के लिए रैंक चुनने के 12 तरीकों को लूप करें। रैंक के प्रत्येक संयोजन के लिए, सूट (1 से 4 तक क्रमांकित) और भारांक इस प्रकार निर्धारित करें। उदाहरण के लिए, पहली पंक्ति जोड़ी के सूट को 1 और 2 पर सेट करती है, और एक तरह के तीन के सूट को 1, 2 और 3 के बराबर रखती है। जोड़ी के लिए सूट चुनने के संयोजन(4,2)=6 तरीके हैं। एक तरह के तीन में दोनों जोड़ी सूट और अन्य दो में से एक का उपयोग किया जाता है। इस प्रकार पहली पंक्ति के लिए भारांक 6×2×2=12 है।
पूरा घर
| जोड़ा कार्ड 1 | जोड़ा कार्ड 2 | 3 प्रकार कार्ड 1 | 3 प्रकार कार्ड 2 | 3 प्रकार कार्ड 3 | वज़न |
|---|---|---|---|---|---|
| 1 | 2 | 1 | 2 | 3 | 12 |
| 1 | 4 | 1 | 2 | 3 | 12 |
एक तरह के चार
एक ही तरह के चार के लिए 13 में से एक रैंक चुनने के सभी 13×12=156 संभावित तरीकों और सिंगलटन के लिए रैंक चुनने के 12 तरीकों को लूप करें। रैंक के प्रत्येक संयोजन के लिए, सूट (1 से 4 तक क्रमांकित) और भारांक इस प्रकार निर्धारित करें। उदाहरण के लिए, पहली पंक्ति एक ही तरह के चार के सूट को 1, 2, 3 और 4 पर सेट करती है, और सिंगलटन के सूट को 1 के बराबर रखती है। एक ही तरह के तीन के लिए 4 में से 4 सूट चुनने का केवल एक ही तरीका है, और सिंगलटन के लिए 4 में से सूट चुनने के 4 तरीके हैं। इस प्रकार पहली पंक्ति के लिए भारांक 1×4×2=4 है।
एक तरह के चार
| 4 प्रकार कार्ड 1 | 4 प्रकार कार्ड 2 | 4 प्रकार कार्ड 3 | 4 प्रकार कार्ड 4 | गाओ. 1 | वज़न |
|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 1 | 4 |
उपरोक्त चरण गणना समय को 95% तक कम कर देगा, लेकिन यदि आप प्रतिस्थापन कार्डों के 1,533,939 संभावित संयोजनों को लूप में दोहराते हैं, तो इसमें अभी भी कई घंटे लगेंगे। तीन सेकंड के प्रोग्राम का रहस्य यह है कि ड्रॉ चरण में लूप न हो। इसे करने का तरीका यहां दिया गया है:
- निम्नलिखित सरणियों को आरंभ करें:
- सरणी 1: आकार 2,598,960
- सारणी 2: आकार 270,725 गुणा 16
- सारणी 3: आकार 22100 x 16
- सारणी 4: आकार 1326 x 16
- सरणी 5: आकार 52 x 16
- सरणी 6: आकार 16
- 52 में से 5 पत्तों के सभी 2,598,960 संयोजनों को लूप करें। इस समय 134,459 हाथ के शॉर्टकट का उपयोग न करें। डील पर प्रत्येक हाथ के लिए निम्नलिखित करें:
- इसे पोकर मूल्य के अनुसार स्कोर करें।
- स्कोर को array0 में डालें। पहले हाथ को array के तत्व 0 में डालें, और प्रत्येक हाथ के लिए 1 से बढ़ाएँ।
- डील पर 5 में से 4 कार्ड चुनने के 5 तरीकों में से प्रत्येक के लिए, चारों कार्डों को 0 से 270,724 तक के सूचकांक संख्या में अनुवाद करें (मैं बाद में समझाऊंगा कि यह कैसे करना है), और array1 के तत्व [सूचकांक संख्या][हैंड स्कोर] को 1 से बढ़ाएं।
- डील पर 5 में से 3 कार्ड चुनने के 10 तरीकों में से प्रत्येक के लिए, तीन कार्डों को 0 से 22,099 तक एक इंडेक्स नंबर में अनुवाद करें, और array2 के तत्व [इंडेक्स नंबर][हैंड स्कोर] को 1 से बढ़ाएं।
- डील पर 5 में से 2 कार्ड चुनने के 10 तरीकों में से प्रत्येक के लिए, दो कार्डों को 0 से 1,325 तक एक इंडेक्स नंबर में अनुवाद करें, और array3 के तत्व [इंडेक्स नंबर][हैंड स्कोर] को 1 से बढ़ाएं।
- डील पर 5 में से 1 कार्ड चुनने के 5 तरीकों में से प्रत्येक के लिए, कार्ड को 0 से 51 तक एक इंडेक्स नंबर में अनुवाद करें, और array4 के तत्व [इंडेक्स नंबर][हैंड स्कोर] को 1 से बढ़ाएँ।
- array5 के तत्व [हैंड स्कोर] को 1 से बढ़ाएँ।
- इसके बाद, ऊपर बताए गए 134,459 हाथ वर्गों पर नजर डालें।
- सभी पांच कार्डों को रखने का मूल्य निर्धारित करने के लिए, पांच कार्डों को एक सूचकांक संख्या में अनुवाद करें, और पोकर मूल्य lin array0 देखें।
- किसी भी चार कार्ड रखने का मूल्य निर्धारित करने के लिए, चार कार्डों को एक इंडेक्स नंबर में बदलें, और सरणी 1 के संबंधित तत्व में ड्रॉ पर संभावित परिणामों को देखें। हालांकि, इसमें आपके द्वारा डील पर त्यागे गए कार्ड को प्राप्त करना शामिल होगा। इसलिए आपको सभी पांच कार्ड रखने के पोकर मूल्य से जुड़े सरणी के तत्व से एक घटाना चाहिए। उदाहरण के लिए, यदि आप J♣, Q♣, K♣, A♣ रखते हैं और 2♥ त्याग देते हैं तो रॉयल प्राप्त करने का 1 तरीका, फ्लश प्राप्त करने के 8 तरीके, स्ट्रेट प्राप्त करने के 3 तरीके, जैक की जोड़ी या बेहतर प्राप्त करने के 12 तरीके और हारने वाला हाथ प्राप्त करने के 23 तरीके होंगे। हालांकि, सरणी 1 बताएगा कि हारने वाला हाथ प्राप्त करने के 24 तरीके हैं, जिसमें ड्रॉ पर 2♥ प्राप्त करना भी शामिल है
- सुनिश्चित करें कि आप ऊपर दिए गए चरण के तर्क को समझते हैं, क्योंकि हम इसे इस चरण में अगले स्तर पर ले जाते हैं। किसी भी 3 कार्ड को रखने के 10 तरीकों के लिए आप सरणी 2 में संभावित परिणामों को देखेंगे। फिर आपके पास मौजूद 3 कार्डों और आपके द्वारा त्यागे जा रहे प्रत्येक कार्ड के लिए सरणी 1 से संभावित परिणामों को घटाएँ। उदाहरण के लिए, 2♣ 2♥ 2♠ को रखने और 4♥ और J♠ को त्यागने के मान के लिए, सरणी 2 में 2♣ 2♥ 2 और हुकुम के मानों से शुरू करें, और फिर 2♣ 2♥ 2♠ 4♥ और 2♣ 2♥ 2♠ J♠ के मानों को घटाएँ। हालाँकि, यह सभी पाँच कार्ड रखने पर दोगुना घटा देगा। इसलिए आपको सभी 5 कार्ड रखने पर जो मिलता है उसे वापस जोड़ना होगा।
- इसी तर्क से, किसी भी 2 कार्ड को रखने के लिए array3 में मानों से शुरू करें, array2 से कार्ड के उपयुक्त सेट को घटाएं, array1 से कार्ड के उपयुक्त सेट को वापस जोड़ें, और array0 से सब कुछ रखने के लिए तत्व को वापस घटाएं।
- 1 कार्ड रखने के लिए, array4 से संबंधित मानों से शुरू करें, array3 से उपयुक्त मानों को घटाएं, array2 से उपयुक्त मानों को वापस जोड़ें, array1 से उपयुक्त मानों को वापस घटाएं, और array0 से उपयुक्त मान वापस जोड़ें।
- सब कुछ हटाने के लिए array5 में मानों से शुरू करें, फिर array4 से उपयुक्त मानों को घटाएं, array3 से उपयुक्त मानों को वापस जोड़ें, array2 से उपयुक्त मानों को वापस घटाएं, array1 से उपयुक्त मानों को वापस जोड़ें, और array0 से उपयुक्त मान घटाएं।
- अब आपके पास हाथ खेलने के सभी 32 तरीकों के सभी संभावित परिणामों के संयोजनों की संख्या होनी चाहिए। प्रत्येक का अपेक्षित मान ज्ञात कीजिए। जिस चाल से सबसे अधिक अपेक्षित मान प्राप्त होता है, उस चाल के संभावित परिणामों को खेल के समग्र संभावित परिणामों की एक सरणी में जोड़ें। डील वाले हाथ के लिए संबंधित भार से गुणा करना याद रखें।
- सभी 134,459 प्रकार के शुरुआती हाथों को पार करने के बाद, आपके पास प्रत्येक हाथ को ड्रॉ पर लाने के तरीकों की संख्या होनी चाहिए। खेल का कुल रिटर्न निर्धारित करने के लिए इस सरणी का उपयोग करें।
2 से 5 कार्डों (0 से 51 तक क्रमांकित) का अनुवाद करने और सूचकांक मान लौटाने के लिए निम्नलिखित चार सबरूटीन हैं।
int HandIndex2(int c1, int c2){ int r; r=combin_array[52][2]-combin_array[52-c1][2]; r+=combin_array[51-c1][1]-combin_array[52-c2][1]; return r;}int HandIndex3(int c1, int c2, int c3){ int r; r=combin_array[52][3]-combin_array[52-c1][3]; r+=combin_array[51-c1][2]-combin_array[52-c2][2]; r+=combin_array[51-c2][1]-combin_array[52-c3][1]; return r;}int HandIndex4(int c1, int c2, int c3, int c4){ int r; r=combin_array[52][4]-combin_array[52-c1][4]; r+=combin_array[51-c1][3]-combin_array[52-c2][3]; r+=combin_array[51-c2][2]-combin_array[52-c3][2]; r+=combin_array[51-c3][1]-combin_array[52-c4][1]; return r;}int HandIndex5(int CardIndex[]){ int r; r=combin_array[52][5]-combin_array[52-CardIndex[0]][5]; r+=combin_array[51-CardIndex[0]][4]-combin_array[52-CardIndex[1]][4]; r+=combin_array[51-कार्डइंडेक्स[1]][3]-combin_array[52-कार्डइंडेक्स[2]][3]; r+=combin_array[51-कार्डइंडेक्स[2]][2]-combin_array[52-कार्डइंडेक्स[3]][2]; r+=combin_array[51-कार्डइंडेक्स[3]][1]-combin_array[52-कार्डइंडेक्स[4]][1]; return r;}लिंक
यह साइट बताती है कि कैसे लेखक ने अपने वीडियो पोकर विश्लेषक की गति एक वर्ष से बढ़ाकर सात सेकंड कर दी।
वीपी जीनियस के पास वीडियो पोकर प्रोग्रामिंग पर एक उत्कृष्ट पृष्ठ है।