当前位置: 首页 > 知识库问答 >
问题:

我的方法有效吗?

太叔何平
2023-03-14

我正在为一副洗牌的纸牌编写代码。我测试了代码,但我真的不知道它是否真的在做它应该做的事?你觉得怎么样?

这是schffle方法的代码:

html" target="_blank">public void shuffle()
{
    for( int x = myDeck.size(); x > 0 ; x--) 
     {
        Random rn = new Random();
        int index1 = rn.nextInt(52);
        Card c = myDeck.remove(index1);
        myDeck.add(c);
     }
  }

我的输出似乎在数字上打乱了,但不是像黑桃心这样的卡片名称,

例如,这是我测试代码时的输出:

Deuce of spades
Seven of spades
Eight of spades
Ace of spades
Three of hearts
Five of hearts
Six of hearts
Seven of hearts
Nine of hearts
Ten of hearts
Queen of hearts
King of hearts
Ace of hearts
Seven of diamonds
Eight of diamonds
Jack of diamonds
King of diamonds
Three of clubs
Seven of clubs
Nine of clubs
Jack of clubs
Queen of clubs
King of clubs
Ace of clubs
Queen of spades
Deuce of clubs
Three of spades
Nine of diamonds
Four of spades
Four of clubs
Deuce of hearts
Jack of spades
Ten of clubs
Six of diamonds
Jack of hearts
Six of clubs
Four of diamonds
Five of diamonds
Ace of diamonds
Four of hearts
Nine of spades
Ten of spades
Five of spades
Three of diamonds
Six of spades
Five of clubs
Deuce of diamonds
Eight of hearts
King of spades
Ten of diamonds
Eight of clubs
Queen of diamonds

就像总是有重复的名字。既然洗牌的目的是把它混在一起,这是错的吗?

这是一个实际的问题:在打牌时,洗牌当然很重要,也就是说,要安排好事情,使牌以随机的顺序被发。有几种方法可以实现这一点。一种策略是反复从纸牌组中随机挑选一张牌,并将其移到最后。下面的代码使用Random类(您在在线课程的“ArrayLists”部分的第8页上遇到)执行一个这样的“拾取并移动到末尾”操作:

Random rn = new Random();
int index1 = rn.nextInt( 52 );
Card c = myDeck.remove( index1 );
myDeck.add( c );

为了有效地洗牌,这个操作应该重复很多次(比如500次)。为Deck类创建一个新的实例方法shuffle,该类使用单个Random对象和for循环来shufflemyDeck。适当修改main方法后,使用它测试新代码。

所以我的主要问题是:我做错了吗?

共有3个答案

傅鸿波
2023-03-14

这个问题给出了一个提示:

为了有效地洗牌,这个操作应该重复多次(比如500次)。

而你的循环只运行52次(myDeck.size())。因此,您删除一张卡并随机更换它仅 52 次。这似乎还不够。

PS:通常写 for(int i = 0; i

万俟渝
2023-03-14

最好的方法是使用内置的 Collections.shuffle() 方法,它将以随机方式(或接近随机)为您洗牌 ArrayList。

现在你的逻辑的问题是,它从纸牌组中挑选出一张随机的牌,然后把它放在最后,然后这样做52次。现在你有了一个很好的改变,你会多次对许多卡片进行这种操作,有些根本没有——因此,你遇到的问题是,许多卡片似乎没有被随机分配。

你似乎有这样的逻辑:你需要对牌组中的牌数进行此操作,这是有缺陷的;你需要多做几次。

你有两个主要的逻辑解决方案,你可以首先做很多次 - 比如说比你现在做的多10倍,或者你可以重新设计你的代码以使用内置的(或更有效的)洗牌算法。

公孙志
2023-03-14

只需将 rn.nextInt(52); 更改为 rn.nextInt(x),您就有了适当的 Fisher-Yates 洗牌。无需执行超过 52 次迭代。

为什么这样做:

>

  • 在第一次迭代中(当x为52时),您将从整副牌中选择一张随机牌,并将其移到最后。

    在第二次迭代中(当x为51时),您将从剩余的牌中选择一张随机牌,并将其移动到最后。

    ...诸如此类。

    经过 52 次迭代后,选择的第一张卡片将最终出现在第一个索引中。由于这张牌是从全副牌中随机选择的,因此每张牌的概率相等。

    同样适用于第二个索引、第三个索引。。。

    因此,甲板的每个可能的排列都是同样可能的。


    (在生产代码中,只需在这些情况下使用Collections.shuffle。)

  •  类似资料:
    • 最近我接受了一次采访,他们问我一个“搜索”问题。问题是: 假设存在一个(正)整数数组,其中每个元素与其相邻元素相比要么是,要么是。 例: 现在搜索并返回其位置。 我给出了这样的答案: 将这些值存储在临时数组中,对它们进行排序,然后应用二进制搜索。 如果找到元素,则返回其在临时数组中的位置 (如果数字出现两次,则返回第一次出现的数字) 但是,他们似乎对这个答案不满意。 正确的答案是什么?

    • 问题内容: 我的桌子上有很多记录(可能超过500 000或1 000 000)。我在此表中添加了一个新列,我需要使用该表中另一列的相应行值为该列中的每一行填充一个值。 我尝试使用单独的事务来选择每100条记录的下一个块并为其更新值,但是例如,要花费数小时来更新Oracle10中的所有记录。 在不使用某些方言特定功能的情况下,在SQL中执行此操作的最有效方法是什么,因此它可在任何地方(Oracle,

    • 问题内容: 我在Java中使用ResultSet,但不确定如何正确关闭它。我正在考虑使用ResultSet构造一个HashMap,然后在那之后关闭ResultSet。这种HashMap技术是有效的还是有更有效的方法来处理这种情况?我需要键和值,因此使用HashMap似乎是一个合理的选择。 如果使用HashMap是最有效的方法,如何在代码中构造和使用HashMap? 这是我尝试过的: 问题答案: 遍

    • 问题内容: 每个“产品”最多可以有10000个“细分”行。这些细分受众群具有一个针对每种产品(1、2、3、4、5,…)从1开始的排序列,以及一个值列,该列可以包含诸如(323.113、5423.231、873.42、422.64、763.1,…)。 我想确定给定细分子集的产品的潜在匹配。例如,如果我按正确的顺序有5个细分值,那么如何在细分表中某处有效地找到所有具有相同顺序的5个细分的所有产品? 问

    • 我在NodeJS中看到过从本地读取JSON文件不同方法。像这样; > 方法 使用fs库 方法 使用require() 方法 使用Ajax请求如何使用Jquery和Ajax从JSON文件中检索数据? 可能还有别的办法。但是我听说使用方法1读取JSON文件比其他方法更有效。

    • 我希望在我们的web应用程序中实现一些高效(即具有良好性能)的逻辑来进行有效负载签名。HTML5客户端的目标是保证接收到的有效负载的内容确实是我们后端生成的内容。 我们不想使用共享盐进行有效负载哈希生成,因为用户可以轻松打开HTML5源并找到盐短语。 我们现在已经实现了RSA签名,我们的后端使用其私钥添加有效负载签名,我们的HTML5客户端使用其烘焙的公钥验证有效负载签名。然而,签名生成过程需要2