StackruError в программе Magic Square для проверки, является ли квадрат магическим
Думаю, я подойду к сути: мой учитель информатики дал нам задание, в котором он хотел, чтобы мы создали программу, которая генерирует магический квадрат 3 на 3 (это означает, что все строки, столбцы и диагонали квадрата должны равняться 15).). Он хотел, чтобы мы использовали обычный массив (массив с одним измерением, а не с двумя) и имели как минимум две функции - одну рекурсивную и генерирующую или перемешивающую квадрат, а другую просто проверяющую, является ли квадрат магическим. Программа должна вернуть и распечатать магический квадрат, и пользовательский ввод не требуется.
Вот мой код (я ставлю это первым, так как проблему, которую я испытываю, легче объяснить, если она будет размещена первой; для конкретных вопросов перейдите к концу):
public class MagicSquare {
public static void main(String[] args) {
// main stub, get user input here
int[] square = {1, 2, 3, 4, 5, 6, 7, 8, 9};
//int[] test = {2, 7, 6, 9, 5, 1, 4, 3, 8};
//printMagicSquare(test);
shuffleSquare(square, 0);
printMagicSquare(square);
}
public static int[] shuffleSquare(int[] square, int count) {
// shuffles array
Random randGen = new Random();
if(count >= square.length-1) {
return square;
}
else {
int index = randGen.nextInt(square.length - 1) + 0;
int temp = square[count];
square[count] = square[index];
square[index] = temp;
shuffleSquare(square, count + 1);
}
return square;
}
public static boolean checkIfMagic(int[] square) {
// returns true or false for whether or not inputted array is a magic square
int MAGICNUM = 15;
int row1 = square[0] + square[1] + square[2];
//System.out.println(square[0] + " " + square[1] + " " + square[2]);
int row2 = square[3] + square[4] + square[5];
//System.out.println(square[3] + " " + square[4] + " " + square[5]);
int row3 = square[6] + square[7] + square[8];
//System.out.println(square[6] + " " + square[7] + " " + square[8] + "\n");
int col1 = square[0] + square[3] + square[6];
int col2 = square[1] + square[4] + square[7];
int col3 = square[2] + square[5] + square[8];
int diag1 = square[0] + square[4] + square[8];
int diag2 = square[2] + square[4] + square[6];
if(row1 == MAGICNUM && row2 == MAGICNUM && row3 == MAGICNUM && col1 == MAGICNUM && col2 == MAGICNUM && col3 == MAGICNUM && diag1 == MAGICNUM && diag2 == MAGICNUM) {
return true;
}
else {
return false;
}
}
public static void printMagicSquare(int[] square) {
// prints out magic square
boolean isMagic = checkIfMagic(square);
// check if square is magic (if it is, print it, if not then re-shuffle it and re-check it)
if(isMagic == true) {
System.out.println("Magic Square: ");
for(int count = 0; count < square.length; count ++) {
if(count == 3 || count == 6) {
System.out.println();
System.out.print(square[count] + " ");
}
else {
System.out.print(square[count] + " ");
}
}
System.out.println("\n");
}
else {
shuffleSquare(square, 0);
printMagicSquare(square);
}
}
}
Итак, проблема у меня в том, что программа перестает перетасовывать квадрат через определенное количество раз. Функции shuffleSquare и checkIfMagic работают, он просто выдает stackOverflowError после повторной перестановки n раз. Я проверил, будет ли это делать, если я уберу некоторые ограничения в функции checkIfMagic (например, я пытался if(row1 == MAGICNUM && row2 == MAGICNUM && row3 == MAGICNUM)
) и это не так. Вместо этого он вывел то, что должен иметь: квадрат, где суммы строк были равны 15. Он начал показывать stackOverflowError, когда код был if(row1 == MAGICNUM && row2 == MAGICNUM && row3 == MAGICNUM && col1 == MAGICNUM && col2 == MAGICNUM && col3 == MAGICNUM)
, Однако, поскольку квадрат должен быть магическим (опять же, имея сумму всех строк, столбцов и диагоналей, равную одному значению), я не могу использовать это.
Я предполагаю, что мои основные вопросы - как мне исправить эту ошибку, чтобы она вместо этого продолжала перетасовываться, пока не вернется магический квадрат, и если есть лучшее место или способ перестановить квадрат, пока он не станет магическим.
1 ответ
Попробуй это:
public class MagicSquare {
public static void main(String[] args) {
// main stub, get user input here
int[] square = {1, 2, 3, 4, 5, 6, 7, 8, 9};
printMagicSquare(square);
}
static Random randGen = new Random();
public static void shuffleSquare(int[] square, int i) {
if (i > 0) {
int index = randGen.nextInt(i);
int temp = square[index];
square[index] = square[i];
square[i] = temp;
shuffleSquare(square, i - 1);
}
}
public static boolean checkIfMagic(int[] square) {
// returns true or false for whether or not inputted array is a magic square
int MAGICNUM = 15;
int row1 = square[0] + square[1] + square[2];
//System.out.println(square[0] + " " + square[1] + " " + square[2]);
int row2 = square[3] + square[4] + square[5];
//System.out.println(square[3] + " " + square[4] + " " + square[5]);
int row3 = square[6] + square[7] + square[8];
//System.out.println(square[6] + " " + square[7] + " " + square[8] + "\n");
int col1 = square[0] + square[3] + square[6];
int col2 = square[1] + square[4] + square[7];
int col3 = square[2] + square[5] + square[8];
int diag1 = square[0] + square[4] + square[8];
int diag2 = square[2] + square[4] + square[6];
if(row1 == MAGICNUM && row2 == MAGICNUM && row3 == MAGICNUM && col1 == MAGICNUM && col2 == MAGICNUM && col3 == MAGICNUM && diag1 == MAGICNUM && diag2 == MAGICNUM) {
return true;
}
else {
return false;
}
}
public static void printMagicSquare(int[] square) {
while (!checkIfMagic(square)){
shuffleSquare(square, square.length - 1);
}
System.out.println("Magic Square: ");
for(int count = 0; count < square.length; count ++) {
if(count == 3 || count == 6) {
System.out.println();
System.out.print(square[count] + " ");
}
else {
System.out.print(square[count] + " ");
}
}
System.out.println("\n");
}
}
Память стека локальных переменных освобождается только после того, как переменные выходят из области видимости. Когда вы вызываете printMagicSquare внутри printMagicSquare. Параметр вызывающей стороны все еще находится в области видимости, поэтому память не освобождается. Среда выполнения создает новые стековые фреймы над старыми для хранения локальных переменных и параметров вызываемой стороны. И это повторяется до тех пор, пока один printMagicSquare не найдет ответ или когда мы исчерпаем память стека. Поскольку shuffleSquare не работает, есть только один путь.
while (!checkIfMagic(square)){
shuffleSquare(square, square.length - 1);
}
Этот не делает никаких рекурсивных вызовов, он сохраняет стабильность вершины стека, даже если он работает вечно.