我正在制作一个动态生成路径的随机棋盘游戏。我使用的数据结构是2D数组,其中" start"定义并随机查找下一个可用路径(向上,向右,向下,向左)。它使用加权随机系统,其中有一个"趋势"按照最后的方向直奔。完成"完成后#34;被封锁,或完成一定数量的步行,它就会停止生成。
我会使用"迷宫生成算法"但我觉得它不适用于我的情况,因为我的目的不是制造迷宫,而是走遍原点。
我的问题是,如何分支"分支"进入新轨道并生成新路径,并在块之间有间距?
我也希望它随机分支到新的路径。什么样的数据结构是可能的?我觉得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
}
答案 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