• 问题

    即使只有52张卡片(我在“说明”部分中描述的permutationIndex)也将是一个庞大的数字;它是52!之一中的数字,需要29个字节来存储。

    因此,我不知道一种简单的方法来计算很大范围的permutationIndex,并以最小的成本存储索引,或者也许也可以计算出它。我在想这个问题的解决方案是三种算法:
  • 一种计算正确的permutationIndex的算法将实现Dealing 方法
  • 一种计算正确的permutationIndex的算法将实现Collect 方法
  • 一种以最小成本存储(或计算)permutationIndex 的算法
  • 解释

    我最初尝试使用置换来实现范围从int.MinValeint.MaxValue的整数句柄生成器。

    因为范围真的很大,所以我从实现到一个带有52张卡的Dealer类开始,该类实际上并没有存储像哈希集或数组这样的一副卡,甚至也不需要随机的(首字母除外) 。

    在给定范围的序数范围内,我认为完整排列之一的每个序列都有一个索引,并将其命名为permutationIndex。我使用索引来记住它是哪个排列,而不真正存储序列。该顺序是一副纸牌的可能顺序之一。

    这是一个在动画图形中进行仿真的示例,以展示我的想法。


    每次我发牌时,我都会更改permutationIndexdealt(已发牌数),从而知道哪些发了牌,哪些仍在手。当我取回已发行的卡时,我会知道卡号并将其放在最上面,它也成为下次处理的卡。在动画中,colleted是卡号。


  • 有关更多信息,如下。
  • 代码说明

    仅三个3的概念样本Dealer类如下。
    该代码是用c#编写的,我也正在考虑任何language-agnostic解决方案。

    这是示例代码的一些描述

  • 示例代码
    public static class Dealer {
        public static void Collect(int number) {
            if(1>dealt)
                throw new IndexOutOfRangeException();
    
            switch(permutationIndex) {
                case 5:
                case 0:
                    switch(number) {
                        case 3:
                            break;
    
                        case 2:
                            permutationIndex=1;
                            break;
    
                        case 1:
                            permutationIndex=4;
                            break;
                    }
    
                    break;
    
                case 4:
                case 3:
                    switch(number) {
                        case 3:
                            permutationIndex=5;
                            break;
    
                        case 2:
                            permutationIndex=2;
                            break;
    
                        case 1:
                            break;
                    }
    
                    break;
    
                case 2:
                case 1:
                    switch(number) {
                        case 3:
                            permutationIndex=0;
                            break;
    
                        case 2:
                            break;
    
                        case 1:
                            permutationIndex=3;
                            break;
                    }
    
                    break;
            }
    
            --dealt;
        }
    
        public static int Dealing() {
            if(dealt>2)
                throw new IndexOutOfRangeException();
    
            var number=0;
    
            switch(permutationIndex) {
                case 5:
                    permutationIndex=3;
                    number=3;
                    break;
    
                case 4:
                    permutationIndex=0;
                    number=1;
                    break;
    
                case 3:
                    permutationIndex=1;
                    number=1;
                    break;
    
                case 2:
                    permutationIndex=4;
                    number=2;
                    break;
    
                case 1:
                    permutationIndex=5;
                    number=2;
                    break;
    
                case 0:
                    permutationIndex=2;
                    number=3;
                    break;
            }
    
            ++dealt;
            return number;
        }
    
        static int[,] sample=
            new[,] {
                { 1, 2, 3 }, // 0
                { 1, 3, 2 }, // 1
                { 3, 1, 2 }, // 2
                { 3, 2, 1 }, // 3
                { 2, 3, 1 }, // 4
                { 2, 1, 3 }, // 5
            };
    
        static int permutationIndex;
        static int dealt;
    }
    
  • 最佳答案

    不完全是您要在此处完成的任务,但是,如果您想随机抽取一副纸牌来进行交易,则可以使用随机播放算法。典型的随机播放算法是Fisher-Yates。随机播放算法将创建一个以随机顺序列出卡号的数组(13,5,7,18,22,...等)。为了解决这个问题,您从数组中的第一个元素开始,然后继续前进。

    09-13 12:47