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 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;
    }

}
MapBinDAO

效果如下:(原点为核心,同颜色为一个省区)

转载于:https://www.cnblogs.com/tysk/p/10872957.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要使用 Echarts 显示四川省区县地图,你需要准备以下资源和步骤: 1. 获取地图数据:你可以从公开的地图数据源或者官方提供的地图数据中心获取四川省区县的地理数据,通常是一个包含地理坐标和区县名称的 GeoJSON 文件。 2. 引入 Echarts 库:在你的网页中引入 Echarts 库,可以通过下载 Echarts 或者使用 CDN 引入。 3. 创建一个具有指定 ID 的 DOM 容器,用于显示地图。 4. 初始化 Echarts 实例:通过 JavaScript 代码初始化一个 Echarts 实例,并将它与之前创建的 DOM 容器关联起来。 5. 配置地图参数:使用 Echarts 提供的 API 配置地图的相关参数,包括地图类型、数据源、样式等。 6. 绘制地图:使用 `setOption` 方法将配置好的参数传递给 Echarts 实例,然后 Echarts 会自动绘制地图。 以下是一个简单的示例代码: ```html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Echarts 显示四川省区县地图</title> <script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script> </head> <body> <div id="mapContainer" style="width: 800px; height: 600px;"></div> <script> // 初始化 Echarts 实例 var chart = echarts.init(document.getElementById('mapContainer')); // 配置地图参数 var option = { title: { text: '四川省区县地图', subtext: '示例', left: 'center' }, tooltip: { trigger: 'item' }, series: [{ name: '四川省区县', type: 'map', mapType: '四川', roam: true, // 开启鼠标缩放和平移漫游 label: { show: true, textStyle: { color: '#000', fontSize: 12 } }, data: [ // 这里填入你的区县地理数据 { name: '成都市', value: 100 }, { name: '绵阳市', value: 50 }, // ... ] }] }; // 绘制地图 chart.setOption(option); </script> </body> </html> ``` 注意,你需要将示例代码中的地理数据替换为你自己的四川省区县数据,并确保 Echarts 库文件正确引入。此外,你还可以根据需要调整地图的样式和交互行为。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值