Java: Trouble randomizing a DFS run to build a maze

こ雲淡風輕ζ 提交于 2019-12-25 01:36:40

问题


I'm having trouble randomizing the visit from a node to its neighbors, rarely is the whole graph (a MxN array, in this test 4x4) visited, I don't get what I'm doing wrong here.

import java.util.ArrayList;



class IJ {

    int i;
    int j;

    IJ (int i,int j){
        i = this.i;
        j= this.j;

    }

}


class Graph {

    int M;
    int N;

    int adjacencyMatrix[][];

    ArrayList <IJ> orderOfVisits;

    Graph(int M,int N){

        this.M=M;
        this.N=N;
        adjacencyMatrix=new int[M][N];

        for (int i=0; i<M; i++)
            for (int j=0;j<N;j++){
                    adjacencyMatrix[i][j]=-1; //mark all vertices as not visited
            }

        orderOfVisits = new ArrayList<IJ>();

    }

 String northOrEast () {

        double lottery = Math.random();

        if (lottery>0.5D) {return "north";}

        else {return "south";}


    }

 String southOrEastOrNorth() {

     double lottery=Math.random();

     if (lottery<=0.33D){
        return "south";
     }

     else if ((lottery > 0.33D) && (lottery <= 0.66D)) {
        return "east";
     }

     else if(lottery > 0.66D)
     {
        return "north";
     }

     System.out.println("method sEn has returned null ");
     return null;
 }


 String southOrEast(){

  double lottery = Math.random();

        if (lottery>0.5D) {return "south";}

        else {return "east";}


 }

String southOrEastOrWest() {

     double lottery=Math.random();

     if (lottery<=0.33D){
        return "south";
     }

     else if ((lottery > 0.33D) && (lottery <= 0.66D)) {
        return "east";
     }

     else if(lottery > 0.66D)
     {
        return "west";
     }

     System.out.println("method sEw has returned null ");
     return null;

}

String southOrWest(){

  double lottery = Math.random();

        if (lottery>0.5D) {return "south";}

        else {return "west";}


 }

String southOrNorthOrWest() {

     double lottery=Math.random();

     if (lottery<=0.33D){
        return "south";
     }

     else if ((lottery > 0.33D) && (lottery <= 0.66D)) {
        return "north";
     }

     else if(lottery > 0.66D)
     {
        return "west";
     }

     System.out.println("method sNw has returned null ");
     return null;

}

String northOrWest(){

  double lottery = Math.random();

        if (lottery>0.5D) {return "north";}

        else {return "west";}


 }

String eastOrNorthOrWest() {

     double lottery=Math.random();

     if (lottery<=0.33D){
        return "east";
     }

     else if ((lottery > 0.33D) && (lottery <= 0.66D)) {
        return "north";
     }

     else if(lottery > 0.66D)
     {
        return "west";
     }

     System.out.println("method eNw has returned null ");
     return null;

}

String any() {

     double lottery=Math.random();

     if (lottery<=0.25D){
        return "east";
     }

     else if ((lottery > 0.25D) && (lottery <= 0.50D)) {
        return "north";
     }

     else if ((lottery > 0.5D) && (lottery <= 0.75D)) {
        return "south";
     }

     else if(lottery > 0.75D)
     {
        return "west";
     }

     System.out.println("method any has returned null ");
     return null;

}



 String goWhere (boolean northValid, boolean southValid, boolean eastValid, boolean westValid, int i, int j){

   //border cases

     //left lower corner, only north and east are valid
     if ((northValid==true) && (southValid==false) &&(eastValid==true) && (westValid==false))
     {return northOrEast();}

      //left border:
     if ((northValid==true) && (southValid==true) && (eastValid==true) && (westValid==false))
     {return southOrEastOrNorth();}

     //upper left corner, only south and east are valid
     if ((northValid==false) && (southValid==true) && (eastValid==true) && (westValid==false))
     {return southOrEast();}


      //upper border
     if ((northValid==false) && (southValid==true) && (eastValid==true) && (westValid==true))
     {return southOrEastOrWest();}

      //upper right corner
     if ((northValid==false) && (southValid==true) && (eastValid==false) && (westValid==true))
     {return southOrWest();}

     //right border
     if ((northValid==true) && (southValid==true) && (eastValid==false) && (westValid==true))
     {return southOrNorthOrWest();}

     //lower right corner
     if ((northValid==true) && (southValid==false) && (eastValid==false) && (westValid==true))
     {return northOrWest();}

     //bottom border
     if ((northValid==true) && (southValid==false) && (eastValid==true) && (westValid==true))
     {return eastOrNorthOrWest();}

     //middle
     if ((northValid==true) && (southValid==true) && (eastValid==true) && (westValid==true))
     {return any();}


    System.out.println("go where a llegado a retornar null");
    return null;

 }


