![](/img/trans.png)
[英]How can I get the shuffler method to only shuffle certain indexes in an array? While not shuffling indexes which I want to stay the same
[英]How do I shuffle an ArrayList, but after shuffling specific indexes stay the same?
在我的ArrayList
,每个数字都有一个根据它们在ArrayList
的位置分配给它们的颜色。 奇数索引中的数字为红色,偶数索引中的数字为蓝色,10 倍数索引中的数字为黑色。 我需要对列表进行洗牌,以便洗牌后,红色数字仍然在奇数索引中,蓝色数字仍然在偶数索引中,黑色数字仍然是十个索引的倍数。 我知道如何打乱整个列表,但不知道这样的具体事情。 我该怎么做呢?
这是上下文的代码:
/* Term 2 Assignment 5 - Game Wheel */
/* GameWheel class*/
import java.util.*;
import java.lang.*;
public class GameWheel
{
// List of slices making up the wheel
private List<Slice> slices;
// Position of currently selected slice on wheel
private int currentPos;
/* Creates a wheel with 40 preset slices which are then randomized (keeping
* the color pattern the same).
*/
public GameWheel()
{
slices = new ArrayList<Slice>();
currentPos = 0;
initGameWheel();
scramble();
}
/* Spins the wheel by so that a different slice is selected. Return that
* slice (Note: the 20 slices following the current slice are more likely to
* be returned than the other 20).
*/
public Slice spinWheel()
{
//spin power between range of 1-100 (inclusive)
int power = (int)(Math.random()*100 + 1);
int newPos = (currentPos + power) % slices.size();
currentPos = newPos;
return slices.get(currentPos);
}
/* Helper method for the constructor. Randomizes the positions of the slices
* that are in the wheel, but without changing the pattern of the colors
* (i.e. the red slices will still be at odd indices, the black slices at
* multiples of 10, and the blue slices at all other even indices).
*/
private void scramble()
{
}
// Helper method which initializes the slices in the wheel
private void initGameWheel()
{
slices.add(new Slice("black", 8000));
for (int i=1; i < 40; i++)
{
if (i%2 == 1)
slices.add(new Slice("red", i*10));
else if (i%10 == 0)
slices.add(new Slice("black", i*200));
else
slices.add(new Slice("blue", i*100));
}
}
// Returns the list of slices for this GameWheel
public List<Slice> getSlices() {
return slices;
}
}
以下是切片的创建方式:
/* Slice class*/
public class Slice
{
private String color;
private int prizeAmount;
// Creates a slice with color c, and cash prize p
public Slice(String c, int p) {
color = c;
prizeAmount = p;
}
// Returns the cash prize in dollars for this slice
public int getPrizeAmount() {
return prizeAmount;
}
// Returns the color of this slice as a string
public String getColor() {
return color;
}
/* Returns a string representation of the slice in the following format:
* Color: red, prize amount: $50.
*/
public String toString() {
return "Color: " + color + ", Prize Amount: $" + prizeAmount;
}
}
任何帮助表示赞赏
没有“简单”(例如,通过像Collections.shuffle
这样的现有方法)方式; 你必须自己编程这个功能,但你当然可以使用一些现有的东西来帮助你。
一种有点迂回的方法是“解构和重建”:编写一种方法,将单个列表分解为 3 个单独的列表(每种颜色 1 个),然后将它们打乱,然后将三个单独的列表“重建”回一个大列表,使用明显算法(如果索引被10整除,从黑名单中抓取下一个,否则如果被2整除,从蓝名单中抓取,否则,从红名单中抓取)。
另一种方法是自己实现 shuffle 算法。 对于上下文,您正在寻找Fisher-Yates shuffle algorithm , Collections.shuffle
的实现也使用它。 需要了解的关键事项:
要获得 0 和 N 之间的随机数,请在Random
实例上调用.nextInt(n)
(创建单个实例,一次,并继续重用它)。 不要使用 common (int) (Math.random() * n)
,这是微妙的错误(鸽巢原理)和非惯用的 java.lang.
Fisher yates 主要涉及从开始(索引 0)到倒数第二个元素(索引为list.size() -2
元素)遍历列表。 对于每个元素,将其与一个统一的随机选择的元素交换,该元素本身或其上方的任何元素。
换句话说,要对1,2,3,4,5
进行混洗,我们从第 0 个元素(即 1)开始,从自身到交换中均匀随机地选择任何元素。 这是 5 个元素的选择,因此我们调用rnd.nextInt(5)
来计算它。 该随机数可能是 0,在这种情况下,“您将 1 与自身交换”,这意味着它保持原样(嘿,洗牌意味着随机;有时在洗牌一副牌后,一张牌最终会在堆中的同一位置!)。 然后对于下一个元素(2;在索引 1 处),您选择从其自身(因此索引 1)到末尾的任何索引,因此我们调用rnd.nextInt(4)
,依此类推。
对于这个练习,棘手的一点是要弄清楚有多少个有效的“高于你”可以与存在交换(这将是你传递给rnd.nextInt(X)
的参数),以及如何翻译数字您的 nextInt 调用为您提供了您现在需要与之交换的索引。
请注意,此算法完全就位; 不需要任何额外的列表或数组。 您只需要一个临时变量即可启用交换。
这听起来像是家庭作业,所以我不会为你预先咀嚼答案。 希望这足以让您自己编写。 祝你好运!
试试这个解决方案:
public void shuffle(List<Slice> slices) {
Map<String, Iterator<Slice>> slicesByColor = slices.stream()
.collect(groupingBy(Slice::getColor)).entrySet().stream()
.peek(e -> Collections.shuffle(e.getValue()))
.collect(toMap(Map.Entry::getKey, e -> e.getValue().iterator()));
for (int i = 0; i < slices.size(); i++) {
Iterator<Slice> sliceIterator = slicesByColor.get(colorByIndex(i));
slices.set(i, sliceIterator.next());
}
}
private String colorByIndex(int index) {
if (index % 2 == 1)
return "red";
else if (index % 10 == 0)
return "black";
else
return "blue";
}
之前的输出:
[Color: black, Prize Amount: $8000, Color: red, Prize Amount: $10, Color: blue, Prize Amount: $200, Color: red, Prize Amount: $30, Color: blue, Prize Amount: $400, Color: red, Prize Amount: $50, Color: blue, Prize Amount: $600, Color: red, Prize Amount: $70, Color: blue, Prize Amount: $800, Color: red, Prize Amount: $90, Color: black, Prize Amount: $2000]
输出后:
[Color: black, Prize Amount: $2000, Color: red, Prize Amount: $90, Color: blue, Prize Amount: $800, Color: red, Prize Amount: $70, Color: blue, Prize Amount: $200, Color: red, Prize Amount: $10, Color: blue, Prize Amount: $400, Color: red, Prize Amount: $50, Color: blue, Prize Amount: $600, Color: red, Prize Amount: $30, Color: black, Prize Amount: $8000]
我认为您可以创建 3 个不同的列表并将它们分别洗牌。 之后使用混洗列表重新创建原始列表:
public static List<Slice> shuffle(List<Slice> slices) {
final int total = slices.size();
List<Slice> red = new ArrayList<>();
List<Slice> blue = new ArrayList<>();
List<Slice> black = new ArrayList<>();
int i = 0;
for (Slice slice : slices) {
if (i % 2 == 1)
red.add(slice);
else if (i % 10 == 0)
black.add(slice);
else
blue.add(slice);
i++;
}
Collections.shuffle(red);
Collections.shuffle(blue);
Collections.shuffle(black);
Iterator<Slice> itRed = red.iterator();
Iterator<Slice> itBlue = blue.iterator();
Iterator<Slice> itBlack = black.iterator();
slices.clear();
for (int j = 0; j < total; j++) {
if (j % 2 == 1)
slices.add(itRed.next());
else if (j % 10 == 0)
slices.add(itBlack.next());
else
slices.add(itBlue.next());
}
return slices;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.