Skip to content
Snippets Groups Projects
Select Git revision
  • 244f61898215b85e6a58d1d2ef8f1f8fa9ff34b9
  • main default protected
  • correction_video
  • going_further
  • ImprovedMouseInteraction
  • final2023
  • template
  • ModifGUI
8 results

CellState.java

Blame
  • Forked from NAVES Guyslain / Game of life Template
    Source project has a limited visibility.
    Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    EntitySpawner.java 10.45 KiB
    package model;
    
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.List;
    import java.util.Map;
    import java.util.Random;
    import java.util.Set;
    
    import util.Direction;
    import util.Position;
    import util.PositionUtil;
    
    public class EntitySpawner {
        private final Board<Square> board;
        private final Random random = new Random();
    
        public EntitySpawner(Board<Square> board) {
            this.board = board;
        }
    
        public void spawnEntities(Map<EntityFactory, Integer> entityCounts) {
            Map<EntityFactory, Integer> counts = new HashMap<>();
            for (EntityFactory factory : entityCounts.keySet()) {
                counts.put(factory, 0);
            }
    
            int totalEntitiesToPlace = entityCounts.values().stream().mapToInt(Integer::intValue).sum();
            int totalEntitiesPlaced = 0;
    
            int chance = 5;
            List<Position> positions = generateAllPositions();
    
            while (totalEntitiesPlaced < totalEntitiesToPlace) {
                Collections.shuffle(positions);
    
                for (Position pos : positions) {
                    if (board.getStates(pos).isEmpty()) {
                        for (EntityFactory factory : entityCounts.keySet()) {
                            int desiredCount = entityCounts.get(factory);
                            int currentCount = counts.get(factory);
    
                            if (currentCount < desiredCount && random.nextInt(100) < chance) {
                                Entity entity = factory.create(pos, board);
                                board.setSquare(new Square(pos, entity));
                                counts.put(factory, currentCount + 1);
                                totalEntitiesPlaced++;
    
                                if (totalEntitiesPlaced == totalEntitiesToPlace) {
                                    return;
                                }
    
                                break; // Move to the next position
                            }
                        }
                    }
                }
    
                // Increase chance after each full traversal
                chance = Math.min(chance + 5, 100);
            }
        }
    
        private List<Position> generateAllPositions() {
            List<Position> positions = new ArrayList<>();
            for (int x = 0; x < board.rowCount(); x++) {
                for (int y = 0; y < board.columnCount(); y++) {
                    positions.add(new Position(x, y));
                }
            }
            return positions;
        }
    
        public static void generateEntitiesInLine(Board<Square> board, Position anchor, EntityFactory entityFactory) {
            int xIncrement = 0;
            int yIncrement = 0;
        
            // Determine increments based on which coordinate is zero
            if (anchor.x() == 0 && anchor.y() >= 0) {
                // Starting from the left edge (x == 0), increment x to move right
                xIncrement = 1;
            } else if (anchor.y() == 0 && anchor.x() >= 0) {
                // Starting from the top edge (y == 0), increment y to move down
                yIncrement = 1;
            } else {
                // If neither x nor y is 0, cannot determine direction
                throw new IllegalArgumentException("Anchor position must have x or y equal to 0");
            }
        
            int x = anchor.x();
            int y = anchor.y();
        
            // Continue until we reach the edge of the board
            while (board.doesPositionExist(new Position(x, y))) {
                Position pos = new Position(x, y);
                // Create a new entity for each position
                Entity entity = entityFactory.create(pos, board);
                entity.setPosition(pos); // Set the position if not already set in the factory
                board.addEntityAtSquare(entity, pos);
        
                x += xIncrement;
                y += yIncrement;
            }
        }
        
        public static List<Position> generateEntitiesInRandomLine(Board<Square> board, Position anchor, int maxStepsInDirection, int minimumRoadLength) {
            Random random = new Random();
            List<Position> path = new ArrayList<>();
            int x = anchor.x();
            int y = anchor.y();
        
            // Toutes les directions possibles
            List<Direction> allDirections = Arrays.asList(Direction.NORTH, Direction.SOUTH, Direction.EAST, Direction.WEST);
        
            // Choisir une direction initiale aléatoire
            Direction initialDirection = allDirections.get(random.nextInt(allDirections.size()));
            path.add(new Position(x, y)); // Ajouter la position de l'ancre au chemin
            int roadLength = 1;
        
            // Déterminer la direction interdite (opposée à la direction initiale)
            Direction forbiddenDirection = PositionUtil.getOppositeDirection(initialDirection);
        
            // Initialiser la direction courante
            Direction currentDirection = initialDirection;
            int stepsInCurrentDirection = 0;
        
            // Ensemble des directions définitivement exclues (direction initiale)
            Set<Direction> permanentlyExcludedDirections = new HashSet<>();
            permanentlyExcludedDirections.add(initialDirection);
        
            // Ensemble des directions temporairement exclues (initialement vide)
            Set<Direction> temporarilyExcludedDirections = new HashSet<>();
        
            while (true) {
                // Calculer la prochaine position dans la direction courante
                int nextX = x + getXIncrement(currentDirection);
                int nextY = y + getYIncrement(currentDirection);
                Position nextPos = new Position(nextX, nextY);
        
                if (board.doesPositionExist(nextPos)) {
                    // Ajouter la position au chemin
                    path.add(nextPos);
                    x = nextX;
                    y = nextY;
                    roadLength++;
                    stepsInCurrentDirection++;
                } else {
                    // La position dans la direction courante est invalide
                    if (roadLength < minimumRoadLength) {
                        // Exclure temporairement la direction courante
                        temporarilyExcludedDirections.add(currentDirection);
        
                        // Choisir une nouvelle direction valide
                        Direction newDirection = chooseNewDirection(allDirections, currentDirection, forbiddenDirection, 
                                permanentlyExcludedDirections, temporarilyExcludedDirections, board, x, y, random);
        
                        if (newDirection == null) {
                            // Aucune direction valide disponible pour atteindre la longueur minimale
                            break;
                        }
        
                        // Mettre à jour la direction courante
                        currentDirection = newDirection;
                        forbiddenDirection = PositionUtil.getOppositeDirection(currentDirection);
                        stepsInCurrentDirection = 0;
                        continue; // Recommencer avec la nouvelle direction
                    } else {
                        // La longueur minimale est atteinte, arrêter la génération
                        break;
                    }
                }
        
                // Vérifier s'il est temps de changer de direction
                if (stepsInCurrentDirection >= maxStepsInDirection) {
                    // Choisir une nouvelle direction
                    Direction newDirection = chooseNewDirection(allDirections, currentDirection, forbiddenDirection, 
                            permanentlyExcludedDirections, temporarilyExcludedDirections, board, x, y, random);
        
                    if (newDirection == null) {
                        // Aucune direction valide disponible
                        break;
                    }
        
                    // Mettre à jour la direction courante
                    currentDirection = newDirection;
                    forbiddenDirection = PositionUtil.getOppositeDirection(currentDirection);
                    stepsInCurrentDirection = 0;
                }
            }
        
            return path;  // Retourner la liste des positions formant le serpent
        }
        
        /**
         * Choisit une nouvelle direction valide en tenant compte des exclusions permanentes et temporaires.
         *
         * @param allDirections Toutes les directions possibles.
         * @param currentDirection La direction actuelle.
         * @param forbiddenDirection La direction opposée à la direction actuelle (interdite).
         * @param permanentlyExcludedDirections Les directions définitivement exclues.
         * @param temporarilyExcludedDirections Les directions temporairement exclues.
         * @param board Le plateau de jeu.
         * @param x La coordonnée X actuelle.
         * @param y La coordonnée Y actuelle.
         * @param random Une instance de Random pour le choix aléatoire.
         * @return La nouvelle direction choisie ou null si aucune direction valide n'est disponible.
         */
        private static Direction chooseNewDirection(List<Direction> allDirections, Direction currentDirection, Direction forbiddenDirection,
                                                   Set<Direction> permanentlyExcludedDirections, Set<Direction> temporarilyExcludedDirections,
                                                   Board<Square> board, int x, int y, Random random) {
            // Créer une liste de directions valides en excluant :
            // - La direction actuelle
            // - La direction interdite (opposée à la direction actuelle)
            // - Les directions définitivement exclues
            // - Les directions temporairement exclues
            List<Direction> validDirections = new ArrayList<>(allDirections);
            validDirections.remove(currentDirection);
            validDirections.remove(forbiddenDirection);
            validDirections.removeAll(permanentlyExcludedDirections);
            validDirections.removeAll(temporarilyExcludedDirections);
        
            // Filtrer les directions qui permettent de continuer le chemin
            validDirections.removeIf(dir -> !board.doesPositionExist(new Position(x + getXIncrement(dir), y + getYIncrement(dir))));
        
            if (validDirections.isEmpty()) {
                // Aucune direction valide disponible
                return null;
            }
        
            // Choisir une nouvelle direction aléatoirement
            return validDirections.get(random.nextInt(validDirections.size()));
        }
        
        private static int getXIncrement(Direction direction) {
            switch (direction) {
                case NORTH: return -1;
                case SOUTH: return 1;
                default:    return 0;
            }
        }
        
        private static int getYIncrement(Direction direction) {
            switch (direction) {
                case EAST:  return 1;
                case WEST:  return -1;
                default:    return 0;
            }
        }
        
    
        
        
        
    
        
        
    
        
    }