简体   繁体   中英

Iterating through a list searching for duplicates

So I have this task that I must do a dice roller and then search for a certain combination if it was rolled. I have an overriden equals method, that checks for the combination and it is working properly. Every object from the class Dice has its own string array which contains information about on which roll is the combination rolled. For example combination of two rolled dice (2, 4) was rolled on 5th roll out of 5 so its array has: [.., .., .., .., 5] And then each object from the class Dice is stored in a List<Dice> which on the other hand is put into a hashmap alongside each dice' string array. My struggles are that I can't understand how to iterate over the list of dice and check if each combination was rolled more than once and put the information about on which roll it's on into the first and then removing the duplicate.

For example let's say the combination (4, 1) has been rolled on the first and then on the 4th roll... its string array should look like: [1, .., .., 4, ..] , instead, the printing of the hashmap shows 2 elements with (4, 1) combination and their own arrays:

[1, .., .., .., ..] , [.., .., .., 4, ..] .

I hope you understand my struggles.

public class Dice {
  private int firstDice;
  private int secondDice;
  public String[] rollArray;
  public int roll;
  public int duplicate = 1; 

  /**
   * Constructor for the class Dice.
   * @param first first dice
   * @param second second dice
   */
  public Dice(int first, int second) {
    firstDice = first;
    secondDice = second;
  }

  @Override
  public String toString() {
    return "(" + firstDice + ", " + secondDice + ")";
  }

  /**
   * Method equals used for comparing two objects from the class Dice.
   * @param obj object from dice class
   * @return returns true/false if conditions are matched.
   */
  public boolean equals(Dice obj) {
    return (obj.firstDice == firstDice && obj.secondDice == secondDice);
  }
}



import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

/**
 * Created by leo on 6/10/15. Class which contains all methods that realize the rolling of two dices
 * and storing the information about them in a hash map.
 */
public class DiceRoller {

  public List<Dice> diceList = new LinkedList<>();
  public List<String> rollingList = new LinkedList<>();

  /**
   * A method which rolls two dices a number of times with random values.
   *
   * @param numberOfRolls number of rolls
   */
  public void rollDice(int numberOfRolls) {
    Random rand = new Random();
    for (int i = 0; i < numberOfRolls; i++) {
      diceList.add(i, new Dice(rand.nextInt(7 - 1) + 1, rand.nextInt(7 - 1) + 1));
      diceList.get(i).rollArray = new String[numberOfRolls];
      diceList.get(i).roll = i + 1;
      diceList.get(i).rollArray[i] = diceList.get(i).roll + "";
      rollingList.add("" + (i + 1));
      checkDuplicateDice(diceList, diceList.get(i));
    }
  }


  private void checkDuplicateDice(List<Dice> listOfDice, Dice tempDice) {
    /*
     * for (int i = 0; i < listOfDice.size(); i++) { for (int j = i + 1; j < listOfDice.size(); j++)
     * { if (listOfDice.get(i).toString().equals(listOfDice.get(j).toString())) {
     * listOfDice.get(i).duplicate++; } } } for (int i = 0; i < listOfDice.size(); i++) {
     * System.out.println(listOfDice.get(i).toString() + listOfDice.get(i).duplicate); }
     */
    Iterator<Dice> iter = listOfDice.iterator();
    while (iter.hasNext()) {
      Dice elem = iter.next();
      if (elem.toString().equals(tempDice.toString())) {
        elem.duplicate++;
      }
      System.out.println(elem.toString() + elem.duplicate);
    }
  }

  /**
   * A method which checks if the combination entered is rolled.
   *
   * @param first first dice
   * @param second second dice
   */

  public void checkCombination(int first, int second) {
    Dice checker = new Dice(first, second);
    int index = 1;
    boolean flag = false;
    for (Dice diceObject : diceList) {
      diceObject.rollArray = new String[diceList.toArray().length];
      diceObject.rollArray[index - 1] = index + "";
      for (int i = 0; i < diceList.size(); i++) {
        if (diceObject.rollArray[i] == null) {
          diceObject.rollArray[i] = "..";
        }
      }

      if (diceObject.equals(checker)) {
        System.out.println("Combination: (" + first + ", " + second + ") rolled on roll No: "
            + index);
        flag = true;
      }
      index++;
    }
    if (!flag) {
      System.out.println("Combination not rolled.");
    }
  }