 void DFS(int i, int j){ // i,j identifies the vertex

     boolean northValid= false;
     boolean southValid= false;
     boolean eastValid = false;
     boolean westValid = false;


     int iNorth, jNorth;
     int iSouth, jSouth;
     int iEast, jEast;
     int iWest, jWest;

     iNorth=i-1;
     if (!(iNorth<0)) northValid=true;

     iSouth=i+1;
     if(!((iSouth)>=M)) southValid=true;

     jEast=j+1;
     if(!((jEast)>=N)) eastValid=true;

     jWest= j-1;
     if (!(jWest<0)) westValid=true;



    if (adjacencyMatrix[i][j]==-1){ //if the vertex is unvisited

        adjacencyMatrix[i][j]=0; //mark the vertex as visited
        IJ ij = new IJ(i,j);
        orderOfVisits.add(ij); //add the vertex to the visit list
        System.out.println("Visit i,j: " + i +" " +j);






//boolean wentNorth = false;
//boolean wentSouth=false;
//boolean wentEast = false;
//boolean wentWest = false;

     //  if (where!=null)
       for (int rows=i; rows<M; rows++)
           for (int cols=j; cols<N; cols++){

         //normal DFS

            String where = goWhere(northValid, southValid, eastValid, westValid, i,j);

            if (where.equals("north"))
            {
                DFS(iNorth,j);
                //wentNorth=true;
            }



            if (where.equals("south")){
                DFS(iSouth,j);
            }

            if(where.equals("east")){
                DFS(i, jEast);
            }

            if (where.equals("west")){
                DFS(i,jWest);
            }


//            if(northValid)
//            {
//                DFS(iNorth,j);
//            }
//
//            if(southValid){
//                DFS(iSouth,j);
//            }
//
//            if(eastValid){
//                DFS(i, jEast);
//            }
//
//            if(westValid){
//                DFS(i,jWest);
//            }


      }



   }






//    boolean southValid;
//    int iSouth, jSouth;
//    iSouth=i+1; jSouth=j;
//    if (iSouth>=M){
//        southValid=false;
//    }
//    else {
//        southValid=true;
//    }
//
//    boolean southUnvisited;
//    if ((southValid)&&
//         (adjacencyMatrix[iSouth][jSouth]==-1)){
//        southUnvisited=true;
//    }
//    else{
//        southUnvisited=false;
//    }
//
//
//    boolean northValid;
//    int iNorth, jNorth;
//    iNorth=i-1; jNorth=j;
//
//    if(iNorth<0){
//        northValid=false;
//    }
//
//    else{
//        northValid=true;
//     }
//
//    boolean northUnvisited;
//    if ((northValid)
//         &&(adjacencyMatrix[iNorth][jNorth]==-1)){
//        northUnvisited=true;
//    }
//    else {
//        northUnvisited=false;
//    }
//
//    boolean westValid;
//    int iWest, jWest;
//    iWest =i; jWest=j-1;
//    if (jWest<0){
//        westValid=false;
//    }
//    else {
//        westValid=true;
//    }
//
//    boolean westUnvisited;
//
//
//    if ((westValid)&&(adjacencyMatrix[iWest][jWest]==-1))
//      {
//        westUnvisited=true;
//       }
//        else {
//        westUnvisited=false;
//        }
//
//
//
//    boolean eastValid;
//    int iEast, jEast;
//    iEast=i; jEast=j+1;
//    if (jEast<0){
//        eastValid=false;
//    }
//     else{
//        eastValid=true;
//    }
//
//    boolean eastUnvisited;
//    if (eastValid&&
//       (adjacencyMatrix[iEast][jEast]==-1)){
//        eastUnvisited=true;
//    }
//    else {
//        eastUnvisited=false;
//    }
//
//    double lottery = Math.random();
//
//
//
//    boolean canVisitNorth=northUnvisited&&northValid;
//    boolean canVisitSouth=southUnvisited&&southValid;
//    boolean canVisitEast=eastUnvisited&&eastValid;
//    boolean canVisitWest=westUnvisited&&westValid;
//
//    if (lottery>0.75D)
//    {
//
//        if(canVisitNorth)
//            DFS(iNorth, jNorth);
//
//        else if(canVisitSouth)
//            DFS(iSouth, jSouth);
//
//        else if(canVisitEast)
//            DFS(iEast, jEast);
//
//        else if(canVisitWest)
//            DFS(iWest, jWest);
//
//     }
//
//     else if(lottery < 0.25D)
//     {
//
//       if(canVisitSouth)
//            DFS(iSouth, jSouth);
//
//       else if(canVisitNorth)
//            DFS(iNorth, jNorth);
//
//        else if(canVisitEast)
//            DFS(iEast, jEast);
//
//        else if(canVisitWest)
//            DFS(iWest, jWest);
//
//
//     }
//
//      else if((lottery >= 0.25D)&&
//             (lottery<0.5D))
//     {
//        if(canVisitEast)
//          DFS(iEast, jEast);
//
//         else if(canVisitSouth)
//            DFS(iSouth, jSouth);
//
//        else if(canVisitNorth)
//            DFS(iNorth, jNorth);
//
//        else if(canVisitWest)
//            DFS(iWest, jWest);
//
//
//     }
//
//    else if((lottery >= 0.5D)&&
//             (lottery<0.75D))
//     {
//
//        if(canVisitWest)
//            DFS(iWest, jWest);
//
//        else if(canVisitEast)
//          DFS(iEast, jEast);
//
//         else if(canVisitSouth)
//            DFS(iSouth, jSouth);
//
//        else if(canVisitNorth)
//            DFS(iNorth, jNorth);
//
//
//     }





} //end DFS

//
}


