魔术方块程序中用于检查方块是否为魔术的StackOverflow错误



我想我会说到点子上:我的计算机科学老师给了我们一个作业,他想让我们创建一个程序,生成一个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都能工作,它只是在重新洗牌n次后给出stackOverflowError。我测试了一下,如果我删除了checkIfMagic函数中的一些限制(例如,我尝试了if(row1 == MAGICNUM && row2 == MAGICNUM && row3 == MAGICNUM)(,它是否会这样做,但它没有。相反,它输出了它应该有的东西:一个行的总和等于15的正方形。当代码为if(row1 == MAGICNUM && row2 == MAGICNUM && row3 == MAGICNUM && col1 == MAGICNUM && col2 == MAGICNUM && col3 == MAGICNUM)时,它开始显示stackOverflowError。然而,由于正方形必须是魔术(同样,所有行、列和对角线的总和都等于相同的值(,我不能使用它。

我想我的主要问题是如何修复这个错误,让它继续洗牌,直到它返回一个魔术方块,以及是否有更好的地方或方法来重新洗牌,直到变成魔术。

试试这个:

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内部调用printMagicSSquare时。调用方的参数仍在作用域中,因此不会释放内存。运行时在旧堆栈帧之上创建新堆栈帧,以存储被调用者的局部变量和参数。这种情况会反复进行,直到一个printMagicSquare找到答案,或者当我们耗尽堆栈内存时。因为shuffleSquare不起作用,所以只有一条路要走。

while (!checkIfMagic(square)){
shuffleSquare(square, square.length - 1);
}

这个不进行递归调用,即使它永远运行,也能保持栈顶的稳定。

最新更新