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

时间:2015-11-26 01:34:39

标签: java arrays random

我正在制作一个动态生成路径的随机棋盘游戏。我使用的数据结构是2D数组,其中" start"定义并随机查找下一个可用路径(向上,向右,向下,向左)。它使用加权随机系统,其中有一个"趋势"按照最后的方向直奔。完成"完成后#34;被封锁,或完成一定数量的步行,它就会停止生成。

我会使用"迷宫生成算法"但我觉得它不适用于我的情况,因为我的目的不是制造迷宫,而是走遍原点。

我的问题是,如何分支"分支"进入新轨道并生成新路径,并在块之间有间距?

例如,我的运行如下: enter image description here

enter image description here

这个是理想的: enter image description here

我也希望它随机分支到新的路径。什么样的数据结构是可能的?我觉得2D数组的功能并不是很好。任何帮助都会很棒。

此代码用于查找Next Path。元组是一个包含Row和Col的类,用于定位。

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


}

1 个答案:

答案 0 :(得分:0)

使用递归求解,构建测试下一个位置的启发式函数。

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