二维平面分支中的随机路径生成-Java

二维平面分支中的随机路径生成-Java,java,arrays,random,Java,Arrays,Random,我正在制作一个随机棋盘游戏,其中路径是动态生成的。我使用的数据结构是一个2D数组,其中定义了“开始”,并随机查找下一个可用路径(上、右、下、左)。它使用一个加权随机系统,在这个系统中,它有一个沿着最后一个方向笔直前进的“趋势”。“finish”被阻止后,或完成一定数量的行走后,它停止生成 我会使用“迷宫生成算法”,但我认为它不适用于我的情况,因为我的目的不是制作迷宫,而是遍历路径 我的问题是,如何“分支”到新的轨道,生成新的路径,并在块之间留有间距 例如,我的跑步记录如下: 这一个很理想:

我正在制作一个随机棋盘游戏,其中路径是动态生成的。我使用的数据结构是一个2D数组,其中定义了“开始”,并随机查找下一个可用路径(上、右、下、左)。它使用一个加权随机系统,在这个系统中,它有一个沿着最后一个方向笔直前进的“趋势”。“finish”被阻止后,或完成一定数量的行走后,它停止生成

我会使用“迷宫生成算法”,但我认为它不适用于我的情况,因为我的目的不是制作迷宫,而是遍历路径

我的问题是,如何“分支”到新的轨道,生成新的路径,并在块之间留有间距

例如,我的跑步记录如下:

这一个很理想:

我还希望它能够随机地分支到新的路径。什么样的数据结构是可能的?我觉得2D阵列的功能在生成这一点上并不是很强大。任何帮助都会很好

此代码用于查找下一条路径。Tuple是一个包含用于定位的行和列的类

