MapGenerator (#34)
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/pr Build is passing

This generate maps following a simple structure

First we choose map size depending on the difficulty

we grind the edge with a random pattern so the map is not just a square

we pick a random open piece and try to make a piece out of it between a size of 1 to 3

and we do this in a loop until all open spaces are filled

this is not the best but it's efficient

known problem:

- We can have sometime a lot of small pieces
- We can have weird shape, for instance pieces that are only connected by corner

I think this is technically not a problem in the end. but this could be changed

Co-authored-by: Debucquoy <debucqquoy.anthony@gmail.com>
Reviewed-on: #34
Reviewed-by: Mat_02 <diletomatteo@gmail.com>
This commit is contained in:
Debucquoy Anthony 2023-05-01 18:38:52 +02:00
parent 692e22b5b9
commit c6df656381
2 changed files with 104 additions and 0 deletions

View File

@ -0,0 +1,78 @@
package school_project;
import school_project.Utils.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Random;
public class MapGenerator {
private static final Random rand = new Random();
public enum Difficulty {
Easy,
Medium,
Difficult,
}
public static Map generate(Difficulty difficulty){
Vec2 map_size;
int depth = 1; // how much the map shape generator could grind
// define map size depending on the difficulty
switch (difficulty){
case Easy -> map_size = new Vec2(rand.nextInt(3, 5), rand.nextInt(3, 5));
case Medium -> map_size = new Vec2(rand.nextInt(5, 8), rand.nextInt(5, 8));
case Difficult -> {
map_size = new Vec2(rand.nextInt(8, 10), rand.nextInt(8, 10));
depth = 2;
}
default -> map_size = new Vec2();
}
// Cut edges
boolean[][] map_shape = new boolean[map_size.x][map_size.y];
for (boolean[] b : map_shape) {
Arrays.fill(b, true);
}
for (int i = 0; i < map_shape.length; i++) {
for (int j = 0; j < map_shape[0].length; j++) {
if(i > depth - 1 && i < map_shape.length - depth && j > depth - 1 && j < map_shape[0].length - depth){
j = map_shape[0].length - depth;
}
map_shape[i][j] = rand.nextBoolean();
}
}
Map ret = new Map(map_shape);
boolean[][] piece_layout = Array.MatrixCopyOf(map_shape);
ArrayList<Vec2> EmptySlots = new ArrayList<>();
for (int i = 0; i < piece_layout.length; i++) {
for (int j = 0; j < piece_layout[i].length; j++) {
if(piece_layout[i][j]){
EmptySlots.add(new Vec2(i, j));
}
}
}
while (EmptySlots.size() > 0){
Collections.shuffle(EmptySlots);
Vec2 selected = EmptySlots.get(0);
int size = rand.nextInt(1, 4);
boolean[][] shape = new boolean[size][size];
for(int i = 0; i < size; i++){
for (int j = 0; j < size; j++) {
Vec2 checked = new Vec2(i, j).add(selected);
if(EmptySlots.contains(checked)){
EmptySlots.remove(checked);
piece_layout[checked.x][checked.y] = false;
shape[i][j] = true;
}
}
}
ret.addPiece(new Piece(shape));
}
//generate pieces
return ret;
}
}

View File

@ -0,0 +1,26 @@
package school_project;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class MapGeneratorTest {
@Test
void generate() {
Map[] maps = new Map[] {
MapGenerator.generate(MapGenerator.Difficulty.Easy),
MapGenerator.generate(MapGenerator.Difficulty.Medium),
MapGenerator.generate(MapGenerator.Difficulty.Difficult),
};
for(Map m: maps){
System.out.println("==========");
System.out.println(m);
System.out.println("++++++++++++++++++++");
for (Piece p: m.getPieces()){
System.out.println(p);
}
}
}
}