import java.util.Random; import java.util.Queue; import java.util.LinkedList; import java.util.Iterator; import java.util.List; import java.util.ArrayList; public class MapGrid extends Grid { protected int seed; protected int count; // variable to store number of continents char[][] continent; // 2d char array to store continent identifier for each cell (i,j) int[] centrality; // int array to store centrality for the capital of each continent int[][] capital; // 2d int array to store coordinates of the capital for each continent boolean[][] seen; // 2d boolean array which is used in method findCapitals() Queue q; // queue of moves used to enqueue neighbors of a cell (i,j) protected MapGrid highNum; protected MapGrid lowNum; protected double avgNum; protected MapGrid highLargest; protected MapGrid lowLargest; protected double avgLargest; protected int largestCont; List mg = new ArrayList(); //List to store MapGrid objects public MapGrid(int rows, int cols, int percentage, int seed) // Preconditions: rows and cols > 0 // 0 <= percentage <= 100 // // Instantiates a grid of size rows by cols, where locations are set to // indicate blob characters based on the percentage probability. { super(rows,cols,percentage); this.rows = rows; this.cols = cols; this.seed = seed; // seed to generate random numbers grid = new boolean [rows][cols]; // to generate random numbers int randInt; Random rand = new Random(seed); for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++) { randInt = rand.nextInt(100); // random number 0 .. 99 if (randInt < percentage) grid[i][j] = true; else grid[i][j] = false; } } private void markBlob(int row, int col, int counter) // Mark position row, col as having been visited & also update each cell's continent identifier // Check and if appropriate mark locations above, below, left, // and right of that position. { visited[row][col] = true; continent[row][col]='A'; // updating each cell's continent identifier continent[row][col]+=counter; // (counter is the current continent integer ID) // check above if ((row - 1) >= 0) // if its on the grid if (grid[row - 1][col]) // and has a blob character if (!visited[row - 1][col]) // and has not been visited markBlob(row - 1, col,counter); // then mark it // check below if ((row + 1) < rows) // if its on the grid if (grid[row + 1][col]) // and has a blob character if (!visited[row + 1][col]) // and has not been visited markBlob(row + 1, col,counter); // then mark it // check left if ((col - 1) >= 0) // if its on the grid if (grid[row][col - 1]) // and has a blob character if (!visited[row][col - 1]) // and has not been visited markBlob(row, col - 1,counter); // then mark it // check right if ((col + 1) < cols) // if its on the grid if (grid[row][col + 1]) // and has a blob character if (!visited[row][col + 1]) // and has not been visited markBlob(row, col + 1, counter); // then mark it } public String continentMap() { // output the continent_map String map = ""; count = 0; visited = new boolean [rows][cols]; // true if location visited continent = new char[rows][cols]; // stores continent identifier for each blob // initialize visited & continent for (int i = 0; i < rows; i++) for (int j = 0; j < cols; j++){ visited[i][j] = false; continent[i][j]='-'; } // mark continents and update continent_map for (int i = 0; i < rows; i++){ for (int j = 0; j < cols; j++){ if (grid[i][j]) if (!visited[i][j]){ markBlob(i, j,count); count++; } map+=continent[i][j]; } map+="\n"; } return map; } private void enqueueNeighbors(int r,int c,int d){ //enqueue neighbors and update distance to (d+1) // check above if ((r - 1) >= 0) // if its on the grid if ((grid[r - 1][c]) && (!seen[r-1][c])){ // has a blob character & has not been visited q.add(new Move(r-1,c,d+1)); //enqueue the Move with (d+1) seen[r-1][c]=true; } // check below if ((r + 1) < rows) if ((grid[r + 1][c]) && (!seen[r + 1][c])){ q.add(new Move(r + 1, c,d+1)); seen[r+1][c]=true; } // check left if ((c - 1) >= 0) if ((grid[r][c - 1]) && (!seen[r][c-1])){ q.add(new Move(r,c-1,d+1)); seen[r][c-1]=true; } // check right if ((c + 1) < cols) if ((grid[r][c + 1]) && (!seen[r][c+1])){ q.add(new Move(r,c+1,d+1)); seen[r][c+1]=true; } } public void findCapitals(){ // method to find capitals (centrality & co-ordinates) of each continent int p,d; centrality = new int[count]; capital = new int[count][2]; for(int i=0;i< rows; i++) for(int j=0; j< cols; j++){ if(grid[i][j]){ // find centrality if it is a grid-cell seen = new boolean[rows][cols]; // to store 'seen' neighbours of a cell (i,j) q = new LinkedList(); // create a queue of moves for each cell (i, j) p = continent[i][j]-'A'; // 'p' is the integer continent identifier q.add(new Move(i,j,0)); seen[i][j]=true; d=0; while(!(q.isEmpty())){ // we enqueue-dequeue 'q' until we've determined the cell (i,j) centrality Move m = q.remove(); d = m.getValue(); enqueueNeighbors(m.getRow(),m.getCol(),d); } if ((centrality[p] == 0) || (d< centrality[p])){ // updating continent's centrality centrality[p]=d; capital[p][0]=i; capital[p][1]=j; } } } } public String capitalMap(){ // method to output capital map findCapitals(); String capital_map = ""; int p; for(int i=0; i < rows; i++){ for(int j=0; j< cols; j++){ if(grid[i][j]){ p = continent[i][j]-'A'; if((capital[p][0] == i) && (capital[p][1] == j)) // if cell (i,j) is a capital capital_map+='*'; else capital_map+=continent[i][j]; } else capital_map+='-'; } capital_map+='\n'; } return capital_map; } public String continentTable(){ // method to return continent Table String output = "Continent Capital Centrality\n"; for(int i=0; i mg2 = new ArrayList(); MapGrid m; while(it.hasNext()){ m = (MapGrid)it.next(); m.largestCont = findLargestCont(m); mg2.add(m); } it = mg2.iterator(); if(highSeed>=lowSeed){ m = (MapGrid)it.next(); highLargest = m; lowLargest = m; avgLargest =m.largestCont; } while(it.hasNext()){ m = (MapGrid)it.next(); if(m.largestCont > highLargest.largestCont) highLargest = m; if(m.largestCont < lowLargest.largestCont) lowLargest = m; avgLargest+=m.largestCont; } avgLargest/=(highSeed-lowSeed+1); } // This method iterates through the List of MapGrid objects and updates highNumConts, lowNumConts and AveNumConts public void gridNumStats(int rows, int cols, int percent, int lowSeed, int highSeed){ collectMapGrids(rows,cols,percent,lowSeed,highSeed); Iterator it=mg.iterator(); MapGrid m; if(highSeed>=lowSeed){ m = (MapGrid)it.next(); highNum=m; lowNum=m; avgNum=m.count; } while(it.hasNext()){ m = (MapGrid)it.next(); if(m.count > highNum.count) highNum = m; if(m.count < lowNum.count) lowNum = m; avgNum+=(m.count); } avgNum/=(highSeed-lowSeed+1); } public MapGrid highNumConts(int rows, int cols, int percent, int lowSeed, int highSeed){ gridNumStats(rows,cols,percent,lowSeed,highSeed); return highNum; } public MapGrid lowNumConts(int rows, int cols, int percent, int lowSeed, int highSeed){ gridNumStats(rows,cols,percent,lowSeed,highSeed); return lowNum; } public double AveNumConts(int rows, int cols, int percent, int lowSeed, int highSeed){ gridNumStats(rows,cols,percent,lowSeed,highSeed); return avgNum; } public MapGrid highLargestCont(int rows, int cols, int percent, int lowSeed, int highSeed){ gridLargestStats(rows,cols,percent,lowSeed,highSeed); return highLargest; } public MapGrid lowLargestCont(int rows, int cols, int percent, int lowSeed, int highSeed){ gridLargestStats(rows,cols,percent,lowSeed,highSeed); return lowLargest; } public double AveLargestCont(int rows, int cols, int percent, int lowSeed, int highSeed){ gridLargestStats(rows,cols,percent,lowSeed,highSeed); return avgLargest; } public String percentageTable(int rows, int cols, int lowSeed, int highSeed){ // method to print the percentageTable String table = ""; double n=0.0,l=0.0; table = "Percent\taveNumCont\taveLargestCont\n"; for(int p=0;p<=100;p+=10){ n = AveNumConts(rows,cols,p,lowSeed,highSeed); l = AveLargestCont(rows,cols,p,lowSeed,highSeed); table += (p+"\t"+String.format("%.2f",n)+"\t"+String.format("%.2f",l)+"\n"); } return table; } }