public class Main {

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        // TODO code application logic here



    Graph theGraph = new Graph(3,3);
    theGraph.DFS(0,0);



    }

}

this code is giving me output like:

Visit i,j: 0 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
Visit i,j: 1 0
Visit i,j: 2 0

even though I'm validating the position of the next move (via the booleans southValid, eastValid, etc.)


回答1:


I have a suggestion to change your goWhere method, since all directions all directions are equally weighted when it comes to choosing which way to go.

String goWhere (boolean northValid, boolean southValid, boolean eastValid, boolean westValid){

    java.util.Random r = new java.util.Random();
    ArrayList<String> valids = new ArrayList<String>();
    if(northValid) { valids.add("north"); }
    if(southValid) { valids.add("south");}
    if(eastValid) { valids.add("east"); }
    if(westValid) { valids.add("west"); }

    if (valids.size() > 1) {
        int rand = r.nextInt(valids.size());
        return valids.get(rand);
    } else { return null; } 
}

I think you can get rid of the other direction finder methods. I think there are some bugs still in there where i or j is outside the matrix boundary, but I think this method change might remove some complications. See my note above about returning "south" in your "northOrEast" method.

Also, consider using constants for your directions. It will help prevent typos and the compiler will catch it.

public static final int NORTH = 0;
public static final int SOUTH = 1;
public static final int EAST = 2;
public static final int WEST = 3;

Then, instead of doing string comparisons, do:

if (Graph.EAST == where) { ... }

I think there is a problem setting your valid booleans. Instead of:

if (!(iNorth<0)) northValid=true;

Try:

northValid = (iNorth >= 0);

There's not necessarily a problem in the North case, but it's a little confusing testing for false if something is less than something else.

When you're comparing to M or N, you are using > to indicate it being invalid. I think South, for example if invalid if it's >= M. Or just do:

southValid = (iSouth < M);



回答2:


Add this method

private boolean boundariesOK(int i, int j) {
    return i >= 0 && j >= 0 && i < this.M && j < this.N;
}

And change decision to

if (boundariesOK(i,j) && adjacencyMatrix[i][j] == -1) { // if the vertex is unvisited

Your code is trying to visit an invalid position at the Matrix (no pun intended =)).

That's a first hack. Now figure the DFS part, where your code should be able to find all positions in the grid, which it currently does not.



来源:https://stackoverflow.com/questions/5825185/java-trouble-randomizing-a-dfs-run-to-build-a-maze

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!