मैं कार्ड गेम के लिए कार्ड में फेरबदल कैसे कर सकता हूं?


13

मैं एंड्रॉइड के लिए एक कार्ड गेम विकसित करने की कोशिश कर रहा हूं क्या कोई मुझे सुझाव दे सकता है कि प्लेइंग कार्ड्स को प्रभावी ढंग से बदलने के लिए कोड कैसे लिखें?

जवाबों:


21

कार्ड फेरबदल एक एल्गोरिथ्म है जो सहज ज्ञान युक्त लिखना आसान है, और ऐसा करने से पूरी तरह से गलत हो जाता है। विकिपीडिया पर कार्ड फेरबदल को सही ढंग से लागू करने के लिए एक अच्छा संदर्भ है । जो मैं यहां प्रस्तुत कर रहा हूं वह आधुनिक एल्गोरिथ्म के तहत उस पृष्ठ पर शामिल किए गए एल्गोरिदम का बहुत थोड़ा सरलीकृत संस्करण है

यहाँ मूल विचार है, सादे अंग्रेजी में:

कार्ड के एक डेक पर विचार करें। इस चर्चा के लिए, आपके पास डेक में कितने भी कार्ड हो सकते हैं, और वे किसी भी क्रम में शुरू हो सकते हैं।

हम डेक में "स्थिति" के बारे में बात करने जा रहे हैं, जहां "स्थिति" उस स्थिति में कार्ड की तुलना में डेक में कितने कार्ड अधिक हैं। उदाहरण के लिए, डेक के ऊपर कार्ड स्थिति 0 पर है, जो कार्ड नीचे की स्थिति 1 पर है (क्योंकि इसमें 1 कार्ड अधिक है - शीर्ष कार्ड), और एक मानक 52-कार्ड डेक में, नीचे कार्ड 51 की स्थिति में है, क्योंकि डेक में 51 कार्ड इसकी तुलना में अधिक हैं।

अब, हम डेक में प्रत्येक स्थिति पर विचार करते हैं, एक समय में, नीचे से शुरू करते हुए, और ऊपर तक हमारा काम करते हैं।

प्रत्येक स्थिति के लिए, हम बेतरतीब ढंग से उन कार्डों में से एक का चयन करते हैं जो उस स्थिति में या कम-संख्या वाली स्थिति में है (याद रखें, डेक का शीर्ष 0 है, और हम डेक के नीचे से अपना रास्ता बना रहे हैं, इसलिए प्रत्येक स्थिति के लिए, आप प्रभावी रूप से उस स्थिति के ऊपर और ऊपर के सभी कार्ड उठा रहे हैं और बेतरतीब ढंग से उन कार्डों में से एक उठा रहे हैं)।

जब हमने यादृच्छिक चयन किया है, तो हम उस स्थिति पर कार्ड स्वैप करते हैं जिसे हम वर्तमान में उस कार्ड के साथ विचार कर रहे हैं जिसे हमने यादृच्छिक रूप से चुना है। यदि हमने अनियमित रूप से उस कार्ड का चयन किया है जो पहले से ही उस स्थिति में था, तो कोई स्वैप नहीं किया जाता है।

स्वैप करने के बाद (या स्वैप नहीं करने पर, यदि हमने अनियमित रूप से उस कार्ड का चयन किया है जो पहले से ही उस स्थिति में था जिसे हम विचार कर रहे थे), हम डेक में अगली स्थिति पर चलते हैं और जारी रखते हैं।

स्यूडोकोड में, साथ n डेक में कार्ड की संख्या में किया जा रहा है, और एक एक सरणी डेक, इस तरह एल्गोरिथ्म दिखता का प्रतिनिधित्व करने जा रहा है:

for each i in [n .. 1] do
     j  random integer in [ 0 .. i ]
     exchange a[j] and a[i]

