思路:一开始计划手工划分,后来实在受不了了,就用程序写了一个 ,剩下的再慢慢完善,大致思路为:
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 java.util.stream.Stream; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Pixmap; import com.zhfy.game.framework.ComUtil; import com.zhfy.game.framework.GameMap; import com.zhfy.game.framework.GameUtil; import com.zhfy.game.model.content.btl.BtlModule1; 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 MapBinDAO(BTLDAO btlDao){ if(btlDao!=null) { mapVersion=1; mapWidth=Integer.parseInt(btlDao.getBm0().getBm0_13()); mapHeight=Integer.parseInt(btlDao.getBm0().getBm0_14()); MapBin=new ArrayList<MapBin>(); MapBin mapBin; for(BtlModule1 bm1:btlDao.getBm1()) { mapBin=new MapBin(); mapBin.setBlockType(Integer.parseInt(bm1.getBm1_1())); mapBin.setBackTile(Integer.parseInt(bm1.getBm1_2())); mapBin.setBackIdx(Integer.parseInt(bm1.getBm1_3())); mapBin.setBackRefX(Integer.parseInt(bm1.getBm1_4())); mapBin.setBackRefY(Integer.parseInt(bm1.getBm1_5())); mapBin.setWaterPass(Integer.parseInt(bm1.getBm1_6())); mapBin.setLandPass(Integer.parseInt(bm1.getBm1_7())); mapBin.setRegionId(Integer.parseInt(bm1.getBm1_8())); mapBin.setClimateId(Integer.parseInt(bm1.getBm1_9())); mapBin.setBuildId(Integer.parseInt(bm1.getBm1_10())); mapBin.setBuildLv(Integer.parseInt(bm1.getBm1_11())); mapBin.setFacility(Integer.parseInt(bm1.getBm1_12())); mapBin.setAreaId(Integer.parseInt(bm1.getBm1_13())); MapBin.add(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(); Boolean ifSea =false; for (j = 0; j < 5; j++) { exct=0; regions = getRegions(j); Gdx.app.log("阶段1", "核心地块数" + regions.size()+"获得地块类:"+j); //循环 挨个对核心地块进行循环 while (exct < 20-j && regions.size() != 0) { for (i = regions.size() - 1; i >= 0; i--) { tempId = getRegionId(regions.get(i)); if(!ifSea){//判断海洋,移除 if(tempId>=0&&MapBin.get(tempId).getBlockType()==1){ tempId=-1; } } if (tempId >= 0) { riSize = getIdByRegion(tempId).size(); if (riSize > (13 + 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) 5,ifSea); rsct = getRegionForIdIs0(); Gdx.app.log("阶段3", "剩余绘制数" + rsct); for (Integer rg : regions) { if(!ifSea&&MapBin.get(rg).getBlockType()==1){ }else{ 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 = ComUtil.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) { if(ifSea) {//如果容许海洋,则合并 //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{ //否则把海港归到最近的地块 updHabourForE(); } } 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&&ifSea) { //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 + ""); } } } {//如果不需要海则清除 if(!ifSea){ for(MapBin mapbin:MapBin){ if(mapbin.getBlockType()==1&&mapbin.getBuildId()!=4){ mapbin.setRegionId(0); } } } } Gdx.app.log("执行完成", ""); } } //重新切割省区 public void cutRegionForE(int maxC) { 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(); { exct=0; regions = getRegions(1); Gdx.app.log("阶段1", "核心地块数" + regions.size()+"获得地块类:"+1); //循环 挨个对核心地块进行循环 while (exct < maxC && regions.size() != 0) { for (i = regions.size() - 1; i >= 0; i--) { tempId = getRegionIdForE(regions.get(i)); if (tempId >= 0) { MapBin.get(tempId).setRegionId(regions.get(i)); } else { regions.remove(i); } } Gdx.app.log("阶段2", "核心地块数" + regions.size() + " 循环次数:" + exct); exct++; } } //打印空白陆地地块和海洋有港口的地块 // logBlankGrid(); } //把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的地块 * 10 获取周围是陆地的地块 11获取周围是海洋的地块 * 12获取沿海陆地地块 */ 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的陆地非平原地块 //10 获取周围是陆地的地块 11获取周围是海洋的地块 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); } else if (type == 10 && (MapBin.get(id2).getBlockType() != 1)) { rsIds.add(id2); } else if (type == 11 && (MapBin.get(id2).getBlockType() == 1)) { rsIds.add(id2); }else if (type == 12 && (MapBin.get(id2).getBlockType() == 1)&& (MapBin.get(id).getBlockType() != 1)) { rsIds.add(id2); } } return rsIds; } } public List<Integer> getAroundIdByIds(List<Integer> ids, int type) { List<Integer> rss = new ArrayList<Integer>(); for (Integer id : ids) { List<Integer> rs = getAroundIdById(id, type); rss.addAll(rs); } return rss; } 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) { int s=m; rs.add(s); } } 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, MapBin.get(r).getRegionId()); } else {//陆 //获取周边陆地地块 rsIds = getAroundIdById(r, 7); if (rsIds.size() != 0&&ComUtil.ifGet(30)) { return getShortAroundId(rsIds, MapBin.get(r).getRegionId()); } else { rsIds = getAroundIdById(r, 8); if (rsIds.size() != 0&&ComUtil.ifGet(30)) { return getShortAroundId(rsIds, MapBin.get(r).getRegionId()); } else { rsIds = getAroundIdById(r, 6); if (rsIds.size() != 0&&ComUtil.ifGet(30)) { return getShortAroundId(rsIds, MapBin.get(r).getRegionId()); } else { rsIds = getAroundIdByIds(getIdByRegion(r), 6); if (rsIds != null && rsIds.size() == 0&&ComUtil.ifGet(50)) { //如果周围没有空余地块,则使用相邻的相邻地块判断 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, MapBin.get(r).getRegionId()); } } } } } //-1找不到 //获得要扩展的id public int getRegionIdForE(int r) { List<Integer> rsIds; List<Integer> tempIds; //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, MapBin.get(r).getRegionId()); } else {//陆 //获取周边陆地地块 rsIds = getAroundIdById(r, 6); if (rsIds.size() == 0) { tempIds= getIdByRegion(r); rsIds = getAroundIdByIds(tempIds, 6); if (rsIds == null || rsIds.size() <3) { //如果周围没有空余地块,则使用相邻的相邻地块判断 //Gdx.app.log("清除核心", r+""); return -1; } } int id= getShortAroundId(rsIds, MapBin.get(r).getRegionId()); return id; } } //chance 最高获取概率,最低默认为10 如果不容许有海洋地块,则多抽0.1 private List<Integer> getRegionIdsByChance(int chance,boolean ifSea) { if(!ifSea){ chance= (int) (chance*1.2); } int cutSide = 5; Random rand = new Random(); int i, j, m,rsMax,rpMax; int mMax = MapBin.size();//chance<(int)(Math.random()*(100) List<Integer> rs = new ArrayList<Integer>(); List<Integer> result = new ArrayList<Integer>(); //获取全部为空的地块 for (m = 0; m < mMax; m++) { if (MapBin.get(m).getRegionId() == 0) { if(ifSea){ rs.add(m); }else if(!ifSea&&MapBin.get(m).getBlockType()!=1){ rs.add(m); } } } if (rs.size() == 0) { return rs; } rsMax=rs.size(); rpMax=rsMax*chance/100; /*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()>0) { rs.add(rsCoords.get(rand.nextInt(rsCoords.size())).getId()); rsCoords.clear(); rs=ComUtil.getNewList(rs); } if(rs.size()>rsMax*chance/100){ break; } if (coords.size() == 0) { break; } } } }*/ int tempId; for(i = 0;i<rpMax;i++){ //显示数字并将其从列表中删除,从而实现不重复. tempId=new Random().nextInt(rs.size()); rs.remove(tempId); result.add(tempId); } Gdx.app.log("获得随机核心", rsMax+":"+result.size()); return result; } //获取空白值 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) 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()); } //将id转为coord 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++) { int s=m; rsIds.add(converCoord(ids.get(s))); } return rsIds; } //获得最近的地块 public int getShortAroundId(List<Integer> ids, int regionId) { // Gdx.app.log("求最近的地块,regionId", regionId+""); List<Coord> coords = converCoords(ids); int i, j, iMax = coords.size(), tempId = -1;double jl,jl2; Coord coord = converCoord(regionId); for (i = 0; i < iMax; i++) { for (j = 0; j < iMax; j++) { jl=Math.pow((coords.get(i).getX() - coord.getX()),2) + Math.pow((coords.get(i).getY() - coord.getY()),2); jl2=(Math.pow((coords.get(j).getX() - coord.getX()),2) + Math.pow((coords.get(j).getY() - coord.getY()),2)); //Gdx.app.log("求最近的地块,交换前", "i:"+coords.get(i).getId()+" 距离系数:"+jl); // Gdx.app.log("求最近的地块,交换前", "j:"+coords.get(i).getId()+" 距离系数:"+jl2); if (jl<jl2) { // 交换两数的位置 //Gdx.app.log("求最近的地块,交换前", "i:"+coords.get(i).getId()+" j:"+coords.get(j).getId()); ComUtil.swap(coords, i, j); //Gdx.app.log("求最近的地块,交换后", "i:"+coords.get(i).getId()+" j:"+coords.get(j).getId()); } } } //Gdx.app.log("求最近的地块,最前", coords.get(0).getId()+""); //Gdx.app.log("求最近的地块,最后", coords.get(coords.size()-1).getId()+""); Random rand = new Random(); {//去除非同一势力 TODO for (i = coords.size() - 1; i >= 0; i--) { if(!ifComLegion(coords.get(i).getId(),coord.getId())) { coords.remove(i); } } } if (coords.size() > 2) { tempId = coords.get(rand.nextInt(2)).getId(); } else if (coords.size() == 0) { return -1; } else { tempId = coords.get(0).getId(); } // 1.8的写法 取出List中的对象的属性值 //List<Integer> xs = coords.stream().map(Coord::getX).collect(Collectors.toList()); //List<Integer> ys = coords.stream().map(Coord::getY).collect(Collectors.toList()); List<Integer> xs=new ArrayList<Integer>(); List<Integer> ys=new ArrayList<Integer>(); for(Coord cd:coords){ xs.add(cd.getX()); ys.add(cd.getY()); } int maxX=Collections.max(xs); int minX=Collections.min(xs); int maxY=Collections.max(ys); int minY=Collections.min(ys); if((maxX-minX)>3||(maxY-minY)>3) { if((maxY-minY)!=0&&(maxX-minX)!=0&&((maxX-minX)/(maxY-minY)>2||(maxY-minY)/(maxX-minX)>2)||getRegionCountByRegionId(regionId)<((maxX-minX)*(maxY-minY)/3)) { return -1; } } /*if(getRegionCountByRegionId(regionId)>(10 + Math.random() * 5)) { return -1; }*/ return tempId; } //获取各region的数量记录为map 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; } //获取通过region获取region的数量 private int getRegionCountByRegionId(int regionId) { int c=0; for (MapBin mapBin : MapBin) { if (mapBin.getRegionId()==regionId) { c++; } } return c; } //通过region获取ids public List<Integer> getIdsByRegionId(int regionId){ List<Integer> rs= new ArrayList<Integer>(); int c=0; for (MapBin mapBin : MapBin) { if (mapBin.getRegionId()==regionId) { rs.add(c); } c++; } return rs; } //获取所有region public List<Integer> getAllRegionIds(){ List<Integer> rs = new ArrayList<Integer>(); for (MapBin mapBin : MapBin) { if (mapBin.getRegionId()!=0&&!rs.contains(mapBin.getRegionId())) { rs.add(mapBin.getRegionId()); } } 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= ComUtil.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=ComUtil.getListMostRepeatData(rs); if(rsI!=null&&rsI!="") { //Gdx.app.log("所属区域region不合法:", "i:"+i); updateRegionIds(MapBin.get(Integer.parseInt(rsI)).getRegionId(),MapBin.get(i).getRegionId()); } } } } //打印空白的非海洋地块(包括港口) private void logBlankGrid() { int i=0; for (MapBin mapBin : MapBin) { if (mapBin.getRegionId()==0&&(mapBin.getBackTile()!=1&&mapBin.getBackTile()!=2)) { Gdx.app.log("空白地块", i+""); } i++; } } //验证势力是否一致 r源id i目标id private boolean ifComLegion(int r,int i) { int sourceLegion=MapBin.get(r).getFacility(); int regionLegion=MapBin.get(i).getFacility(); if(sourceLegion==regionLegion) { return true; }else if(sourceLegion==255) { return true; }else { return false; } } //将海港城市归为最近的陆地城市 private void updHabourRegionForE() { List<Integer> habour= getRegions(5); List<Integer> rsIds,tempIds;int id; Random rand = new Random(); for(Integer r:habour) { rsIds = getAroundIdById(r, 4); if (rsIds.size() == 0) { Gdx.app.log("警告", r+":海港周围为空"); }else { id= rsIds.get(rand.nextInt(rsIds.size())); if(id!=-1&&MapBin.get(r).getRegionId()==r) { MapBin.get(r).setRegionId(MapBin.get(id).getRegionId()); } } } } public void updHabourForE() { updHabourRegionForE(); logBlankGrid(); } //替换当前的地区的所有相同区块为一个id的所在区块 public void replaceRegionIdById(int id){ int regionId=MapBin.get(id).getRegionId(); for (MapBin mapBin : MapBin) { if(mapBin.getRegionId()==regionId){ mapBin.setRegionId(id); } } } //替换当前空白的地块以及与其相邻的地块的region public void replaceRegionIdForFFArea(int id,int regionId){ //替换不穿海,只替换该区域的 List<Integer> rs= new ArrayList<Integer>(); List<Integer> tempI; if(MapBin.get(id).getRegionId()!=0){ return; }else{ List<Integer> tempIds=getAroundIdById(id, 6); rs.addAll(tempIds); int n=0; do{ tempIds= (List<Integer>) ((ArrayList<Integer>) rs).clone(); for(int i:tempIds){ tempI=getAroundIdById(i, 6); rs.removeAll(tempI); rs.addAll(tempI); } n=n+1; if(n>5){ break; } }while(ComUtil.ifListContainListByInteger(rs,tempIds)); for(int i:rs){ MapBin.get(i).setRegionId(regionId); } } } //批量获取符合某种条件的地块,条件参看getAroundIdById public List<Integer> getIdsByAround(int type){ List<Integer> rsGrid=new ArrayList<Integer>(); List<Integer> rs; int id=0; for (MapBin mapBin : MapBin) { rs = getAroundIdById(id, type); if(rs.size()>0){ rsGrid.add(id); } id=id+1; } return rsGrid; } }
效果如下:(原点为核心,同颜色为一个省区)