【问题标题】:Knights Tour Java骑士游爪哇
【发布时间】:2022-01-03 00:09:35
【问题描述】:

当我运行程序而不是找到 Knights Tour 时,我收到了 StackOverflow 错误。知道是什么原因造成的,以及如何更改我的代码以实际找到 Knights Tour 并摆脱此错误。项目适用于我的 CS280 课程,将于周五到期,请帮忙。谢谢!!

public class KnightsTourDriver {
    public static void main (String[]args) {
        KnightsTour tour1 = new KnightsTour;
        tour1.findTour(1);
        tour1.displayTour();
    }
}  



import java.util.Arrays;
class KnightsTour
{

    static int the_board[][] = new int[8][8];
    int the_tour[][] = new int [8][8];
    int k,moves = 0;
    int x = 0, y = 0; 
    int z, j = 1;
    boolean tour_found, isSafe;

        //fills 2D array with 0's
        public KnightsTour()
        {
            for (int i = 0; i < 8; i++) 
                {
                 for (int r = 0; r < 8; r++) 
                    {
                            the_board[i][r] = 0;
                        }
                }
        }
        /*recursive method, checks how many moves were made if 16 were made tour finished, 
        else if not moves knight checks if the move is valid if not back tracks*/
        public void findTour(int q)
        {

            if(moves == 64)
                {
                    tour_found = true;
                }

            else 
                move(q); 

            if(isSafe == true)
                    {
                        findTour(q++);
                        moves++;
                    }
            else
                if(isSafe == false)
                    {
                        findTour(q*(-1));
                        moves--;
                    }
        }
        //used to keep prevent arrayindexoutofbounds error
        public boolean arrayInBounds(int x, int y)
        { 
        if(x < 8 && y < 8 && x >= 0 && y >= 0)
                {
                    return true;
                }
            else return false;
        }
        /*move method uses switch statement to decide which move the knight should make
        based on a case number, negative case numbers back track knight. if statement checks
        if the current array element is empty and the index is inbounds*/
        public void move(int a)
        {

            switch (a)
            {
               case 1:
                if(arrayInBounds(x+2, y+1) == true){
                   if(the_board[x+2][y+1] != 0){                          
                        the_board[x+2][y+1]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
                    }
                else isSafe = false;
               case 2:
                if (arrayInBounds(x+1, y+2) == true){
                    if(the_board[x+1][y+2] != 0){               
                            the_board[x+1][y+2]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
                }
                else isSafe = false;
               case 3:
                 if(arrayInBounds(x-1, y+2) == true){
                   if(the_board[x-1][y+2] != 0){           
                            the_board[x-1][y+2]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
                 }
                else isSafe = false;
               case 4:
                if (arrayInBounds(x-2, y+1) == true){
                    if(the_board[x-2][y+1] != 0){           
                            the_board[x-2][y+1]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
                }
                else isSafe = false;
               case 5:
                if(arrayInBounds(x-2, y-1) == true){
                    if(the_board[x-2][y-1] != 0){           
                            the_board[x-2][y-1]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
                }
                else isSafe = false;
               case 6:
                if(arrayInBounds(x-1, y-2) == true){
                        if(the_board[x-1][y-2] != 0){                    
                            the_board[x-1][y-2]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
            }
                else isSafe = false;
               case 7:
                 if(arrayInBounds(x+1, y-2) == true){
                    if(the_board[x+1][y-2] != 0){          
                            the_board[x+1][y-2]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
                 }
                 else isSafe = false;
               case 8:
                if(arrayInBounds(x+2, y-1) == true){
                 if(the_board[x+2][y-1] != 0){
                            the_board[x+2][y-1]=j;
                            j++;
                            break;
                        }
                        else isSafe = false;
                        break;
                }
                else isSafe = false;
               case -1:
                      j--;
                      tryNextMove(a);
                      break;
                    case -2:
                        j--;
                        tryNextMove(a);
                        break;
                    case -3:
                      j--;
                      tryNextMove(a);
                      break;
                    case -4:
                      j--;
                      tryNextMove(a);
                      break;
                  case -5:
                     j--;
                      tryNextMove(a);
                      break;
                    case -6:
                      j--;
                      tryNextMove(a);
                      break;
                    case -7:
                      j--;
                      tryNextMove(a);
                      break;
                   case -8:
                      j--;
                      tryNextMove(a);
                      break;
             }
        }
        public void tryNextMove(int m)
        {
            move(m++);
        }
        //for loop to display tour once found//         
        public void displayTour()
        {
            int v = 1;
            for (int i = 0; i < 8; i++) 
                {
                 for (int e = 0; e < 8; e++) 
                    {               
                                if(v % 8 == 0)
                                {
                                    System.out.print(the_board[i][e] + "\t");
                                    System.out.println("\n");
                                } 
                        else    
                            System.out.print(the_board[i][e] + "\t");
                            v++;                
                        }
                }
        }
}

【问题讨论】:

  • 堆栈跟踪会很好,但如果您自己调试它,那将比我们提供的任何答案更能帮助您。
  • 查看if 方法中的第一组findTour 条件;是否有一条路径不会再次递归调用findTour
  • 请了解后自增和前自增运算符。也许你会看到你的错误。
  • 你介意把它放在一个主要的方法中吗?所以 some1 readng 可以用代码快速播放
  • 如何显示堆栈跟踪?

标签: java recursion backtracking knights-tour


【解决方案1】:

如果您的算法确实需要大量递归调用,您可以在启动时将参数传递给 JVM 以增加堆栈大小的限制:-Xss4m

当然,如果你的算法没有限制地递归,这只会延迟问题。

【讨论】:

    【解决方案2】:

    您需要在 switch 中的 case 语句中进行一些中断,否则它将失败。

    【讨论】:

    • 我实现了 break 语句,但仍然出现此错误
    • KnightsTour.try.tryNextMove(KnightsTour.java:189) 在 KnightsTour.move(KnightsTour.java:155) 的线程“main”java.lang.StackOverflowError 中出现异常(KnightsTour.java:155)---jGRASP 楔形 2:退出代码进程为1。----jGRASP:操作完成。
    • if/else 情况下的中断对我来说看起来不正确。并且您需要包含行号,以便我们可以看到第 189 行在哪里。
    • KnightsTour tour1 = 新 KnightsTour;一开始就错了!
    • 好吧,我不会为你调试它,但我运行了它。看起来它永远不会终止。您需要考虑终止条件,以及不满足这些条件的原因。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-09
    • 1970-01-01
    • 2014-03-24
    相关资源
    最近更新 更多