繁体   English   中英

如何对 ArrayList 进行混洗,但在混洗特定索引后保持不变?

[英]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 algorithmCollections.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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM