【问题标题】:StackOverflowError in Magic Square program for checking if square is magicMagic Square 程序中的 StackOverflowError 用于检查正方形是否是魔法
【发布时间】:2018-12-19 00:10:29
【问题描述】:

我想我要直截了当:我的计算机科学老师给了我们一个作业,他希望我们创建一个程序来生成一个 3 x 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 &amp;&amp; row2 == MAGICNUM &amp;&amp; row3 == MAGICNUM)),它是否会这样做,但它没有。相反,它输出了它应该具有的确切内容:行总和等于 15 的正方形。当代码为 if(row1 == MAGICNUM &amp;&amp; row2 == MAGICNUM &amp;&amp; row3 == MAGICNUM &amp;&amp; col1 == MAGICNUM &amp;&amp; col2 == MAGICNUM &amp;&amp; col3 == MAGICNUM) 时,它开始显示 stackOverflowError。但是,由于正方形必须是魔法(同样,所有行、列和对角线的总和都等于相同的值),我不能使用它。

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

【问题讨论】:

  • 您需要在代码中添加一些 println,以查看您的递归停止条件永远不会实现以及原因。你的递归有点复杂,因为你有方法调用其他方法,然后调用它们自己和第一个方法。
  • @HovercraftFullOfEels 感谢您的提示!下次我发布问题时,我会记住这一点。

标签: java recursion stack-overflow magic-square


【解决方案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);
    }

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

【讨论】:

  • 请解释您的答案,而不是简单地提供代码转储。如果不解释 OP 的问题以及为什么您的解决方案有助于解决它,那么答案对未来的访问者没有帮助。
  • 如果您认为无法补救,请随时修改答案或发布新答案。我出去吃晚饭了。
  • @JohnSmith 谢谢你的帮助!我今天去找我的老师问这个代码是否可以;他说我误解了他的意思,并帮助我理解了他想要什么。我不得不重做一些代码并设法解决它。很抱歉给您带来麻烦,再次感谢您!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-05
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
  • 1970-01-01
  • 2011-03-11
  • 1970-01-01
相关资源
最近更新 更多