private void nextPath(){
    // up, right, down, left
    boolean availableNext [] = new boolean[] { false, false, false, false};

    //up
    if(isEmpty(new Tuple(this.lastPath.getRow() - 1, this.lastPath.getCol()))){
        availableNext[0] = true;
        //System.out.println("This ran");
    }

    //right
    if(isEmpty(new Tuple(this.lastPath.getRow(), this.lastPath.getCol() + 1))){
        availableNext[1] = true;
    }

    //down
    if(isEmpty(new Tuple(this.lastPath.getRow() + 1, this.lastPath.getCol()))){
        availableNext[2] = true;
    }

    //left
    if(isEmpty(new Tuple(this.lastPath.getRow(), this.lastPath.getCol() - 1))){
        availableNext[3] = true;
    }

    int numTrue = 0;
    for(int i=0; i<availableNext.length; i++){
        if(availableNext[i] == true){

            numTrue ++;
        }
        //System.out.println(availableNext[i]);
    }//end numTrueTest

    if(numTrue == 0 || order == this.terminateNumber){
        building = false;
        this.im[lastPath.getRow()][lastPath.getCol()] = "Finish";
    } else {

        boolean chosenC = false;
        while(!chosenC) {


            int tempWeightedArr [] = new int[100];
            int counter = 0;
            for(int i=0; i<this.weightedDir.length; i++){
                  for(int j=0; j<this.weightedDir[i]; j++){
                      tempWeightedArr[counter] = i;
                      counter++;
                  }
            }//end for

            //int rnd = new Random().nextInt(availableNext.length);
            int rnda = new Random().nextInt(tempWeightedArr.length);
            int rnd = tempWeightedArr[rnda];


            if(availableNext[rnd]){
                chosenC = true;
                //rnd = 0,1,2,3
                if(rnd == 0){
                    this.im[this.lastPath.getRow() - 1][this.lastPath.getCol()] = Integer.toString(order);
                    this.lastPath = new Tuple(this.lastPath.getRow()-1, this.lastPath.getCol());

                }
                if(rnd == 1){
                    this.im[this.lastPath.getRow()][this.lastPath.getCol()+1] =  Integer.toString(order);
                    this.lastPath = new Tuple(this.lastPath.getRow(), this.lastPath.getCol()+1);

                }
                if(rnd == 2){
                    this.im[this.lastPath.getRow() + 1][this.lastPath.getCol()] =  Integer.toString(order);
                    this.lastPath = new Tuple(this.lastPath.getRow()+1, this.lastPath.getCol());

                }
                if(rnd == 3){
                    this.im[this.lastPath.getRow()][this.lastPath.getCol()-1] =  Integer.toString(order);
                    this.lastPath = new Tuple(this.lastPath.getRow(), this.lastPath.getCol()-1);
                }
                for(int i=0; i<4; i++){
                    this.weightedDir[i] = 15;
                }
                this.weightedDir[rnd] = 55;
                this.lastDir = rnd;
                order++;
            }//end if
        }//end while
    }//end else


}
private void nextPath(){
//上、右、下、左
布尔值availableNext[]=新布尔值[]{false,false,false,false};
//向上
if(isEmpty(新元组(this.lastPath.getRow()-1,this.lastPath.getCol())){
availableNext[0]=真;
//System.out.println(“本次运行”);
}
//对
if(isEmpty(新元组(this.lastPath.getRow(),this.lastPath.getCol()+1))){
availableNext[1]=真;
}
//向下
if(isEmpty(新元组(this.lastPath.getRow()+1,this.lastPath.getCol())){
availableNext[2]=真;
}
//左
if(isEmpty(新元组(this.lastPath.getRow(),this.lastPath.getCol()-1))){
availableNext[3]=真;
}
int numTrue=0;

对于(int i=0;i使用递归求解,构建一个启发式函数测试下一个位置

package testingforan;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class NewInnerMap {

public static final int MAX_ROWS = 20;
public static final int MIN_ROWS = 19;
public static final int MAX_COLS = 21;
public static final int MIN_COLS = 18;

public static final int MAX_LENGTH = 30;


private String [][] im;
private int numRow;
private int numCol;

private Tuple startingPosition;

public NewInnerMap(){
    this.init();
}




    private void init(){

        this.numRow = randomBetween(NewInnerMap.MIN_ROWS, NewInnerMap.MAX_ROWS);
        this.numCol = randomBetween(NewInnerMap.MIN_COLS, NewInnerMap.MAX_COLS);
        this.im = new String[numRow][numCol];

        this.startingPosition = this.getRandomStartingPosition();

        this.generateMap();
    }//end init


    private void generateMap(){
         this.setStringToMap("Start", startingPosition);
         this.nextPath(startingPosition, -1, 0);
    }

    private int [] getHeuristics(Tuple pos, int lastDirection){

        //top, right, bottom, left
         int [] heuristic = new int[] {0,0,0,0};

         Tuple top = new Tuple(pos.getRow() - 1, pos.getCol());
         Tuple right = new Tuple(pos.getRow(), pos.getCol()+ 1);
         Tuple bottom = new Tuple(pos.getRow() + 1, pos.getCol());
         Tuple left = new Tuple(pos.getRow(), pos.getCol() - 1);


         //top
         if(pos.getRow() - 1 >= 0){
         heuristic[0] += this.getHeuristicForPositionBasedOnNumSurroundings(top);
         //heuristic for going straight is given a random chance
         if(lastDirection == 0){
             heuristic[0] += randomBetween(0,3);
         }//end if
         }


         if(pos.getCol()+1 < im[0].length){
         //right
         heuristic[1] += this.getHeuristicForPositionBasedOnNumSurroundings(right);
         if(lastDirection == 1){
             heuristic[1] += randomBetween(0,3);
         }
         }


         if(pos.getRow()+1 < im.length){
         //bottom
         heuristic[2] += this.getHeuristicForPositionBasedOnNumSurroundings(bottom);
         //heuristic for going straight is given a random chance
         if(lastDirection == 2){
             heuristic[2] += randomBetween(0,3);
         }//end if
         }


         if(pos.getCol() - 1 >= 0){
         //left
         heuristic[3] += this.getHeuristicForPositionBasedOnNumSurroundings(left);
         //heuristic for going straight is given a random chance
         if(lastDirection == 3){
             heuristic[3] += randomBetween(0,3);
         }//end if

         }
         return heuristic;
    }//emnd getHeuristics



    /*
        exists piece -> -1
        no empty surrounding -> -1
        1 empty surrounding -> -1
        2 empty surrounding -> -1
        3 empty surrounding -> 10
    */
    private int getHeuristicForPositionBasedOnNumSurroundings(Tuple pos){
        if(this.im[pos.getRow()][pos.getCol()] != null ||
                this.numEmptySurrounding(pos) == 1 ||
                this.numEmptySurrounding(pos) == 2 ){
            return -100;
        } else {

            return 15;
            //return this.numEmptySurrounding(pos);
        }
    }//end getHeuristicForPositionBasedOnNumSurroundings


    /*
            startPath -> find next possible moves
            next possible moves -> store in array, give them a weight

            should not border other than previous = max weight
            going straight = weighted

            if -> this path is 3 empty, possibly branch
    */
    public void nextPath(Tuple lastPos, int dir, int depth){

        int [] fh = this.getHeuristics(lastPos, dir);
        int max = maxFromIntArray(fh);

        if(fh[max] <= 5 || depth >= NewInnerMap.MAX_LENGTH){
            im[lastPos.getRow()][lastPos.getCol()] = "Finish";
        }//end if

        else if(im[lastPos.getRow()][lastPos.getCol()] != null){
            if(im[lastPos.getRow()][lastPos.getCol()].equals("Start")){
            this.nextPath(this.getNextPositionBasedOnDirection(lastPos, max), max, depth+1);
            }
        }//end else if

        else{
            im[lastPos.getRow()][lastPos.getCol()] = Integer.toString(depth);
            this.nextPath(this.getNextPositionBasedOnDirection(lastPos, max), max, depth+1);
        }//end else

    }//end



    /*

            HEURISTIC BUILDERS ------------------

    */

    private boolean [] nextEmpty(Tuple pos){
        boolean [] availableNext = new boolean[]{false, false, false, false};

        //up
        if(isEmpty(new Tuple(pos.getRow() - 1, pos.getCol()))){
            availableNext[0] = true;
        }

        //right
        if(isEmpty(new Tuple(pos.getRow(), pos.getCol() + 1))){
             availableNext[1] = true;
        }

        //down
        if(isEmpty(new Tuple(pos.getRow() + 1, pos.getCol()))){
             availableNext[2] = true;
        }

        //left
        if(isEmpty(new Tuple(pos.getRow(), pos.getCol() - 1))){
              availableNext[3] = true;
        }

        return availableNext;
    }//end numSurrounding

    private int numEmptySurrounding(Tuple pos){
        boolean [] avaN = this.nextEmpty(pos);
        int emptySurrounding = 0;

   /*    if(pos.getRow() == 0 
               || pos.getRow() == im.length - 1
               ){
            emptySurrounding ++;
        } 

        if(pos.getCol() == 0 
                || pos.getCol() == im[0].length - 1
                ){
            emptySurrounding++;
        }
        */

        for(int i=0; i<avaN.length; i++){
            if(avaN[i] == true) { emptySurrounding++; }
        }//end for
        return emptySurrounding;
    }//end numEmptySurrounding


    private boolean isEmpty(Tuple testPos){
        if(testPos.getRow() >= 0 && testPos.getCol() >= 0 && testPos.getRow() < this.im.length && testPos.getCol() < this.im[0].length) {
            if (this.im[testPos.getRow()][testPos.getCol()] == null) {
                return true;
            }
        }//end if
        return false;
    }//end isEmpty

    private Tuple getNextPositionBasedOnDirection(Tuple pos, int dir){

        if(dir == 0){
            return new Tuple(pos.getRow() - 1, pos.getCol());
        }

        else if(dir == 1){
            return new Tuple(pos.getRow(), pos.getCol() + 1);
        }

        else if(dir == 2){
            return new Tuple(pos.getRow() + 1, pos.getCol());
        }

        else if (dir == 3){
            return new Tuple(pos.getRow(), pos.getCol() -1);
        }

        return new Tuple(-1,-1);
    }


    /*

        UTILITY CLASSES ----------------------------

    */

    private void setStringToMap(String s, Tuple pos){
        this.im[pos.getRow()][pos.getCol()] = s;
    }

    private void setIntToMap(int i, Tuple pos){
        this.setStringToMap(Integer.toString(i), pos);
    }

    private static int randomBetween(int min, int max){
        Random r = new Random();
        return r.nextInt((max-min)+1) + min;
    }//end randomBetween

    private Tuple getRandomStartingPosition(){
        return new Tuple(randomBetween(0,im.length-1), randomBetween(0,im[0].length-1));
    }//end getRandomStartingPosition

    private Tuple getRandomStartingPosition(Tuple min, Tuple max){
        return new Tuple(randomBetween(min.getRow(),max.getRow()), randomBetween(min.getCol(), max.getCol()));
    }//end getRandomStartingPosition

    private static int maxFromIntArray(int [] arr){
        List <Integer> numMax = new ArrayList<>();
        int max = 0;
        numMax.add(max);
        for(int i=1; i<arr.length; i++){
            if(arr[i] > arr[max]){
                numMax.removeAll(numMax);
                max = i;
                numMax.add(i);
            } else if(arr[i] == arr[max]){
                numMax.add(i);
            }
        }
        return numMax.get(randomBetween(0,numMax.size()-1));
    }//end maxFromIntArray

    public String [][] getIm(){
        return this.im;
    }

}//end class
package-testingforan;
导入java.util.ArrayList;
导入java.util.array;
导入java.util.Collections;
导入java.util.List;
导入java.util.Random;
公共类NewInnerMap{
公共静态最终整数最大行数=20;
公共静态最终整数最小行数=19;
公共静态最终整数最大值=21;
公共静态最终整数最小值=18;
公共静态最终整数最大长度=30;
私有字符串[][]im;
私人国际机场;
私有国际货币基金组织;
私有元组起始位置;
公共NewInnerMap(){
this.init();
}
私有void init(){
this.numRow=randomBetween(NewInnerMap.MIN\u行,NewInnerMap.MAX\u行);
this.numCol=randomBetween(NewInnerMap.MIN\u COLS,NewInnerMap.MAX\u COLS);
this.im=新字符串[numRow][numCol];
this.startingPosition=this.getRandomStartingPosition();
这个.generateMap();
}//结束初始化
私有void generateMap(){
此设置字符串映射(“启动”,启动位置);
此.nextPath(起始位置,-1,0);
}
私有int[]getHeuristics(元组位置,int lastDirection){
//上、右、下、左
int[]启发式=新的int[]{0,0,0};
Tuple top=新的Tuple(位置getRow()-1,位置getCol());
元组右=新元组(位置getRow(),位置getCol()+1);
Tuple bottom=新的Tuple(位置getRow()+1,位置getCol());
Tuple left=新元组(pos.getRow(),pos.getCol()-1);
//顶
如果(位置getRow()-1>=0){
启发式[0]+=this.GetHeuristicForPositionBasedOnNumEnvironment(顶部);
//给出了一个随机的机会来进行直线运动
如果(lastDirection==0){
启发式[0]+=介于(0,3)之间的随机数;
}//如果结束
}
if(位置getCol()+1=0){
//左
启发式[3]+=this.GetHeuristicForPositionBasedOnNumEnvironment(左);
//给出了一个随机的机会来进行直线运动
如果(lastDirection==3){
启发式[3]+=介于(0,3)之间的随机数;
}//如果结束
}
返回启发式;
}//emnd启发式
/*
存在件->-1
无空周围->-1
1空周围->-1
2空周围->-1
3空周围->10
*/
私有int GetHeuristicForPositionBasedOnNumEnvironment(元组位置){
如果(this.im[pos.getRow()][pos.getCol()]!=null||
此.numEmptySurrounding(pos)==1||
此.numEmptySurrounding(pos)==2){
返回-100;
}否则{
返回15;
//返回此.numpTysUrounding(pos);
}
}//end GetHeuristicForPositionBasedOnNumEnvironment
/*
开始路径->查找下一步可能的移动
下一步可能的移动->存储在阵列中,给它们一个权重
不应为上一个=最大重量以外的边框
直行=加权
如果->此路径为3空,则可能为分支
*/
public void nextPath(元组lastPos、int dir、int depth){
int[]fh=this.getHeuristics(lastPos,dir);
int max=最大FROMINTARRAY(fh);
if(fh[max]=NewInnerMap.max\u长度){
im[lastPos.getRow()][lastPos.getCol()]=“完成”;
}//如果结束
else if(im[lastPos.getRow()][lastPos.getCol()]!=null){
如果(im[lastPos.getRow()][lastPos.getCol()].equals(“Start”)){
this.nextPath(this.getNextPositionBased