Как перезапустить цикл do-while, если последнее условие не выполняется?
Я пробовал это сам и искал везде ответ и, кажется, не могу найти подходящий обходной путь. Я нашел много ответов на этом сайте раньше, поэтому я зарегистрировался, чтобы задать свой вопрос. У меня есть программа, которая перебирает 6 пользователей и назначает их на должность. Пользователи: Альфа, Браво, Чарли, Дельта, эхо и Фрэнк. Позиции: 1,2,3,4,5,6. Я генерирую случайные числа, чтобы назначить пользователю его позицию. У меня есть одно правило, которое я проверяю; ни один пользователь не может быть назначен одному и тому же позиция дважды. Из-за этого правила и случайного назначения пользователей станциям, иногда единственным пользователем, оставшимся на позиции 6, является пользователь, который уже был назначен на позицию 6 в предыдущей ротации. Когда это происходит, моя программа выходит из строя, и это справедливо. Как мне преодолеть это? У меня были случаи, когда программа делала правильный выбор, и у меня было 6 успешных ротаций. Я хотел бы иметь 6 успешных ротаций каждый раз. Я потратил две недели, пытаясь понять это. Любая помощь, которую я могу получить, будет очень признательна. Спасибо. Я вставил свой код ниже. Я использую Java.
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.border.EmptyBorder;
import java.awt.Color;
import java.awt.CardLayout;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
public class test extends JFrame implements ActionListener {
/**
*
*/
private static final long serialVersionUID = 1L;
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
test frame = new test();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
//TODO
int randnum[] = new int [7];
int numOfRotations = 1;
String[] String_CurrentOperator = new String[7];
Random rand_opers = new Random();
List<Integer> ArrayList_UsedRandNums = new ArrayList<>();
List<List<String>> ArrayList_MainOperatorHistory = new ArrayList<List<String>>();
List<String> ArrayList_AllOpers = new ArrayList<>();
List<String> ArrayList_UsedOpers = new ArrayList<>();
List<String> ArrayList_OperatorHistory1 = new ArrayList<>();
List<String> ArrayList_OperatorHistory2 = new ArrayList<>();
List<String> ArrayList_OperatorHistory3 = new ArrayList<>();
List<String> ArrayList_OperatorHistory4 = new ArrayList<>();
List<String> ArrayList_OperatorHistory5 = new ArrayList<>();
List<String> ArrayList_OperatorHistory6 = new ArrayList<>();
public test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 450, 300);
contentPane = new JPanel();
contentPane.setBackground(Color.DARK_GRAY);
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
setContentPane(contentPane);
contentPane.setLayout(new CardLayout(0, 0));
JButton btnShuffle = new JButton("SHUFFLE");
contentPane.add(btnShuffle, "name_253561263644851");
btnShuffle.addActionListener(this);
ArrayList_AllOpers.add("POSITION ZERO");
ArrayList_AllOpers.add("Alpha");
ArrayList_AllOpers.add("Bravo");
ArrayList_AllOpers.add("Charlie");
ArrayList_AllOpers.add("Delta");
ArrayList_AllOpers.add("Echo");
ArrayList_AllOpers.add("Frank");
ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory1);
ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory1);
ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory2);
ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory3);
ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory4);
ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory5);
ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory6);
}
public void actionPerformed(ActionEvent arg0) {
/*******************************
*****ASSIGN ALL OPERATORS******
*******************************/
System.out.println("THIS IS ROTATION "+numOfRotations);
genRandoms();
for(int i=1; i<6+1; i++){
do{
//randnum[i] = rand_opers.nextInt(6)+1;
String_CurrentOperator[i] = ArrayList_AllOpers.get(randnum[i]);
}
while(ArrayList_UsedOpers.contains(String_CurrentOperator[i]) || ArrayList_MainOperatorHistory.get(i).contains(String_CurrentOperator[i]));
ArrayList_UsedOpers.add(String_CurrentOperator[i]); //add to used names thus far
}
for(int i=1; i<6+1; i++){
System.out.println(String_CurrentOperator[i]); //Prints the name of the operator working on the station
ArrayList_MainOperatorHistory.get(i).add(String_CurrentOperator[i]); //adds operator to list of all users who have been assigned to this station
}
//Perform cleanup actions for next iteration of the loop
numOfRotations++; //increment the rotation count by 1
ArrayList_UsedRandNums.clear(); //clear the list of randum numbers used
ArrayList_UsedOpers.clear(); //clear the list of assigned operators
System.out.println("");
}
public void genRandoms(){
for(int i=1; i<6+1; i++){
do{
randnum[i] = rand_opers.nextInt(6)+1;
}
while (ArrayList_UsedRandNums.contains(randnum[i]));
ArrayList_UsedRandNums.add(randnum[i]); //add randnum[i] to list of random numbers used thus far
}
}
}
3 ответа:
Задачу можно переформулировать следующим образом:
У вас есть сетка/матрица 6x6:
1 2 3 4 5 6 r1 A B C D E F r2 F A B C D E r3 E F A B C D r4 D E F A B C r5 C D E F A B r6 B C D E F A
Со столбцами, являющимися позициями сидений,строками, являющимися вращениями, и значениями ячеек, являющимися Альфа, Бета, Чарли,... Вы хотите перемешать эту сетку случайным образом, не нарушая ограничения, что в каждой строке и столбце Значение встречается только один раз.
Это похоже на перетасовку сетки судоку. Эта задача не слишком тривиальна. Вот ответ, который дает решение с помощью backtracking: Как создать полную доску судоку Простым решением может быть произвольная замена строк и столбцов исходной сетки.Вот моя попытка создать, надеюсь, безошибочное решение с обратным отслеживанием: Строки изначально перемешиваются с помощью алгоритма Фишера-Йейтса. Затем сетка проверяется сверху вниз с помощью обратного отслеживания.
public static int[][] fillGrid(Random random, int size){ int[][] grid = new int[size][size]; do{ for(int row = 0; row < size; row++){ grid[row] = IntStream.rangeClosed(1, size).toArray(); shuffleArray(grid[row], random); //randomize row } }while(!validate(grid, 0, 0)); //defensive: reroll if failed to validate (should not happen) return grid; } private static boolean validate(int[][] grid, int row, int col){ if(col == grid.length){ if(row == grid.length-1){ //end of grid reached -> whole grid is valid return true; } //end of valid row reached -> validate next row return validate(grid, row + 1, 0); } //search for a value that makes the whole row valid for(int i = col; i < grid.length; i++){ swap(grid[row], i, col); //try next value //check if the current column is valid boolean validCol = true; for(int j = 0; j < row; j++){ if(grid[j][col] == grid[row][col]){ validCol = false; break; } } if (validCol && validate(grid, row, col + 1)){ //the whole row is valid return true; } swap(grid[row], i, col); //value does not fit -> swap back } //the row is invalid return false; } private static void shuffleArray(int[] array, Random random){ for (int i1 = array.length - 1; i1 > 0; i1--){ int i2 = random.nextInt(i1 + 1); swap(array, i1, i2); } } private static void swap(int[] array, int i1, int i2){ int temp = array[i1]; array[i1] = array[i2]; array[i2] = temp; }
Вызов метода
fillGrid(new Random(), 6)
даст вам перетасованную сетку, которая удовлетворяет ограничениям. Вы можете получить доступ к значениям с[numOfRotations-1][i-1]
в каждой итерации внутри вашего цикла for. Нет необходимости использоватьArrayList_UsedOpers
илиArrayList_MainOperatorHistory
.
Я думаю, что ваша логика кажется правильной. Однако массивы основаны на нуле, поэтому у вас есть проблема. Попробуйте изменить свои два цикла for следующим образом:
for(int i=0; i<6; i++){
Я придумал это решение, которое до сих пор срабатывало каждый раз. Спасибо за все отзывы. Это может быть не самый эффективный код, но, безусловно, работает так, как ожидалось. Я включил некоторые настройки, позволяющие вычислять до 10 вращений. Хотя он действительно борется с этим. Надеюсь, кто-нибудь найдет это полезным.
import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.border.EmptyBorder; import java.awt.Color; import java.awt.CardLayout; import java.util.ArrayList; import java.util.List; import java.util.Random; import javax.swing.JButton; public class test extends JFrame implements ActionListener { /** * */ private static final long serialVersionUID = 1L; private JPanel contentPane; /** * Launch the application. */ public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { public void run() { try { test frame = new test(); frame.setVisible(true); } catch (Exception e) { e.printStackTrace(); } } }); } /** * Create the frame. */ //TODO int numOfStations = 6; boolean cleared[] = new boolean[21]; boolean finalCleared = false; int randnum[] = new int [numOfStations+1]; int numOfRotations = 1; String[] String_CurrentOperator = new String[numOfStations+1]; Random rand_opers = new Random(); List<Integer> ArrayList_UsedRandNums = new ArrayList<>(); List<List<String>> ArrayList_MainOperatorHistory = new ArrayList<List<String>>(); List<String> ArrayList_AllOpers = new ArrayList<>(); List<String> ArrayList_CurrentRotationOperators = new ArrayList<>(); List<String> ArrayList_UsedOpers = new ArrayList<>(); List<String> ArrayList_OperatorHistory1 = new ArrayList<>(); List<String> ArrayList_OperatorHistory2 = new ArrayList<>(); List<String> ArrayList_OperatorHistory3 = new ArrayList<>(); List<String> ArrayList_OperatorHistory4 = new ArrayList<>(); List<String> ArrayList_OperatorHistory5 = new ArrayList<>(); List<String> ArrayList_OperatorHistory6 = new ArrayList<>(); List<String> ArrayList_OperatorHistory7 = new ArrayList<>(); List<String> ArrayList_OperatorHistory8 = new ArrayList<>(); List<String> ArrayList_OperatorHistory9 = new ArrayList<>(); List<String> ArrayList_OperatorHistory10 = new ArrayList<>(); public test() { setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300); contentPane = new JPanel(); contentPane.setBackground(Color.DARK_GRAY); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); setContentPane(contentPane); contentPane.setLayout(new CardLayout(0, 0)); JButton btnShuffle = new JButton("SHUFFLE"); contentPane.add(btnShuffle, "name_253561263644851"); btnShuffle.addActionListener(this); ArrayList_AllOpers.add("POSITION ZERO"); ArrayList_AllOpers.add("A"); ArrayList_AllOpers.add("B"); ArrayList_AllOpers.add("C"); ArrayList_AllOpers.add("D"); ArrayList_AllOpers.add("E"); ArrayList_AllOpers.add("F"); ArrayList_AllOpers.add("Greek"); ArrayList_AllOpers.add("Hospital"); ArrayList_AllOpers.add("Indigo"); ArrayList_AllOpers.add("Juliette"); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory1); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory1); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory2); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory3); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory4); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory5); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory6); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory7); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory8); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory9); ArrayList_MainOperatorHistory.add(ArrayList_OperatorHistory10); } public void actionPerformed(ActionEvent arg0) { finalCleared = false; for(int j=1; j<numOfStations+1; j++){ cleared[j]=false; } for(int j=numOfStations+1; j<21; j++){ cleared[j]=true; } /******************************* *****ASSIGN ALL OPERATORS****** *******************************/ //System.out.println("THIS IS ROTATION "+numOfRotations); for(int i=1; i<1+1; i++){ do{ //clears the list of operators used during last rotation ArrayList_CurrentRotationOperators.clear(); //Assign the operators for(int j=1; j<numOfStations+1; j++){ String_CurrentOperator[j] = ArrayList_AllOpers.get(randnum[j]); } //1. Ensure assigned operators or unique else fail finalCleared check //2. If finalCleared is true then exit do and for loops for(int j=1; j<numOfStations+1; j++){ if (ArrayList_MainOperatorHistory.get(j).contains(String_CurrentOperator[j]) || ArrayList_CurrentRotationOperators.contains(String_CurrentOperator[j])){ cleared[j]=false; } else{ cleared[j]=true; ArrayList_CurrentRotationOperators.add(String_CurrentOperator[j]); } } if (cleared[1]==true && cleared[2]==true && cleared[3]==true && cleared[4]==true && cleared[5]==true && cleared[6]==true && cleared[7]==true && cleared[8]==true && cleared[9]==true && cleared[10]==true){ finalCleared=true; } else{ genRandoms(); } } while(finalCleared == false); } //1. Prints the name of the operator working on the station //2. Adds operator to list of all users who have been assigned to station for(int i=1; i<numOfStations+1; i++){ System.out.print(String_CurrentOperator[i]+" "); ArrayList_MainOperatorHistory.get(i).add(String_CurrentOperator[i]); } //Perform cleanup actions for next iteration of the loop //1. increment the rotation count by 1 numOfRotations++; System.out.println(""); } /********************* **genRandoms Method** *********************/ public void genRandoms(){ for(int i=1; i<numOfStations+1; i++){ randnum[i] = rand_opers.nextInt(numOfStations)+1; } } }