9.随机生成省区
Posted tysk
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了9.随机生成省区相关的知识,希望对你有一定的参考价值。
思路:一开始计划手工划分,后来实在受不了了,就用程序写了一个 ,剩下的再慢慢完善,大致思路为:
1.首先地图存储关键城市,港口,建筑信息,设定这些为核心,以他们扩展,并在扩展时给予一定约束
2.对未扩展的区块进行分割,计算面积,随机出来新的核心,然后再以这些核心扩展
3.对生成的地图进行检验,合并过小的区块,检查生成是否正确等
代码如下:
package com.zhfy.game.model.content; import java.io.BufferedInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Random; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Pixmap; import com.zhfy.game.framework.GameMap; import com.zhfy.game.framework.GameUtils; import com.zhfy.game.model.content.def.DefMap; import com.zhfy.game.model.content.def.DefTerrainimg; import com.zhfy.game.model.framework.Coord; public class MapBinDAO { public int mapVersion;// 2-地图版本 public int mapWidth;// 4-长 public int mapHeight;// 4-宽 public List<MapBin> MapBin;// public int getMapVersion() { return mapVersion; } public void setMapVersion(int mapVersion) { this.mapVersion = mapVersion; } public int getMapWidth() { return mapWidth; } public void setMapWidth(int mapWidth) { this.mapWidth = mapWidth; } public int getMapHeight() { return mapHeight; } public void setMapHeight(int mapHeight) { this.mapHeight = mapHeight; } public List<MapBin> getMapbin() { return MapBin; } public void setMapbin(List<MapBin> MapBin) { this.MapBin = MapBin; } public void initRegionId() { int i, iMax; iMax = MapBin.size(); for (i = 0; i < iMax; i++) { MapBin.get(i).setRegionId(i); } } //随机装饰(除特殊装饰,以及ref有值的外) public void randomAllDecoration() { Random rand = new Random(); //储存地块最高范围 Map map = GameMap.getDecorateRandMaxMap(); //Map(id_type+"_min",idx_min) Map(id_type+"_max",idx_max) //循环遍历所有地块 int i; int iLength = MapBin.size(); int vMin, vMax; for (i = 0; i < iLength; i++) { /* * if(MapBin.get(i).getBackTile()==5) { Gdx.app.log("MapBin.i:", * "imin:"+(MapBin.get(i).getBackTile()+"_"+MapBin.get(i). * getBlockType()+"_min")+" imax:"+(MapBin.get(i).getBackTile()+"_"+ * MapBin.get(i).getBlockType()+"_max")); } */ if (map.containsKey(MapBin.get(i).getBackTile() + "_" + MapBin.get(i).getBlockType() + "_min") && map.containsKey(MapBin.get(i).getBackTile() + "_" + MapBin.get(i).getBlockType() + "_max") && MapBin.get(i).getBackRefX() == 0 && MapBin.get(i).getBackRefY() == 0) { vMin = (Integer) map.get(MapBin.get(i).getBackTile() + "_" + MapBin.get(i).getBlockType() + "_min"); vMax = (Integer) map.get(MapBin.get(i).getBackTile() + "_" + MapBin.get(i).getBlockType() + "_max"); //Gdx.app.log("", " backTile:"+MapBin.get(i).getBackTile()+" type:"+MapBin.get(i).getBackTile()+" max:"+map.get(MapBin.get(i).getBackTile()+"_"+MapBin.get(i).getBlockType()+"_max")+" min:"+map.get(MapBin.get(i).getBackTile()+"_"+MapBin.get(i).getBlockType()+"_min")+" backIdx:"+backIdx); MapBin.get(i).setBackIdx(rand.nextInt(vMax - vMin + 1) + vMin); } if (map.containsKey(MapBin.get(i).getForeTile() + "_" + MapBin.get(i).getBlockType() + "_min") && map.containsKey(MapBin.get(i).getForeTile() + "_" + MapBin.get(i).getBlockType() + "_max") && MapBin.get(i).getForeRefX() == 0 && MapBin.get(i).getForeRefY() == 0) { vMin = (Integer) map.get(MapBin.get(i).getForeTile() + "_" + MapBin.get(i).getBlockType() + "_min"); vMax = (Integer) map.get(MapBin.get(i).getForeTile() + "_" + MapBin.get(i).getBlockType() + "_max"); //Gdx.app.log("", " backTile:"+MapBin.get(i).getBackTile()+" type:"+MapBin.get(i).getBackTile()+" max:"+map.get(MapBin.get(i).getBackTile()+"_"+MapBin.get(i).getBlockType()+"_max")+" min:"+map.get(MapBin.get(i).getBackTile()+"_"+MapBin.get(i).getBlockType()+"_min")+" backIdx:"+backIdx); MapBin.get(i).setForeIdx(rand.nextInt(vMax - vMin + 1) + vMin); } } } //随机增加2层装饰 public void randomForeDecoration() { int foreId, vMin, vMax; Random rand = new Random(); //储存地块最高范围 Map map = GameMap.getDecorateRandMaxMap(); //循环遍历所有地块 int i; int iLength = MapBin.size(); Object o1; for (i = 0; i < iLength; i++) { //配对规则 //4丘陵 4 5 6 //5山地 4 5 6 //6森林 4 5 6 if (rand.nextInt(100) < 31 && map.containsKey(MapBin.get(i).getBackTile() + "_" + MapBin.get(i).getBlockType() + "_min") && map.containsKey(MapBin.get(i).getBackTile() + "_" + MapBin.get(i).getBlockType() + "_max") && MapBin.get(i).getBackTile() > 3 && MapBin.get(i).getBackTile() < 7) { foreId = 4 + rand.nextInt(3); MapBin.get(i).setForeTile(foreId); o1 = map.get(foreId + "_" + MapBin.get(i).getBlockType() + "_min"); if (o1 != null && MapBin.get(i).getForeRefX() == 0 && MapBin.get(i).getForeRefY() == 0) { vMin = (Integer) map.get(foreId + "_" + MapBin.get(i).getBlockType() + "_min"); vMax = (Integer) map.get(foreId + "_" + MapBin.get(i).getBlockType() + "_max"); //Gdx.app.log("", " backTile:"+MapBin.get(i).getBackTile()+" type:"+MapBin.get(i).getBackTile()+" max:"+map.get(MapBin.get(i).getBackTile()+"_"+MapBin.get(i).getBlockType()+"_max")+" min:"+map.get(MapBin.get(i).getBackTile()+"_"+MapBin.get(i).getBlockType()+"_min")+" backIdx:"+backIdx); MapBin.get(i).setForeIdx(rand.nextInt(vMax - vMin + 1) + vMin); } } else { MapBin.get(i).setForeTile(0); MapBin.get(i).setForeIdx(0); } } } //规则 有建筑或有地名的区块=id 否则为0 public void resetRegionId() { int i; int iMax = MapBin.size(); for (i = 0; i < iMax; i++) { if (MapBin.get(i).getAreaId() == 0 && MapBin.get(i).getBuildId() == 0) { MapBin.get(i).setRegionId(0); } else { MapBin.get(i).setRegionId(i); } } } //根据纬度生成随机气候 TODO public void randomClimate() { } //随机海岸河流 TODO public void randomCoastRever() { } //完全随机地图 TODO public void randomAll(int i) { } //重新切割省区 TODO public void cutRegion() { Random rand = new Random(); int tempId, exct = 0, i = 0, iMax = 0, j, jMax, rsct, riSize; List<Integer> regions = null; List<Integer> temps = null; Map regionCountMap = new HashMap(); for (j = 0; j < 5; j++) { exct=0; regions = getRegions(j); Gdx.app.log("阶段1", "核心地块数" + regions.size()+"获得地块类:"+j); //循环 挨个对核心地块进行循环 while (exct < 15-j && regions.size() != 0) { for (i = regions.size() - 1; i >= 0; i--) { tempId = getRegionId(regions.get(i)); if (tempId >= 0) { riSize = getIdByRegion(tempId).size(); if (riSize > (10 + Math.random() * 5)) { regions.remove(i); } else { MapBin.get(tempId).setRegionId(regions.get(i)); } } else { regions.remove(i); } } Gdx.app.log("阶段2", "核心地块数" + regions.size() + " 循环次数:" + exct); exct++; } } //循环2 自定义随机地块 // 随机一定条件取核心值 //循环挨个核心地块循环 //如果核心地块周围有非核心地块的空地且面积不超过一定值,则染色(条件可放宽),否则移除,直到移除全部地块 { regions = getRegionIdsByChance((int) 10); rsct = getRegionForIdIs0(); Gdx.app.log("阶段3", "剩余绘制数" + rsct); for (Integer rg : regions) { MapBin.get(rg).setRegionId(rg); } } int rgc = 0;//可用地块 while (rsct > 0) {//空白地块不能等于0 jMax = regions.size(); if(jMax==0) { break; } for (j = jMax - 1; j >= 0; j--) {//regions.get(j)为当前地块值 //定义当前地块为特定地块 //循环填充周围地块 iMax=(int)(10 + Math.random() * 10); for (i = 0; i < iMax; i++) { rgc = getRegionId(regions.get(j)); if (rgc == -1) { regions.remove(regions.get(j)); break; } else { MapBin.get(rgc).setRegionId(regions.get(j)); } } } rsct = getRegionForIdIs0(); Gdx.app.log("阶段3", "剩余绘制数" + rsct + " 核心地块数:" + regions.size()); } /* 自检,合并不规范地块 */ { //0查看所有region为0的地块并合并到周围地块 { regions = getIdsForBlankRegion(); for (Integer region : regions) {//rsCoords.size() rand.nextInt( temps = getAroundIdById(region, 9); if (temps.size() != 0) { MapBin.get(region).setRegionId(temps.get(rand.nextInt(temps.size()))); } else { //此时剩下的应该是碎小的岛屿或水洞 temps = getAroundIdById(region, 0); if (temps.size() != 0) { MapBin.get(region).setRegionId(temps.get(rand.nextInt(temps.size()))); } else { Gdx.app.log("警告:有空白地块无法合并到周围地块:", region + ""); } } } } //对所有region数量进行检查 //Map.Entry entry; int rgct, argId; List<Integer> argIds, regionCounts; { checkRegion(); regionCountMap = getRegionCountMap(); regionCounts = getKeyByMap(regionCountMap); for (Integer rgId : regionCounts) { if (regionCountMap.containsKey(rgId) && regionCountMap.get(rgId) != null) { rgct = Integer.parseInt(regionCountMap.get(rgId).toString()); if (rgct < 7) { if (MapBin.get(rgId).getBuildId() == 1) { //0:低于5的城市合并周围的最低地块普通或建筑地块(小于5) argIds = getAroundRegionId(rgId);//获取周围地块 for (Integer tarId : argIds) { if (Integer.parseInt(regionCountMap.get(tarId).toString()) < 6 && MapBin.get(tarId).getBuildId() != 1 && MapBin.get(tarId).getBlockType() != 1) { updateRegionIds(rgId, tarId); regionCountMap.put(rgId, (Integer.parseInt(regionCountMap.get(tarId).toString()) + Integer.parseInt(regionCountMap.get(rgId).toString()))); regionCountMap.remove(tarId); break; } } } else if (MapBin.get(rgId).getBuildId() == 4) { //1:低于5的海港合并周围的最低海洋地块(小于5) argIds = getAroundRegionId(rgId);//获取周围地块 for (Integer tarId : argIds) { if (Integer.parseInt(regionCountMap.get(tarId).toString()) < 6 && MapBin.get(tarId).getBuildId() != 4 && MapBin.get(tarId).getBlockType() == 1) { updateRegionIds(rgId, tarId); regionCountMap.put(rgId, (Integer.parseInt(regionCountMap.get(tarId).toString()) + Integer.parseInt(regionCountMap.get(rgId).toString()))); regionCountMap.remove(tarId); break; } } } else if (MapBin.get(rgId).getBlockType() != 1 && MapBin.get(rgId).getBuildId() == 0) { //2:低于5的陆地地块合并到周围地块数量最低的陆地地块 argIds = getAroundRegionId(rgId);//获取周围地块 for (Integer tarId : argIds) { if (Integer.parseInt(regionCountMap.get(tarId).toString()) < 6 && MapBin.get(tarId).getBuildId() != 4 && MapBin.get(tarId).getBlockType() != 1) { updateRegionIds(rgId, tarId); regionCountMap.put(rgId, (Integer.parseInt(regionCountMap.get(tarId).toString()) + Integer.parseInt(regionCountMap.get(rgId).toString()))); regionCountMap.remove(tarId); break; } } } else if (MapBin.get(rgId).getBlockType() == 1) { //3:低于5的海洋地块合并到周围地块数量最低的海洋地块 argIds = getAroundRegionId(rgId);//获取周围地块 for (Integer tarId : argIds) { if (Integer.parseInt(regionCountMap.get(tarId).toString()) < 6 && MapBin.get(tarId).getBuildId() != 4 && MapBin.get(tarId).getBlockType() == 1) { updateRegionIds(rgId, tarId); regionCountMap.put(rgId, (Integer.parseInt(regionCountMap.get(tarId).toString()) + Integer.parseInt(regionCountMap.get(rgId).toString()))); regionCountMap.remove(tarId); break; } } } else if (MapBin.get(rgId).getBlockType() != 1 && MapBin.get(rgId).getBuildId() != 1) { //4:低于5的非城市建筑陆地地块合并到最近的城市地块 argIds = getAroundRegionId(rgId);//获取周围地块 for (Integer tarId : argIds) { if (Integer.parseInt(regionCountMap.get(tarId).toString()) < 6 && MapBin.get(tarId).getBuildId() != 4 && MapBin.get(tarId).getBlockType() != 1) { updateRegionIds(rgId, tarId); regionCountMap.put(rgId, (Integer.parseInt(regionCountMap.get(tarId).toString()) + Integer.parseInt(regionCountMap.get(rgId).toString()))); regionCountMap.remove(tarId); break; } } } else { Gdx.app.log("警告:未检测到的地块:", rgId + ""); } } } } } //0查看所有孤岛类地块并合并到周围地块 { //自动合并孤岛类地块 mergeIslandGridByRegion(); regions = getIdsForBlankRegion(); for (Integer region : regions) {//rsCoords.size() rand.nextInt( if (MapBin.get(region).getBlockType() == 1) { temps = getAroundIdById(region, 3); } else { temps = getAroundIdById(region, 4); } if (temps.size() != 0) { MapBin.get(region).setRegionId(temps.get(rand.nextInt(temps.size()))); } else { Gdx.app.log("警告:有空白地块无法合并到周围地块:", region + ""); } } } Gdx.app.log("执行完成", ""); } } //把region是target的修改为 rgId private void updateRegionIds(Integer rgId, Integer targetId) { //交换前检查合不合法 if(MapBin.get(MapBin.get(rgId).getRegionId()).getRegionId()!=MapBin.get(rgId).getRegionId()) { Gdx.app.log("警告:不合法,修正前", "rgId:"+rgId+" targetId:"+targetId); rgId=MapBin.get(MapBin.get(rgId).getRegionId()).getRegionId(); Gdx.app.log("警告:不合法,修正后", "rgId:"+rgId+" targetId:"+targetId); } for (MapBin mapBin : MapBin) { if (mapBin.getRegionId() == targetId) { mapBin.setRegionId(rgId); } } } public List<Integer> getAroundRegionId(int rgId) { List<Integer> regions = new ArrayList<Integer>(); List<Integer> tempId; int i, iMax = MapBin.size(); int blockType = MapBin.get(rgId).getBlockType(); for (i = 0; i < iMax; i++) { if (MapBin.get(i).getRegionId() == rgId) { if (blockType != 1) { //陆地 tempId = getAroundIdById(i, 4); } else { //海洋 tempId = getAroundIdById(i, 3); } for (Integer id : tempId) { if (MapBin.get(id).getRegionId() != rgId) { regions.add(MapBin.get(id).getRegionId()); } } } } tempId = new ArrayList<Integer>();//去重 for (Integer in : regions) { if (!tempId.contains(in)) { tempId.add(in); } } return tempId; } //根据条件获得核心地块 private List<Integer> getRegions(int i) { //0 全部核心地块 只限城市和海港 //1 只限于陆地的核心地块 只限城市 //2 只限于陆地的核心地块 只限工厂且未被覆盖 //3 只限于陆地的核心地块 只限机场且未被覆盖 //4 只限于陆地的核心地块 只限油库且未被覆盖 //5 只限于海洋的核心地块 只限海港 //6 全部核心地块,不限类型 int m; int mMax = MapBin.size(); List<Integer> regions = new ArrayList<Integer>(); if (i == 0) { for (m = 0; m < mMax; m++) { if (MapBin.get(m).getAreaId() != 0 || (MapBin.get(m).getBuildId() == 1 || MapBin.get(m).getBuildId() == 4)) { regions.add(m); } } } else if (i == 1) { for (m = 0; m < mMax; m++) { if (MapBin.get(m).getBlockType() != 1 && (MapBin.get(m).getAreaId() != 0 || (MapBin.get(m).getBuildId() == 1))) { regions.add(m); } } } else if (i == 2) { for (m = 0; m < mMax; m++) { if (MapBin.get(m).getBlockType() != 1 && (MapBin.get(m).getRegionId() == m || MapBin.get(m).getRegionId() == 0) && (MapBin.get(m).getAreaId() != 0 || (MapBin.get(m).getBuildId() == 2))) { regions.add(m); } } } else if (i == 3) { for (m = 0; m < mMax; m++) { if (MapBin.get(m).getBlockType() != 1 && (MapBin.get(m).getRegionId() == m || MapBin.get(m).getRegionId() == 0) && (MapBin.get(m).getAreaId() != 0 || (MapBin.get(m).getBuildId() == 3))) { regions.add(m); } } } else if (i == 4) { for (m = 0; m < mMax; m++) { if (MapBin.get(m).getBlockType() != 1 && (MapBin.get(m).getRegionId() == m || MapBin.get(m).getRegionId() == 0) && (MapBin.get(m).getAreaId() != 0 || (MapBin.get(m).getBuildId() == 5))) { regions.add(m); } } } else if (i == 5) { for (m = 0; m < mMax; m++) { if (MapBin.get(m).getBlockType() == 1 && (MapBin.get(m).getAreaId() != 0 || (MapBin.get(m).getBuildId() == 4))) { regions.add(m); } } } else if (i == 6) { for (m = 0; m < mMax; m++) { if(!regions.contains(MapBin.get(m).getRegionId())) { regions.add(m); } } } return regions; } //根据id获得周围6边的地块id /* * type 0全部 1获取region为0的地块 3获取周围的有region的海洋地块 4获取周围的有region的陆地地块 * 5只获取region为0的海洋地块 6只获取region为0的陆地地块 7只获取region为0的陆地平原地块 * 8只获取region为0的陆地非平原地块 9根据id区分海洋陆地,获取region为0的地块 * */ public List<Integer> getAroundIdById(int id, int type) { List<Integer> ids = new ArrayList<Integer>(); List<Integer> rsIds = new ArrayList<Integer>(); boolean top = false; boolean foot = false; boolean left = false; boolean right = false; //判断处于哪个边 int y = (int) id / mapWidth; int x = id - y * mapWidth; int t1, t2, t3, t4, t5, t6; if ((x&1) == 1) { t1 = id - 1; t2 = id - mapWidth; t3 = id + 1; t4 = id + mapWidth - 1; t5 = id + mapWidth; t6 = id + mapWidth + 1; } else { t1 = id - mapWidth - 1; t2 = id - mapWidth; t3 = id - mapWidth + 1; t4 = id - 1; t5 = id + mapWidth; t6 = id + 1; } if (x == 0) { left = true; } if (x == mapWidth - 1) { right = true; } if (y == 0) { top = true; } if (y == mapHeight - 1) { foot = true; } if (!top && !left) { ids.add(t1); } if (!top) { ids.add(t2); } if (!top && !right) { ids.add(t3); } if (!foot && !left) { ids.add(t4); } if (!foot) { ids.add(t5); } if (!foot && !right) { ids.add(t6); } //type 0全部 1只读取region为0的值 5只获取region为0的海洋地块 6只获取region为0的陆地地块 //7只获取region为0的陆地平原地块 8只获取region为0的陆地非平原地块 if (type == 0) { return ids; } else { for (Integer id2 : ids) { if (type == 1 && MapBin.get(id2).getRegionId() == 0) { rsIds.add(id2); } else if (type == 6 && MapBin.get(id2).getRegionId() == 0 && MapBin.get(id2).getBlockType() != 1) { rsIds.add(id2); } else if (type == 5 && MapBin.get(id2).getRegionId() == 0 && (MapBin.get(id2).getBlockType() == 1 || MapBin.get(id2).getBackTile() == 1)) { rsIds.add(id2); } else if (type == 7 && MapBin.get(id2).getRegionId() == 0 && MapBin.get(id2).getBlockType() != 1 && MapBin.get(id2).getBackTile() == 0) { rsIds.add(id2); } else if (type == 8 && MapBin.get(id2).getRegionId() == 0 && MapBin.get(id2).getBlockType() != 1 && MapBin.get(id2).getBackTile() != 0) { rsIds.add(id2); } else if (type == 3 && MapBin.get(id2).getRegionId() != 0 && (MapBin.get(id2).getBlockType() == 1)) { rsIds.add(id2); } else if (type == 4 && MapBin.get(id2).getRegionId() != 0 && (MapBin.get(id2).getBlockType() != 1)) { rsIds.add(id2); } else if (type == 9 && ((MapBin.get(id).getBlockType()!=1) ==(MapBin.get(id2).getBlockType() != 1))) { rsIds.add(id2); } } return rsIds; } } public List<Integer> getAroundIdByIds(List<Integer> ids, int type) { List<Integer> rs = null; for (Integer id : ids) { rs = getAroundIdById(id, type); if (rs.size() != 0) { break; } } return rs; } private List<Integer> getIdByRegion(int regionId) { int m; int mMax = MapBin.size(); List<Integer> rs = new ArrayList<Integer>(); for (m = 0; m < mMax; m++) { if (MapBin.get(m).getRegionId() == regionId) { rs.add(m); } } return rs; } //-1找不到 //获得要扩展的id public int getRegionId(int r) { List<Integer> rsIds; //1判断自身是海洋还是陆地 if (MapBin.get(r).getBlockType() == 1) {//海 //获取周边的海洋地块 rsIds = getAroundIdById(r, 5); if (rsIds.size() == 0) { rsIds = getAroundIdByIds(getIdByRegion(r), 5); if (rsIds == null || rsIds.size() == 0) { //如果周围没有空余地块,则使用相邻的相邻地块判断 return -1; } } //根据条件随机获取其中一个地块id //return(rsIds.get(rand.nextInt(rsIds.size()))); return getShortAroundId(rsIds, r); } else {//陆 //获取周边陆地地块 rsIds = getAroundIdById(r, 7); if (rsIds.size() != 0) { return getShortAroundId(rsIds, r); } else { rsIds = getAroundIdById(r, 8); if (rsIds.size() != 0) { return getShortAroundId(rsIds, r); } else { rsIds = getAroundIdById(r, 6); if (rsIds.size() != 0) { return getShortAroundId(rsIds, r); } else { rsIds = getAroundIdByIds(getIdByRegion(r), 6); if (rsIds != null && rsIds.size() == 0) { //如果周围没有空余地块,则使用相邻的相邻地块判断 rsIds = getAroundIdByIds(getIdByRegion(r), 7); if (rsIds != null && rsIds.size() == 0) { //如果周围没有空余地块,则使用相邻的相邻地块判断 rsIds = getAroundIdByIds(getIdByRegion(r), 8); if (rsIds != null && rsIds.size() == 0) { return -1; } } } if (rsIds == null) { return -1; } return getShortAroundId(rsIds, r); } } } } } //chance 最高获取概率,最低默认为10 private List<Integer> getRegionIdsByChance(int chance) { int cutSide = 5; Random rand = new Random(); int i, j, m; int mMax = MapBin.size();//chance<(int)(Math.random()*(100) List<Integer> rs = new ArrayList<Integer>(); //获取全部为空的地块 for (m = 0; m < mMax; m++) { if (MapBin.get(m).getRegionId() == 0) { rs.add(m); } } if (rs.size() == 0) { return rs; } List<Coord> coords = converCoords(rs); List<Coord> rsCoords = new ArrayList<Coord>(); rs = new ArrayList<Integer>(); for (i = mapWidth; i >= 0; i = i - cutSide) { for (j = mapHeight; j >= 0; j = j - cutSide) { for (m = coords.size() - 1; m >= 0; m--) { if (coords.get(m).getX() > i && coords.get(m).getY() > j) { rsCoords.add(coords.get(m)); coords.remove(m); } if (rsCoords.size() > (int) (Math.random() * (chance - 10) + 10)) { rs.add(rsCoords.get(rand.nextInt(rsCoords.size())).getId()); rsCoords.clear(); } if (coords.size() == 0) { break; } } } } return rs; } //获取空白值 private int getRegionForIdIs0() { int ct = 0, m, mMax = MapBin.size(); for (m = 0; m < mMax; m++) { if (MapBin.get(m).getRegionId() == 0) { ct++; } } return ct; } //获得空白地块 private List<Integer> getIdsForBlankRegion() { int m; int mMax = MapBin.size(); List<Integer> rs = new ArrayList<Integer>(); for (m = 0; m < mMax; m++) { if (MapBin.get(m).getRegionId() == 0) { rs.add(m); } } return rs; } //将id转为coord(x,y,id,regionId) TODO 检查 private Coord converCoord(int id) { int y = (int) id / mapWidth; int x = id - y * mapWidth; return new Coord(x, y, id, MapBin.get(id).getRegionId()); } private List<Coord> converCoords(List<Integer> ids) { int m; int mMax = ids.size(); List<Coord> rsIds = new ArrayList<Coord>(); for (m = 0; m < mMax; m++) { rsIds.add(converCoord(ids.get(m))); } return rsIds; } //获得最近的地块 public int getShortAroundId(List<Integer> ids, int regionId) { List<Coord> coords = converCoords(ids); int i, j, iMax = coords.size(), tempId = -1; Coord coord = converCoord(regionId); for (i = 0; i < iMax; i++) { for (j = 0; j < iMax; j++) { if ((Math.abs(coords.get(i).getX() - coord.getX()) + Math.abs(coords.get(i).getY() - coord.getY())) < (Math.abs(coords.get(j).getX() - coord.getX()) + Math.abs(coords.get(j).getY() - coord.getY()))) { // 交换两数的位置 swap(coords, i, j); } } } Random rand = new Random(); if (coords.size() > 2) { tempId = coords.get(rand.nextInt(2)).getId(); } else if (coords.size() == 0) { return -1; } else { tempId = coords.get(0).getId(); } List<Integer> xs = coords.stream().map(Coord::getX).collect(Collectors.toList()); List<Integer> ys = coords.stream().map(Coord::getY).collect(Collectors.toList()); int maxX=Collections.max(xs); int minX=Collections.min(xs); int maxY=Collections.max(ys); int minY=Collections.min(ys); if((maxY-minY)!=0&&(maxX-minX)!=0&&((maxX-minX)/(maxY-minY)>2||(maxY-minY)/(maxX-minX)>2)) { return -1; } if(getRegionCountByRegionId(regionId)>(10 + Math.random() * 5)) { return -1; } return tempId; } //获取各region的数量 private Map getRegionCountMap() { Map rsMap = new HashMap(); for (MapBin mapBin : MapBin) { if (!rsMap.containsKey(mapBin.getRegionId())) { rsMap.put(mapBin.getRegionId(), 1); } else { rsMap.put(mapBin.getRegionId(), Integer.parseInt(rsMap.get(mapBin.getRegionId()).toString()) + 1); } } return rsMap; } private int getRegionCountByRegionId(int regionId) { int c=0; for (MapBin mapBin : MapBin) { if (mapBin.getRegionId()==regionId) { c++; } } return c; } //list值交换位置 public static void swap(List<?> list, int i, int j) { final List l = list; l.set(i, l.set(j, l.get(i))); } //获取map的key值 public List<Integer> getKeyByMap(Map map) { List<Integer> rs = new ArrayList<Integer>(); for (Object key : map.keySet()) { rs.add(Integer.parseInt(key.toString())); } return rs; } //合并孤岛类地块 private void mergeIslandGridByRegion() { int i,iMax=MapBin.size(),rsI=0; String rz; List<Integer> rs; int tempRegionId; for (i=0;i<iMax;i++) { //获得结果值 rs= getAroundIdById(i,9); Collections.sort(rs); rsI=0; //判断是否是孤岛 for(Integer id:rs) { if(MapBin.get(id).getRegionId()!=MapBin.get(i).getRegionId()) { rsI++; } } if(rsI>4) { rz= getListMostRepeatData(rs); //updateRegionIds(MapBin.get(Integer.parseInt(rz)).getRegionId(),i); MapBin.get(i).setRegionId(MapBin.get(Integer.parseInt(rz)).getRegionId()); } } } public static void main(String[] args) { int i; for (i = 0; i < 30; i++) { System.out.println("sj:" + (int) (10 + Math.random() * 15)); } } //检查所属的区块是不是合法的region,如果不是给周围的地块 TODO测试 private void checkRegion() { int i,iMax=MapBin.size();String rsI; List<Integer> rs; for (i=0;i<iMax;i++) { //获得结果值 rs= getAroundIdById(i,9); Collections.sort(rs); if(MapBin.get(MapBin.get(i).getRegionId()).getRegionId()!=MapBin.get(i).getRegionId()) { rsI=getListMostRepeatData(rs); if(rsI!=null&&rsI!="") { //Gdx.app.log("所属区域region不合法:", "i:"+i); updateRegionIds(MapBin.get(Integer.parseInt(rsI)).getRegionId(),MapBin.get(i).getRegionId()); } } } } //获得list出现最多的数据 public String getListMostRepeatData(List<?> l) { String regex; Pattern p; Matcher m; String tmp = ""; String tot_str = l.toString(); //System.out.println(tot_str); //[aa, aa, aa, aa, bb, bb, cc, cc, dd, ed] int max_cnt = 0; String max_str = ""; for(Object str : l) { if (tmp.equals(str)) continue; tmp = str.toString(); regex = str.toString(); p = Pattern.compile(regex); m = p.matcher(tot_str); int cnt = 0; while(m.find()) { cnt++; } //System.out.println(str + ":" + cnt); if (cnt > max_cnt) { max_cnt = cnt; max_str = str.toString(); } } //System.out.println(" 出现的最大次数的字符串是 " + max_str) ; return max_str; } }
效果如下:(原点为核心,同颜色为一个省区)
以上是关于9.随机生成省区的主要内容,如果未能解决你的问题,请参考以下文章