1
एल्गोरिथ्म यहाँ भी अच्छी तरह से कल्पना की गई है: bost.ocks.org/mike/algorithms/#shuffling
फेलिसिर

9

आप पहले उन सभी कार्डों के अनुक्रम को परिभाषित करते हैं जिन्हें आप फेरबदल करना चाहते हैं:

List<Card> shuffled = new ArrayList<Card>();
shuffled.addAll(allCards);

फिर आप अनुक्रम में हर स्थिति से चलते हैं और इसे यादृच्छिक रूप से एक कार्ड असाइन करते हैं।

Random random = new Random();
for (int i = shuffled.size() - 1; i >= 0; i--) {
    int j = random.nextInt(i + 1);

    /* swap cards i,j */
    Card card = shuffled.get(i);
    shuffled.set(i, shuffled.get(j));
    shufflet.set(j, card);
}

अब shuffledआपके सभी कार्डों का एक यादृच्छिक क्रम है।


3
इसे नथ के फेरबदल के रूप में जाना जाता है: en.wikipedia.org/wiki/Knuth_shuffle
krolth

2

मैं झंकार करना चाहता हूं और "प्रारूप संरक्षण एन्क्रिप्शन" का उल्लेख एक गेम में कार्ड को फेरबदल करने के लिए एक विधि के रूप में करना चाहता हूं।

अनिवार्य रूप से आपके पास एक एन्क्रिप्शन एल्गोरिथ्म है जो 0 से 51 के मान में लेता है, और एक कुंजी (फेरबदल के बीज) और 0 से 51 के मान को बाहर निकालता है। चूंकि एन्क्रिप्शन परिभाषा से प्रतिवर्ती है, जिसका अर्थ है कि कोई भी 2 इनपुट नंबर एन्क्रिप्ट नहीं कर सकता समान आउटपुट संख्या, जिसका अर्थ है कि यदि आपने 0 से 51 को एन्क्रिप्ट किया है, तो आपको एक अलग क्रम में आउटपुट के रूप में 0 से 51 मिलेगा। दूसरे शब्दों में, आप अपने फेरबदल है और किसी भी वास्तविक फेरबदल करने की जरूरत नहीं है।

इस मामले में आपको एक एन्क्रिप्शन एल्गोरिथ्म बनाना या ढूंढना होगा जो 6 बिट्स में लिया गया और 6 बिट्स (0-63) को थूक दिया। अगले कार्ड को डेक से खींचने के लिए आपके पास एक इंडेक्स वैरिएबल होगा जो शून्य पर शुरू हुआ था, आप उस इंडेक्स को एन्क्रिप्ट करेंगे, इंडेक्स को बढ़ाएंगे और उस मूल्य को देखेंगे जो सिफर से निकला था। यदि मान> = 52 है, तो आप इसे अनदेखा करते हैं और एक नया नंबर उत्पन्न करते हैं (और फिर से पाठ्यक्रम को बढ़ाते हैं)। चूंकि 0-63 को एन्क्रिप्ट करने का परिणाम 0-63 के आउटपुट के रूप में होगा, एक अलग क्रम में, आप बस किसी भी मूल्य को अनदेखा कर रहे हैं जो बाहर आता है = = 52 ताकि आप अपने एल्गोरिथ्म को 0-51 में लेते हैं और 0-51 से बाहर निकलते हैं।

डेक को फेरबदल करने के लिए, सूचकांक को शून्य पर सेट करें और एन्क्रिप्शन कुंजी (फेरबदल बीज) को बदलें।

