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

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

技术图片技术图片技术图片技术图片技术图片技术图片

以上是关于9.随机生成省区的主要内容,如果未能解决你的问题,请参考以下文章

如何在SQL里生成四位随机数?

环保净化车

java如何生成随机数?

随机森林引导训练和森林生成

最近遇到的两个有意思的问题(合并K个有序数组,打印省区市所有与目标市名字相同的路径)

最近遇到的两个有意思的问题(合并K个有序数组,打印省区市所有与目标市名字相同的路径)