首页 > 解决方案 > 如何改组 ArrayList,但改组特定索引后保持不变?

问题描述

在我的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;      
  }
}

任何帮助表示赞赏

标签: javaarraylist

解决方案


没有“简单”的方式(例如,通过现有的方法,例如Collections.shuffle);你必须自己编程这个功能,但你当然可以使用一些现有的东西来帮助你。

一种有点迂回的方法是“解构和重构”:编写一个方法,将单个列表分解为 3 个单独的列表(每种颜色 1 个),然后将它们打乱,然后将三个单独的列表“重构”回一个大列表,使用明显的算法(如果索引能被 10 整除,则从黑名单中抓取下一个,否则如果能被 2 整除,则从蓝名单中抓取,否则,从红名单中抓取)。

另一种方法是自己实现洗牌算法。对于上下文,您正在寻找Fisher-Yates shuffle algorithm,它的实现Collections.shuffle也使用了该算法。要知道的关键事项:

  • 要获得 0 到 N 之间的随机数,请调用(创建单个实例,一次,并继续重复使用它)的实例.nextInt(n)Random不要使用 common (int) (Math.random() * n),这是微妙的错误(鸽子原则)和非惯用的 java。

  • Fisher yates 主要涉及从开始(索引 0)到倒数第二个元素(具有索引的那个)遍历列表list.size() -2。对于每个元素,将其与一个统一的随机选择的元素交换,该元素本身或它上面的任何元素。

换句话说,要 shuffle 1,2,3,4,5,我们从第 0 个元素(第 1 个)开始,并从其自身中选择任何均匀随机的元素并与之交换。这是5个元素的选择,所以我们打电话rnd.nextInt(5)来弄清楚。该随机数可能是 0,在这种情况下,“你将 1 与它自己交换”,这意味着它保持原位(嘿,洗牌意味着随机;有时一张牌在洗牌后会出现在牌堆中的同一个位置!)。然后对于下一个元素(索引 1 处的 2),您从其自身(即索引 1)中选择任何索引直到最后,因此我们调用rnd.nextInt(4),依此类推。

对于这个练习,棘手的一点是要弄清楚有多少有效的“在你之上”可以交换存在(这将是你传递给的参数rnd.nextInt(X)),以及如何翻译你的 nextInt 调用给你的数字您现在需要交换的索引。

请注意,此算法完全可以正常工作;不需要任何额外的列表或数组。您只需要一个临时变量来启用交换。

这听起来像家庭作业,所以我不会为你预先咀嚼答案。希望这足以让您自己编写它。祝你好运!


推荐阅读