From da3a5d5948f0f5bb5b8295f7bfaedf83a39e4066 Mon Sep 17 00:00:00 2001 From: paull Date: Mon, 27 May 2024 15:57:23 +0200 Subject: [PATCH] Task 1 should work --- src/backend/Simulator.java | 557 +++++++++++++++++-------------------- 1 file changed, 248 insertions(+), 309 deletions(-) diff --git a/src/backend/Simulator.java b/src/backend/Simulator.java index 9774cd3..0d53aec 100644 --- a/src/backend/Simulator.java +++ b/src/backend/Simulator.java @@ -1,332 +1,271 @@ package backend; -import java.util.ArrayList; +import java.util.ArrayList; import windowInterface.MyInterface; public class Simulator extends Thread { - private MyInterface mjf; - - private final int COL_NUM = 100; - private final int LINE_NUM = 100; - private final int LIFE_TYPE_NUM = 4; - //Conway Radius : 1 - private final int LIFE_AREA_RADIUS = 1; - //Animal Neighborhood Radius : 5 - private final int ANIMAL_AREA_RADIUS = 2; - private ArrayList fieldSurviveValues; - private ArrayList fieldBirthValues; - - private ArrayList agents; - - private boolean stopFlag; - private boolean pauseFlag; - private boolean loopingBorder; - private boolean clickActionFlag; - private int loopDelay = 150; + private MyInterface mjf; - //TODO : add missing attribute(s) + private final int COL_NUM = 100; + private final int LINE_NUM = 100; + private final int LIFE_TYPE_NUM = 4; + private final int LIFE_AREA_RADIUS = 1; + private final int ANIMAL_AREA_RADIUS = 2; + private ArrayList fieldSurviveValues; + private ArrayList fieldBirthValues; - public Simulator(MyInterface mjfParam) { - mjf = mjfParam; - stopFlag=false; - pauseFlag=false; - loopingBorder=false; - clickActionFlag=false; + private ArrayList agents; - agents = new ArrayList(); - fieldBirthValues = new ArrayList(); - fieldSurviveValues = new ArrayList(); + private boolean stopFlag; + private boolean pauseFlag; + private boolean loopingBorder; + private boolean clickActionFlag; + private int loopDelay = 150; - //TODO : add missing attribute initialization - - - - //Default rule : Survive always, birth never - for(int i =0; i<9; i++) { - fieldSurviveValues.add(i); - } - - } + private int[][] grid; - public int getWidth() { - //TODO : replace with proper return - return 0; - } + public Simulator(MyInterface mjfParam) { + mjf = mjfParam; + stopFlag = false; + pauseFlag = false; + loopingBorder = false; + clickActionFlag = false; - public int getHeight() { - //TODO : replace with proper return - return 0; - } + agents = new ArrayList(); + fieldBirthValues = new ArrayList(); + fieldSurviveValues = new ArrayList(); - //Should probably stay as is - public void run() { - int stepCount=0; - while(!stopFlag) { - stepCount++; - makeStep(); - mjf.update(stepCount); - try { - Thread.sleep(loopDelay); - } catch (InterruptedException e) { - e.printStackTrace(); - } - while(pauseFlag && !stopFlag) { - try { - Thread.sleep(loopDelay); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - } + grid = new int[LINE_NUM][COL_NUM]; - } + // Default rule : Survive always, birth never + for (int i = 0; i < 9; i++) { + fieldSurviveValues.add(i); + } + } - /** - * method called at each step of the simulation - * makes all the actions to go from one step to the other - */ - public void makeStep() { - // agent behaviors first - // only modify if sure of what you do - // to modify agent behavior, see liveTurn method - // in agent classes - for(Agent agent : agents) { - ArrayList neighbors = - this.getNeighboringAnimals( - agent.getX(), - agent.getY(), - ANIMAL_AREA_RADIUS); - if(!agent.liveTurn( - neighbors, - this)) { - agents.remove(agent); - } - } - //then evolution of the field - // TODO : apply game rule to all cells of the field - - /* you should distribute this action in methods/classes - * don't write everything here ! - * - * the idea is first to get the surrounding values - * then count how many are alive - * then check if that number is in the lists of rules - * if the cell is alive - * and the count is in the survive list, - * then the cell stays alive - * if the cell is not alive - * and the count is in the birth list, - * then the cell becomes alive - */ - - - - - } - - /* - * leave this as is - */ - public void stopSimu() { - stopFlag=true; - } - - /* - * method called when clicking pause button - */ - public void togglePause() { - // TODO : actually toggle the corresponding flag - } - - /** - * method called when clicking on a cell in the interface - */ - public void clickCell(int x, int y) { - //TODO : complete method - } - - /** - * get cell value in simulated world - * @param x coordinate of cell - * @param y coordinate of cell - * @return value of cell - */ - public int getCell(int x, int y) { - //TODO : complete method with proper return - return 0; - } - /** - * - * @return list of Animals in simulated world - */ - public ArrayList getAnimals(){ - return agents; - } - /** - * selects Animals in a circular area of simulated world - * @param x center - * @param y center - * @param radius - * @return list of agents in area - */ - public ArrayList getNeighboringAnimals(int x, int y, int radius){ - ArrayList inArea = new ArrayList(); - for(int i=0;i getSaveState() { - //TODO : complete method with proper return - return null; - } - /** - * - * @param lines of file representing saved world state - */ - public void loadSaveState(ArrayList lines) { - /* - * First some checks that the file is usable - * We call early returns in conditions like this - * "Guard clauses", as they guard the method - * against unwanted inputs - */ - if(lines.size()<=0) { - return; - } - String firstLine = lines.get(0); - String[] firstLineElements = firstLine.split(";"); - if(firstLineElements.length<=0) { - return; - } - /* - * now we fill in the world - * with the content of the file - */ - for(int y =0; y getRule() { - //TODO : complete method with proper return - - return null; - } + public void makeStep() { + int[][] newGrid = new int[LINE_NUM][COL_NUM]; - public void loadRule(ArrayList lines) { - if(lines.size()<=0) { - System.out.println("empty rule file"); - return; - } - //TODO : remove previous rule (=emptying lists) - - - String surviveLine = lines.get(0); - String birthLine = lines.get(1); - String[] surviveElements = surviveLine.split(";"); - for(int x=0; x getAgentsSave() { - //TODO : Same idea as the other save method, but for agents - return null; - } + for (int y = 0; y < LINE_NUM; y++) { + for (int x = 0; x < COL_NUM; x++) { + int aliveNeighbors = countAliveNeighbors(x, y); - public void loadAgents(ArrayList stringArray) { - //TODO : Same idea as other load methods, but for agent list - - } + if (grid[y][x] == 1) { + if (aliveNeighbors < 2 || aliveNeighbors > 3) { + newGrid[y][x] = 0; + } else { + newGrid[y][x] = 1; + } + } else { + if (aliveNeighbors == 3) { + newGrid[y][x] = 1; + } else { + newGrid[y][x] = 0; + } + } + } + } - /** - * used by label in interface to show the active click action - * @return String representation of click action - */ - public String clickActionName() { - // TODO : initially return "sheep" or "cell" - // depending on clickActionFlag - return ""; - } + grid = newGrid; + } + private int countAliveNeighbors(int x, int y) { + int aliveCount = 0; + int[] dx = {-1, -1, -1, 0, 0, 1, 1, 1}; + int[] dy = {-1, 0, 1, -1, 1, -1, 0, 1}; + + for (int i = 0; i < 8; i++) { + int nx = x + dx[i]; + int ny = y + dy[i]; + + if (loopingBorder) { + nx = (nx + COL_NUM) % COL_NUM; + ny = (ny + LINE_NUM) % LINE_NUM; + } + + if (nx >= 0 && nx < COL_NUM && ny >= 0 && ny < LINE_NUM) { + aliveCount += grid[ny][nx]; + } + } + + return aliveCount; + } + + public void togglePause() { + pauseFlag = !pauseFlag; + } + + public void clickCell(int x, int y) { + if (clickActionFlag) { + agents.add(new Sheep(x, y)); + } else { + int currentState = getCell(x, y); + setCell(x, y, currentState == 0 ? 1 : 0); + } + } + + public int getCell(int x, int y) { + if (x >= 0 && x < COL_NUM && y >= 0 && y < LINE_NUM) { + return grid[y][x]; + } + return 0; + } + + public void setCell(int x, int y, int val) { + if (x >= 0 && x < COL_NUM && y >= 0 && y < LINE_NUM) { + grid[y][x] = val; + } + } + + public void toggleLoopingBorder() { + loopingBorder = !loopingBorder; + } + + public boolean isLoopingBorder() { + return loopingBorder; + } + + public void setLoopDelay(int delay) { + loopDelay = delay; + } + + public void toggleClickAction() { + clickActionFlag = !clickActionFlag; + } + + public void generateRandom(float chanceOfLife) { + for (int y = 0; y < LINE_NUM; y++) { + for (int x = 0; x < COL_NUM; x++) { + grid[y][x] = Math.random() < chanceOfLife ? 1 : 0; + } + } + } + + public ArrayList getAnimals() { + return agents; + } + + public ArrayList getNeighboringAnimals(int x, int y, int radius) { + ArrayList inArea = new ArrayList(); + for (Agent agent : agents) { + if (agent.isInArea(x, y, radius)) { + inArea.add(agent); + } + } + return inArea; + } + + public ArrayList getSaveState() { + ArrayList saveState = new ArrayList(); + for (int y = 0; y < LINE_NUM; y++) { + StringBuilder sb = new StringBuilder(); + for (int x = 0; x < COL_NUM; x++) { + sb.append(grid[y][x]); + if (x < COL_NUM - 1) { + sb.append(";"); + } + } + saveState.add(sb.toString()); + } + return saveState; + } + + public void loadSaveState(ArrayList lines) { + if (lines.size() != LINE_NUM) { + return; + } + for (int y = 0; y < LINE_NUM; y++) { + String[] lineElements = lines.get(y).split(";"); + if (lineElements.length != COL_NUM) { + return; + } + for (int x = 0; x < COL_NUM; x++) { + grid[y][x] = Integer.parseInt(lineElements[x]); + } + } + } + + public ArrayList getRule() { + ArrayList rules = new ArrayList(); + StringBuilder surviveBuilder = new StringBuilder(); + StringBuilder birthBuilder = new StringBuilder(); + + for (int value : fieldSurviveValues) { + surviveBuilder.append(value).append(";"); + } + for (int value : fieldBirthValues) { + birthBuilder.append(value).append(";"); + } + + rules.add(surviveBuilder.toString()); + rules.add(birthBuilder.toString()); + return rules; + } + + public void loadRule(ArrayList lines) { + if (lines.size() < 2) { + System.out.println("empty rule file"); + return; + } + + fieldSurviveValues.clear(); + fieldBirthValues.clear(); + + String[] surviveElements = lines.get(0).split(";"); + for (String elem : surviveElements) { + if (!elem.isEmpty()) { + fieldSurviveValues.add(Integer.parseInt(elem)); + } + } + + String[] birthElements = lines.get(1).split(";"); + for (String elem : birthElements) { + if (!elem.isEmpty()) { + fieldBirthValues.add(Integer.parseInt(elem)); + } + } + } + + public ArrayList getAgentsSave() { + // TODO: Same idea as the other save method, but for agents + return null; + } + + public void loadAgents(ArrayList stringArray) { + // TODO: Same idea as other load methods, but for agent list + } + + public String clickActionName() { + return clickActionFlag ? "sheep" : "cell"; + } }