आपके एल्गोरिथ्म को क्रिप्टोग्राफ़िक गुणवत्ता होने की आवश्यकता नहीं है (और यह नहीं होना चाहिए, क्योंकि यह कम्प्यूटेशनल रूप से महंगा होगा!)। कस्टम आकार के एन्क्रिप्शन एल्गोरिथ्म के साथ आने के लिए वास्तव में एक अच्छा तरीका एक feistel नेटवर्क का उपयोग करना होगा, जो आपको आपकी आवश्यकताओं के आधार पर आकार और गुणवत्ता को अनुकूलित करने की अनुमति देता है। Feistel नेटवर्क के गोल कार्य के लिए, मैं murmurhash3 जैसी किसी चीज़ की सिफारिश करूंगा क्योंकि यह तेज़ है और इसमें एक अच्छा हिमस्खलन प्रभाव है, जिससे फेरबदल अच्छी तरह यादृच्छिक रूप से प्रकट होंगे।

अधिक विस्तृत जानकारी और स्रोत कोड के लिए मेरी ब्लॉग पोस्ट देखें: http://blog.demofox.org/2013/07/06/fast-lightweight-random-shuffle-functionality-fixed/


यह जवाब क्योंकि यह वर्तमान में प्रकाशित किया गया है, जब URL अनिवार्य रूप से इंटरनेट की सतह से गिर जाता है, तो इससे बहुत मदद नहीं मिलती है। लिंक किए गए लेख के मुख्य बिंदुओं पर उत्तर में विस्तार से विचार करें, ताकि उत्तर अपने आप खड़ा हो सके।
लार्स विकलंड

1
अच्छा बिंदु लार्स, अधिक जानकारी के साथ अद्यतन किया जाता है ताकि एक पाठक कम से कम एक समाधान के सभी विशिष्ट घटकों पर अधिक जानकारी के लिए कार्ड को फेरबदल करके प्रारूप संरक्षण एन्क्रिप्शन का उपयोग कर देख सके। धन्यवाद!
एलन वोल्फ

1

जावा 1.5 enum ट्यूटोरियल , डेक के निर्माण फेरबदल और काम कर ताश के पत्तों के लागू करने के लिए एक दिलचस्प तरीका है। सभी बहुत ही सरल enumऔर एस का उपयोग करCollections

public class Card {
    public enum Rank { DEUCE, THREE, FOUR, FIVE, SIX,
        SEVEN, EIGHT, NINE, TEN, JACK, QUEEN, KING, ACE }

    public enum Suit { CLUBS, DIAMONDS, HEARTS, SPADES }

    private final Rank rank;
    private final Suit suit;
    private Card(Rank rank, Suit suit) {
        this.rank = rank;
        this.suit = suit;
    }

    public Rank rank() { return rank; }
    public Suit suit() { return suit; }
    public String toString() { return rank + " of " + suit; }

    private static final List<Card> protoDeck = new ArrayList<Card>();

    // Initialize prototype deck
    static {
        for (Suit suit : Suit.values())
            for (Rank rank : Rank.values())
                protoDeck.add(new Card(rank, suit));
    }

    public static ArrayList<Card> newDeck() {
        return new ArrayList<Card>(protoDeck); // Return copy of prototype deck
    }
}

और डेक का प्रबंधन करने के लिए कक्षा।

public class Deal {
    public static void main(String args[]) {
        int numHands = Integer.parseInt(args[0]);
        int cardsPerHand = Integer.parseInt(args[1]);
        List<Card> deck  = Card.newDeck();
        Collections.shuffle(deck);
        for (int i=0; i < numHands; i++)
            System.out.println(deal(deck, cardsPerHand));
    }

    public static ArrayList<Card> deal(List<Card> deck, int n) {
         int deckSize = deck.size();
         List<Card> handView = deck.subList(deckSize-n, deckSize);
         ArrayList<Card> hand = new ArrayList<Card>(handView);
         handView.clear();
         return hand;
     }
}

0

बस पायथन पर वहाँ की तरह एक समारोह itertools का उपयोग करें। मुझे जावा फ़ंक्शन में उसी फ़ंक्शन के नाम के बारे में पता नहीं है " http://code.google.com/p/neoitertools/ "

"कार्ड" नामक वस्तु के सभी क्रमपरिवर्तन का पता लगाएं


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.