  /**
   * A method which stores the data of the dice and each dice'.
   */
  public void hashMapThingy() {
    System.out.print("Roll: ");
    for (int i = 0; i < rollingList.size(); i++) {
      System.out.print((i + 1) + " ");
    }

    System.out.print("\n");
    System.out.println("Comb:");
    HashMap<Dice, String[]> hm = new HashMap<>();
    for (Dice diceObject : diceList) {
      hm.put(diceObject, diceObject.rollArray);
    }

    Set<Map.Entry<Dice, String[]>> set = hm.entrySet();
    for (Map.Entry<Dice, String[]> me : set) {
      System.out.println(me.getKey() + " " + Arrays.toString(printArray(me.getValue())));
    }
  }

  /**
   * Printer method.
   * 
   * @param array array that contains the roll number
   * @return returns the array string
   */
  public String[] printArray(String[] array) {
    return array;
  }
}


public class Test {
  /**
   * Main function.
   * 
   * @param args arguments
   */
  public static void main(String[] args) {
    int number = 5;
    DiceRoller diceRoller = new DiceRoller();
    diceRoller.rollDice(number);
//    Dice.fillDiceList();

//    Dice.printListDices();
    diceRoller.checkCombination(3, 2);
    diceRoller.checkCombination(1, 3);
    diceRoller.checkCombination(6, 3);
    diceRoller.hashMapThingy();
  }
}

And current console output:

(5, 1)2
(5, 1)2
(1, 1)2
(5, 1)3
(1, 1)2
(5, 1)2
(5, 1)3
(1, 1)2
(5, 1)2
(1, 5)2
(5, 1)3
(1, 1)2
(5, 1)2
(1, 5)2
(4, 4)2
Combination not rolled.
Combination not rolled.
Combination not rolled.
Roll: 1 2 3 4 5 
Comb:
(1, 1) [.., 2, .., .., ..]
(1, 5) [.., .., .., 4, ..]
(5, 1) [1, .., .., .., ..]
(5, 1) [.., .., 3, .., ..]
(4, 4) [.., .., .., .., 5]

The problem is with your checkDuplicateDice method

  private void checkDuplicateDice(List<Dice> listOfDice, Dice tempDice) {
  boolean duplicate = false;
  for (Dice elem : listOfDice) {
      if (elem.roll != tempDice.roll && elem.toString().equals(tempDice.toString())) {
            elem.duplicate++;
            elem.rollArray[tempDice.roll-1] = tempDice.roll + "";
            duplicate = true;
        }
  }
  if(duplicate)
      listOfDice.remove(tempDice.roll -1);

}

Like above you need to update your rollArray and send it back so that rollArray will be updated.

Doing it this way is not the best way but changing as above will get the answer you want

I wondered if I could follow Sujit Chaitanya's logic and I thought why not the method return an object from the class Dice, instead of void then use that object to remove it safely without exceptions.. I modified it a bit and it turned out pretty good.

private Dice checkDuplicateDice(List<Dice> listOfDice, Dice tempDice) {

boolean duplicate = false;
for (Dice elem : listOfDice) {
  if (elem.roll != tempDice.roll && elem.toString().equals(tempDice.toString())) {
    elem.rollArray[tempDice.roll - 1] = tempDice.roll + "";
    duplicate = true;
  }
}
if (duplicate) {
  return tempDice;
}
return null;

}

In the rollDice method I inserted a new for loop after the first one:

for (int j = 0; j < diceList.size(); j++) {
  if (checkDuplicateDice(diceList, diceList.get(j)) != null) {
    diceList.remove(j);
  }
}

I also modified the checkCombination method to not override the array. I added a new global variable listSize which takes the diceList.size() right after all the dices have been rolled so that it won't change after a dice is removed. I use the listSize in the loop in order to correctly mark those elements of the string array that don't contain a value (are null )

public void checkCombination(int first, int second) {
Dice checker = new Dice(first, second);
int index = 1;
boolean flag = false;
for (Dice diceObject : diceList) {

  for (int i = 0; i < listSize; i++) {
    if (diceObject.rollArray[i] == null) {
      diceObject.rollArray[i] = "..";
    }
  }

  if (diceObject.equals(checker)) {
    System.out.println("Combination: (" + first + ", " + second + ") rolled on roll No: "
        + index);
    flag = true;
  }
  index++;
}
if (!flag) {
  System.out.println("Combination not rolled.");
}

}

Then the output was as follows:

Roll: 1 2 3 4 5 
Comb:
(2, 1) [.., .., 3, .., ..]
(3, 6) [.., 2, .., 4, 5]
(6, 5) [1, .., .., .., ..]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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