Java 随机卡片生成
我需要从数组中随机生成三张卡,我有52张卡的数组,从card1到card52Java 随机卡片生成,java,Java,我需要从数组中随机生成三张卡,我有52张卡的数组,从card1到card52 String rank[]=new String[52]; for(int i=0;i<rank.length;i++) { rank[i]= "card"+i; } String rank[]=新字符串[52]; 对于(int i=0;i而言,每当您选择一张卡时,都要有一个数组(甚至一个字符串)并添加到其中。这样,每当您选择第二张或第三张卡时,如果它在数组(或字符串)中,您就可以选择另一张卡 这里有一个方法…
String rank[]=new String[52];
for(int i=0;i<rank.length;i++)
{
rank[i]= "card"+i;
}
String rank[]=新字符串[52];
对于(int i=0;i而言,每当您选择一张卡时,都要有一个数组(甚至一个字符串)并添加到其中。这样,每当您选择第二张或第三张卡时,如果它在数组(或字符串)中,您就可以选择另一张卡
这里有一个方法…我没有检查它是否有效
String pickedCards = ""
int totalPickedCards = 0
boolean continue = true;
for(continue)
{
tempVariable = pickedCard
if (pickedCard.contains("/"+tempVariable+"/") == false) { // if you didn't already pick it then
pickedCards = pickedCards + "/" + tempVariable + "/";
// save the card you picked - stored in tempVariable
++totalPickedCards
}
if (totalPickedCards >= 3) { // exit loop if you have 3 cards picked
continue = false;
}
}
您可以尝试以下方法:
String rank[]=新字符串[52];
for(int i=0;i
如果你将数组转换成一个列表,你可以使用它进行随机操作。如果你只取列表的前三个条目,你将得到三张没有重复的随机卡片
List<String> ranklist = Arrays.asList(rank);
Collections.shuffle(ranklist);
String rank1 = ranklist.get(0);
String rank2 = ranklist.get(1);
String rank3 = ranklist.get(2);
List ranklist=Arrays.asList(rank);
收藏。洗牌(ranklist);
字符串rank1=ranklist.get(0);
字符串rank2=ranklist.get(1);
String rank3=ranklist.get(2);
比洗牌整个阵列更快的东西:
java.util.Random r = new java.util.Random();
int c1 = r.nextInt(52),
c2 = r.nextInt(51),
c3 = r.nextInt(50);
if(c2 >= c1) c2++;
if(c3 >= Math.min(c1, c2)) c3++;
if(c3 >= Math.max(c1, c2)) c3++;
System.out.println("Card 1: " + rank[c1]);
System.out.println("Card 2: " + rank[c2]);
System.out.println("Card 3: " + rank[c3]);
事实上,我使用vs(屏幕截图)的通用(较慢)形式进行的一些计时测试表明,对于3张卡,该方法的速度大约是3.7倍,而实际上,对于选择多达24张随机卡,该方法的速度是3.7倍
向怀疑者解释算法:
概率
我们选择随机数-首先,52张牌中的一张。如果我们移除那张牌,然后选择另一张牌,那将是51张牌中的一张……所以我们选择的索引的随机数范围是可以接受的
如果我们从一个数组中拾取和移除,那么我们只需要取出索引1处的项,然后取出索引2处的项,对于索引3也是如此
我在上面所做的是调整索引,使其具有与从数组中取出项相同的效果
对于索引2,我们有一个数字,可以是0到50之间的任何数字。但是,让我们假设我们在索引6处取出了卡片
这意味着,我们不需要一个分布在0到50之间的随机数,而是需要一个分布在0-5和7-51之间的随机数。这仍然是51种可能性的总和。我们通过在第二个索引中添加1来实现这一点,如果它大于等于6。现在,我们有一个分布正确的正确范围内的数字,如果击中一个目标,则具有相同的概率允许的索引的y
第三张牌的逻辑也稍微复杂一些:牌组中有两个点“缺失”——因此我们调整第三个索引以覆盖可用范围。首先,如果它等于或高于第一个缺失位置,则将其向上移动。然后,如果它等于或高于第二个缺失位置,则将其再次向上移动。这不会使选择偏向高er值—我们所做的只是避免使用已经使用过的索引
概率没有偏差
效率
评论中提到,此算法和使用集合的算法具有相同的复杂性(即,O(n)),此方法的可读性稍差。首先要指出的是,此算法更复杂;即,对整个数组进行洗牌时,它是O(n^2).对于低n,该算法更有效。而且,我认为效率的差异保证了可读性的牺牲。比较:
收藏。洗牌
随机数
从列表中删除项目
将项目插入列表
再重复51次
此方法
随机数
随机数
随机数
最多3个增量
这忽略了使用第一种方法时从数组到容器的必要转换。不可避免的结论是,这种方法更有效
顺便说一句,当你考虑挑选4张牌时,你可以想象O(n^2)的性质-这需要最多6张增量…5张牌,最多10张…6张牌,最多15张…n,(n^2-n)/2
概括
在本例中,我使用了Math.min
和Math.max
作为一种简单的方法来对2个项目的列表进行排序。在一般情况下(即选择“n”[1-52]非重复随机卡),我们需要对最多52个项目的列表进行排序。这可以在O(n)中完成最坏的情况是使用插入排序,方法是保留选定索引的有序列表。通过
使用random.nextInt(52-selectedIndexListSize)
在排序列表上迭代,在每个节点上,如果大于等于节点值,则增加所选索引,如果小于,则停止
阵列中选定索引处的输出卡
将所选索引插入到排序列表中,即我们停止的位置
每个选项都是O(n)-但如果给出52个选项,则为O(n^2)
然而,就效率而言,当m^2Random Random=new Random();
Random random = new Random();
List<Integer> randomList = new ArrayList<Integer>();
int randomInt;
do {
randomInt = random.nextInt(52);
if (randomList.contains(new Integer(randomInt)))
continue;
randomList.add(randomInt);
} while (randomList.size() < 3);
List randomList=新建ArrayList();
int-randomInt;
做{
randomInt=random.nextInt(52);
if(randomList.contains(新整数(randomInt)))
继续;
添加(randomInt);
}while(randomList.size()<3);
随机列表将包含三张卡片的索引基本上有两种数学上有效的方法:
正如其他人所建议的,洗牌整个阵列,然后从一开始按顺序拾取
随机选取第一个。然后随机选取第二个。如果第二个与第一个相同,则再次随机选取。也就是说,将选取放入一个保持t的循环中
Random random = new Random();
List<Integer> randomList = new ArrayList<Integer>();
int randomInt;
do {
randomInt = random.nextInt(52);
if (randomList.contains(new Integer(randomInt)))
continue;
randomList.add(randomInt);
} while (randomList.size() < 3);