检查数组中的整数

时间:2014-04-25 11:46:51

标签: java arrays random

我在大学里做了一项练习,其中一部分包括制作一包必须洗牌的卡片。我把卡片放在一个阵列中(没有洗牌)并且想要将它们洗牌并将它们推到自制的堆栈上,我可以从中弹出卡片来处理它们。

我的问题是我想检查我生成的随机数(以及代表阵列中的一张卡)是否已经在堆栈中。从阅读这个论坛我已经得到了下面的代码,在我看来应该工作。在调试虽然我注意到重复。

根据我在下面的评论,我们无法使用收藏框架(编辑)

private Stack<Card> deck;//to hold cards
private Card[] protoDeck;//to hold cards before shuffling
private Random randomer;

private int cardsDealt;//how many cards used. Used for other methods
private static final int TOTALCARDS = 52;//sets limit of deck for all decks

public void shuffle(){//remove cards from deck and put back in random order
    randomer = new Random();
    int[] temp = new int[TOTALCARDS];//to keep track of random numbers
    int rand = 0;

    for (int i = 0; i < temp.length ; i++) {
        do {//keep creating randoms if 
            rand = randomer.nextInt(TOTALCARDS);
            deck.push(protoDeck[rand]);//puts the Card onto the Deck in a random position
            temp[i] = rand;
        } while (!(Arrays.asList(temp).contains(rand)));//check if the number already used  
    }
}

@PeterLawrey我已经稍微调整了代码,因为我只需要将整个套牌洗牌并且它有效,我将从堆栈中弹出卡片来处理


public void shuffle() {
    randomer = new Random();
    for(int i = 0; i < TOTALCARDS; i++) {
        // pick a random card from the rest of the deck
        int j = randomer.nextInt(protoDeck.length - i) + i;
        // swap cards
        Card tmp = protoDeck[i];
        protoDeck[i] = protoDeck[j];
        protoDeck[j] = tmp;
        deck.push(protoDeck[i]);
    }

}

感谢彼得和所有其他贡献者。微米。

5 个答案:

答案 0 :(得分:3)

开始
private final Card[] deck;//to hold cards before shuffling
private final Random rand = new Random();

你可以做到

public void shuffle() {
    // no need the shuffle the last card.
    shuffle(deck.length - 1);
}

// will leave the first N card random without duplicates.
public void shuffle(int numberOfCards) {
    for(int i = 0; i < numberOfCards; i++) {
        // pick a random card from the rest of the deck
        int j = rand.nextInt(protoDeck.length - i) + i;
        // swap cards
        Card tmp = deck[i];
        deck[i] = deck[j];
        deck[j] = tmp;
    }
}

成本为O(N),其中N是随机卡的数量。


想象一下你有一个像

这样的小甲板
AS AC AD AH 2S 2C 2D 2H

你需要随机选择第一张牌,你从牌组中选择一张并交换该牌。说nextInt()是5 =&gt; 2C

2C | AC AD AH 2S AS 2D 2H

桌子由随机​​选择的卡+未选中。你没有重复,因为相同的卡被移动。下一张随机卡是2H,与AC交换

2C 2H | AD AH 2S AS 2D AC

最后恰好选择了AD。

2C 2H AD | AH 2S AS 2D AC

这会给你三张随机卡,其余的。同一个数组可以再次使用,因为从排序或随机套牌开始,不会使结果或多或少随机。


如果有123,则回答Why does this simple shuffle algorithm produce biased results?,可能的结果是

123
 +- 123          - swap 1 and 1 (these are positions, not numbers)
 |   +- 123      - swap 2 and 2
 |   +- 132      - swap 2 and 3
 +- 213          - swap 1 and 2
 |   +- 213      - swap 2 and 2
 |   +- 231      - swap 2 and 3
 +- 321          - swap 1 and 3
     +- 321      - swap 2 and 2
     +- 312      - swap 2 and 3

正如您所看到的,只有6种可能的结果,所有结果都是同样可能的。

答案 1 :(得分:1)

实际上Stack扩展了Vector。因此,您可以使用contains方法检查已存在的元素是否存在。

答案 2 :(得分:1)

最初的问题是Arrays.asList(temp)不会创建List<Integer>而是创建List<int[]>

因此Arrays.asList(temp).contains(rand)始终返回false

如果您使用了包装类IntegerInteger[] temp = new Integer[TOTALCARDS];),它会起作用,但是您的方法效率非常低,因为您必须在集合中生成“随机”数字,这将减少每次迭代。

一种方法是创建一个包含位置0到51的数组,对其进行随机播放,然后遍历它以推动卡片中的卡片。

public void shuffle(){//remove cards from deck and put back in random order
    int[] temp = new int[TOTALCARDS];//to keep track of random numbers
    for(int i = 0; i < temp.length; i++){
        temp[i] = i;
    }

    //shuffle the array

    for (int i = 0; i < temp.length ; i++) {
        deck.push(protoDeck[temp[i]]);             
    }
}

这种方法在O(n)时间内运行。

答案 3 :(得分:0)

也许我弄错了,但我认为你的概念很糟糕。

  1. 生成随机数
  2. 把它放在新的套牌中
  3. 检查它是否已经存在
  4. 听起来像是错误的订单。另一方面,如果你想要独特的元素,使用Set总是有效。

答案 4 :(得分:-1)

在@ ZouZou州,Arrays.asList(temp)返回List<int[]>。你可能会这样做是因为answer引起的混乱(顺便说一句是错的)。这个answer显示了一种使用二进制搜索的方法:

public boolean contains(final int[] array, final int key) 
{  
     Arrays.sort(array);  
     return Arrays.binarySearch(array, key) >= 0;  
}  

这会修改传入的数组。你可以选择复制数组并处理原始数组,即int[] sorted = array.clone();但这只是短代码的一个例子。运行时为O(NlogN)

根据Java文档,binarySearch将返回以下内容之一(我强调了重点):

搜索键的索引(如果它包含在列表中);否则,( - (插入点) - 1)插入点定义为将键插入列表的点:第一个元素的索引大于键,或者list.size(),如果所有元素都在列表小于指定的密钥。请注意,当且仅当找到密钥时,这可以保证返回值>> =。