If you haven't read my introduction post, please do: http://www.javaprogrammingforums.com...017-hello.html
tl;dr version: I'm a fairly new-ish hobbiest java programmer teaching himself how to code, please don't hold "bad" coding practices against me, I did the best I knew how with what the google had to offer. =) This is my first *true post* on the forums. Thanks!
I know there must be an easier way to do this, though I can't follow along with the examples I see on /the/ Google, so I attempted to write my own, and I have something now that works, albeit very shaky.
So here it is. I'm trying to write the World and Map generator for a game. There is as of yet no real game, and just an Island Generator, and its shaky at best. It likes to randomly go out of bounds.
My code consists of 6 classes in top down order:
Mapper.java <-Main class for the generator.
package com.kfgeeks.java.Mapper; import java.util.*; public class Mapper { static Scanner ReadUserInput = new Scanner(System.in); /** * @param args */ public static void main(String[] args) { //I know...Looks stupid, but we're gonna make sure java works first =P //(Besides....Saying "Hello" is always more interesting than "Initializing Java..." Right?) System.out.println("Hello Java!"); for (int i=0; i<10; i++){ System.out.println(i); } MapBuilder.run(40, 160); } }
MapBuilder.java <-This class is responsible for managing all of the other builders, and telling them when to run. So far only Island Builder is Implemented, and assembling the map based on their output.
package com.kfgeeks.java.Mapper; public class MapBuilder { public static void run(int x, int y){ Map worldMap = new Map(); worldMap = buildMap(x, y); worldMap = IslandBuilder.run(worldMap); printMap(worldMap); } private static Map buildMap(int x, int y) { Map worldMap = new Map(); worldMap.setHeight(x); worldMap.setWidth(y); worldMap.mapCells = new Cell[worldMap.getHeight()][]; for (int i = 0; i < worldMap.mapCells.length; i++) { worldMap.mapCells[i] = new Cell[worldMap.getWidth()]; for (int j = 0; j < worldMap.mapCells[i].length; j++) { worldMap.mapCells[i][j] = new Cell(); worldMap.mapCells[i][j].setTerrain(0); } } return worldMap; } // Just a clever little Print function(); @SuppressWarnings("unused") private void print(String s) { System.out.println(s); } private static void printMap(Map passWorld_Map) { Map worldMap = passWorld_Map; for (int i = 0; i < worldMap.mapCells.length; i++) { for (int j = 0; j < worldMap.mapCells[i].length; j++) { System.out.print(worldMap.mapCells[i][j].getTerrain_Char()); } System.out.print("\n"); } } }
IslandBuilder.java <-This class is responsible for building, as the name implies, the individual Islands on the map.
package com.kfgeeks.java.Mapper; import java.util.Random; public class IslandBuilder { public static Map run(Map passWorld_Map){ Map World_Map = passWorld_Map; buildIslands(World_Map); populateShores(World_Map); return World_Map; } private static Map buildIslands(Map passWorld_Map){ Map worldMap = passWorld_Map; Island newIsland = new Island(); Random generator = new Random(); int numOfIslands = 0; while (numOfIslands < 20){ newIsland.setMaxHeight(24); newIsland.setMinHeight(5); newIsland.setMaxWidth(24); newIsland.setMinWidth(5); newIsland.setHeight(generator.nextInt(newIsland.getMax_height() - newIsland.getMin_height()) + newIsland.getMin_height()); newIsland.setWidth(generator.nextInt(newIsland.getMax_width() - newIsland.getMin_width()) + newIsland.getMin_width()); System.out.print(newIsland.getHeight() + " -- "); System.out.print(newIsland.getWidth() + "\n"); newIsland.islandCells = new Cell[newIsland.getHeight()][]; for (int i = 0; i < newIsland.islandCells.length; i++){ newIsland.islandCells[i]=new Cell[generator.nextInt(newIsland.getMax_width())]; for (int j = 0; j < newIsland.islandCells[i].length; j++){ newIsland.islandCells[i][j] = new Cell(); newIsland.islandCells[i][j].setTerrain(3); } } int startCell_X = generator.nextInt(worldMap.getHeight()); int startCell_Y = generator.nextInt(worldMap.getWidth()); if ((startCell_X + newIsland.getHeight() < worldMap.getHeight() -1 ) && (startCell_Y + newIsland.getWidth() < worldMap.getWidth()-1)){ for (int i = 0; i < newIsland.islandCells.length; i++){ for (int j = 0; j < newIsland.islandCells[i].length; j++){ worldMap.mapCells[startCell_X + i ][startCell_Y + j].setTerrain(newIsland.islandCells[i][j].getTerrain()); } } } else{ continue; } numOfIslands++; } return worldMap; } private static Map populateShores(Map passWorld_Map) { Map WorldMap = passWorld_Map; for (int i = 1; i < WorldMap.mapCells.length - 1; i++) { for (int j = 1; j < WorldMap.mapCells[i].length -1; j++) { if (WorldMap.mapCells[i][j].getTerrain() == 3){ //check surrounding cells for water for (int ii = i - 1; ii <= i + 1; ii++){ for (int jj = j -1; jj <= j + 1; jj++){ if ((ii == i)&&(jj == j)){ continue; } else if (WorldMap.mapCells[ii][jj].getTerrain() == 0){ WorldMap.mapCells[i][j].setTerrain(1); } } } } } } return WorldMap; } }
Map.java <-This class describes what a Map is. Maps can be of any integral width & height and are composed of individual Cells, which are stored in a two dimensional array.
package com.kfgeeks.java.Mapper; public class Map { private int size = 0; private int height = 0; private int width = 0; Cell[][] mapCells; public void setHeight(int x){ height = x; } public void setWidth(int x){ width = x; } public int getWidth(){ return width; } public int getHeight(){ return height; } /*This Comment Intentionally Left Blank*/ } /*Just trying to tidy up the close Braces*/ /*You know...Make it look all Pretty*/ /*Before you get to........*/ /************The Very End!*/
Cell.java <-This class describes an individual Cell. Cells can be one of several terrain types and have several properties including passable, swimmable, buildable, value etc. The only implemented terrain types currently are Shore, Ocean, and Grassland.
package com.kfgeeks.java.Mapper; public class Cell { /***********************************************************************************************************/ private boolean passable = false; private boolean shipPass = false; private boolean buildible = false; private boolean visited = false; private int terrain_type; private String Terrain_Name; private char terrainChar; private float cellWeight=0; private String[] aTerrain_Name = {"Ocean", "Shore", "River", "Grassland", "Forest","Mineable Stone","Non-Mineable Stone"}; private char[] aTerrain_Char= {'~','!','r','"','f','S','s'}; private boolean[] aPassable = {false,true,false,true,true,false,false}; private boolean[] aShip_Pass ={true,false,false,false,false,false,false}; private boolean[] aBuildable={false, false, false, true, true, false, false}; /********************Getters and Setters**********************************************/ public float getCell_weight() { return cellWeight; } public int getTerrain(){ return terrain_type; } public char getTerrain_Char() { return terrainChar; } public String getTerrain_Name() { return Terrain_Name; } public boolean isBuildible() { return buildible; } public boolean isPassable() { return passable; } public boolean isShip_pass() { return shipPass; } public boolean isVisited() { return visited; } public void setBuildible(boolean buildible) { this.buildible = buildible; } public void setCell_weight(float cell_weight) { this.cellWeight = cell_weight; } public void setPassable(boolean passable) { this.passable = passable; } public void setShip_pass(boolean ship_pass) { this.shipPass = ship_pass; } /**Should be a number between 0 and 6 * @0 = Ocean = '~' * @1 = Shore = '$' * @2 = River = '=' * @3 = Grassland = '`' * @4 = Forest = '*' * @5 = Minable stone = '%' * @6 = Non-Minable stone = '^' */ public void setTerrain(int x){ terrain_type = x; setTerrain_Name(aTerrain_Name[terrain_type]); setTerrain_Char(aTerrain_Char[terrain_type]); setPassable(aPassable[terrain_type]); setShip_pass(aShip_Pass[terrain_type]); setBuildible(aBuildable[terrain_type]); } public void setTerrain_Char(char terrain_Char) { terrainChar = terrain_Char; } public void setTerrain_Name(String terrain_Name) { Terrain_Name = terrain_Name; } public void setVisited(boolean visited) { this.visited = visited; } }
Island.java <-This Class describes an Island. Islands are randomly sized at creation, and are surrounded by shoreline.
package com.kfgeeks.java.Mapper; public class Island { private int islandHeight = 0; private int islandWidth = 0; private int maxWidth = 0; private int maxHeight = 0; private int minHeight = 0; private int minWidth = 0; Cell[][] islandCells; public int getHeight(){ return islandHeight; } public int getWidth(){ return islandWidth; } public void setHeight(int x){ islandHeight = x; } public void setWidth(int x){ islandWidth = x; } public void setMaxWidth(int x){ maxWidth = x; } public void setMaxHeight(int x){ maxHeight = x; } public int getMax_height(){ return maxWidth; } public int getMax_width(){ return maxHeight; } public void setMinWidth(int x){ minWidth = x; } public void setMinHeight(int x){ minHeight = x; } public int getMin_height(){ return minWidth; } public int getMin_width(){ return minHeight; } }
A zipped file of my source will be included with this post, as well as the eclipse project data.
My question here is this, is there an easier/"better" way to code this that will make it a) more stable and b)more predictable, although still essentially random?
I've learned a lot to get as far as I have, however I still don't know enough to go further much further along these lines, so I would greatly appreciate somebody being able to take a quick peek at my code and see if it can be fixed or if it should just be scratched all together.
Mapper.rar
Thank you in advance.
Rooster