বাস্তব মানচিত্র তৈরি করুন


25

আমি এমএস পেইন্টে কয়েক মিনিটের মধ্যে একটি কাল্পনিক শব্দের অঞ্চলগুলির এই মানচিত্রটি আঁকলাম:

আমার মানচিত্র

আমি মনে করি যে প্রোগ্রামের মতো এই জাতীয় মানচিত্র তৈরি করতে সক্ষম হওয়া সত্যিই দুর্দান্ত।

চ্যালেঞ্জ

এমন একটি প্রোগ্রাম লিখুন যা ইতিবাচক পূর্ণসংখ্যার Wএবং H, এবং খালি খালি ইতিবাচক পূর্ণসংখ্যার সেট করে S

পিক্সেল লম্বা পিক্সেল প্রশস্ত একটি স্ট্যান্ডার্ড সত্য রঙের চিত্র তৈরি করুন ।WH

প্রতিটি পূর্ণসংখ্যা জন্য iমধ্যে S, ইমেজ পিক্সেলে যার এলাকায় সমানুপাতিক একটি প্ল্যানার অঞ্চল আঁকা iকোন প্রতিবেশী অঞ্চল থেকে একটি রং বিভিন্ন ব্যবহার করে,। বিশেষত, এই অঞ্চলে পিক্সেলগুলির সংখ্যাটি W * H * i / sum(S)উপরের বা নীচে গোল করা উচিত তা নিশ্চিত করার জন্য চিত্রটির প্রতিটি পিক্সেল কোনও অঞ্চলের অন্তর্গত

পরিকল্পনাকারী অঞ্চল হ'ল সংস্থার সাথে পিক্সেলের একটি সেট যা অঞ্চলে থাকা কোনও পিক্সেল অন্য যে কোনও অঞ্চলে থাকতে পারে এবং কেবল অर्थ োগোনালি (এবং তির্যক নয়) চলে যাওয়ার মাধ্যমে পৌঁছানো যায় । আমার মানচিত্রে 10 প্ল্যানার অঞ্চল রয়েছে।

প্ল্যানার অঞ্চলের সমস্ত পিক্সেল অবশ্যই একই রঙের হতে হবে, যা অবশ্যই কোনও প্রতিবেশী অঞ্চলের রঙের চেয়ে আলাদা হতে হবে। অঞ্চলগুলি প্রতিবেশী না হলে একই বর্ণ থাকতে পারে।

অন্যথায়, আপনি কীভাবে আপনার অঞ্চলগুলিকে আকৃতি, অবস্থান বা রঙিন করতে পারেন তার কোনও সীমাবদ্ধতা নেই। এটি একটি জনপ্রিয়তা-প্রতিযোগিতা। লক্ষ্য হ'ল এমন একটি প্রোগ্রাম তৈরি করা যা কোনও স্তরের ভৌগলিক সহ কোনও শারীরিক বা রাজনৈতিক, কাল্পনিক জগতের বাস্তব মানচিত্র তৈরি করে।

স্বাভাবিকভাবেই, দয়া করে কেবল আপনার কোড নয়, আপনার সেরা আউটপুট চিত্রগুলি প্রদর্শন করুন।

বিস্তারিত

  • ফাইল, কমান্ড লাইন, স্টিডিন বা অনুরূপ থেকে ইনপুট নিন। চিত্রটি কোনও মানক বিন্যাসে সংরক্ষণ করুন বা স্ক্রিনে প্রদর্শন করুন।
  • আপনার প্রোগ্রামটি অভিন্ন ইনপুটগুলির জন্য নির্ধারিত হওয়া উচিত। অর্থাৎ আউটপুট ইমেজ সবসময় কিছু নির্দিষ্ট জন্য একই হতে হবে H, Wএবং S। (দ্রষ্টব্য এটি Sএকটি সেট , কোনও তালিকা নয়, তাই এর ক্রমটি অর্ডার করার কোনও গুরুত্ব নেই)) অন্যথায় আপনি এলোমেলোভাবে কর্মসংস্থান করতে পারেন যেখানে আপনি চান না, যদিও আপনার প্রয়োজন হয় না (তবে আমি এটির জন্য অত্যন্ত পরামর্শ দিই)।
  • আউটপুট চিত্রের ভূগোলের বিভিন্ন মান Wবা H(যদিও এটি হতে পারে) জন্য "স্কেল" করতে হবে না । এটি সম্পূর্ণ আলাদা হতে পারে।
  • আপনি এলোমেলোভাবে রঙগুলি বরাদ্দ করতে পারেন, প্রতিবেশী-রঙের নিয়মকে উপেক্ষা করে, যতক্ষণ না কমপক্ষে 32 টি এলোমেলো রঙের সম্ভাবনা রয়েছে, যেহেতু দুই প্রতিবেশীর পক্ষে রঙিন একরকম হওয়ার সম্ভাবনা কম।
  • অঞ্চলগুলি চিত্রের সীমানায় থামে। চারপাশে কোনও মোড়ানো নেই ।
  • অঞ্চলগুলিতে শূন্য পিক্সেল (এবং এইভাবে অস্তিত্বহীন থাকতে পারে) থাকতে পারে, যেমন পিক্সেলগুলির চেয়ে বেশি অঞ্চল থাকতে পারে।

উদাহরণ ইনপুট

একটি বৈধ জমা দেওয়ার ফলে প্যারামিটারগুলি সহ আমার মানচিত্রটি উত্পন্ন হয়েছে:

W = 380
H = 260
S = {233, 420, 1300, 3511, 4772, 5089, 9507, 22107, 25117, 26744}

এই Sমানগুলি প্রতিটি অঞ্চলে পিক্সেলের সংখ্যার মতো হুবহু তবে এটির প্রয়োজন হবে না। মনে রাখবেন যে Sএটি একটি সেট, তাই এটি সর্বদা বাছাই করা হয় না।

উত্তর:


15

আমি অন্যদের সাথে একমত, এটি একটি আশ্চর্যজনকভাবে চ্যালেঞ্জ ছিল। আংশিকভাবে একই অঞ্চলের ধরণের নিকটবর্তীভাবে সংযুক্ত পিক্সেলগুলির প্রয়োজনের কারণে, তবে অঞ্চলগুলিকে দেশের মানচিত্রের মতো দেখানোর নান্দনিক চ্যালেঞ্জের কারণেও।

এখানে আমার প্রচেষ্টা ... এটি মারাত্মকভাবে অক্ষম তবে যুক্তিসঙ্গত আউটপুট তৈরি বলে মনে হচ্ছে। তুলনা উদ্দেশ্যে সাধারণ ইনপুট ব্যবহার করার প্রবণতা অব্যাহত:

প্যারামিটার: 380 260 233 420 1300 3511 4772 5089 9507 22107 25117 26744

এখানে চিত্র বর্ণনা লিখুন

প্যারামিটার: 380 260 8 5 6 7 8 4 5 6 7 9 4 6 9 5 8 8 7 5

এখানে চিত্র বর্ণনা লিখুন

ক্যামলোটের অন্ধকার বয়স 213 307 1 1 1

এখানে চিত্র বর্ণনা লিখুন

আমার আরও বড় উদাহরণ: (640 480 6 1 7 2 9 3 4 5 6 1 9 8 7 44 3 1 9 4 5 6 7 2 3 4 9 3 4 5 9 8 7 5 6 1 2 1 2 1 2 6 7 8 9 63 3)

এখানে চিত্র বর্ণনা লিখুন

আরও দেশগুলির সাথে একটি উদাহরণ: 640 480 6 1 7 2 9 3 4 5 6 1 9 8 7 44 3 1 9 4 5 6 7 2 3 4 9 3 4 5 9 8 7 5 6 1 2 1 2 1 2 6 7 8 9 63 5 33 11 88 2 7 9 5 6 2 5 7

package GenerateRealisticMaps;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import javax.imageio.ImageIO;

public class GenerateRealisticMaps
{
    private static final Random rand = new Random(3);
    private static final Color[] paletteizedColours = new Color[100];

    // create colour palette
    static
    {
        paletteizedColours[0] = new Color(0xFF000000);
        for (int i = 1; i < paletteizedColours.length; i++)
        {
            paletteizedColours[i] = Color.getHSBColor(rand.nextFloat(), rand.nextFloat(), 0.5f + rand.nextFloat() * 0.4f);
        }
    }

    /**
     * Represents a pixel that is the boundary of a region
     * @author default
     *
     */
    public static class BoundaryPixel
    {
        public BoundaryPixel(int x, int y, int otherRegionId)
        {
            super();
            this.x = x;
            this.y = y;
            this.otherRegionId = otherRegionId;
        }

        int x;
        int y;
        int otherRegionId;
    }

    /**
     * Group of adjacent pixels that represent a region (i.e. a country in the map)
     * @author default
     *
     */
    public static class Region
    {
        static private int masterId = 0;

        Region(int desiredSize)
        {
            this.desiredSize = desiredSize;
            id = ++masterId;
        }

        int desiredSize;
        int size = 0;
        int id;
        List<BoundaryPixel> boundary = new ArrayList<GenerateRealisticMaps.BoundaryPixel>();

    }

    /**
     * Container of regions
     * @author default
     *
     */
    public static class Regions
    {
        List<Region> regionList = new ArrayList<GenerateRealisticMaps.Region>();
        Map<Integer, Region> regionMap = new HashMap<Integer, GenerateRealisticMaps.Region>();
    }

    public static void main(String[] args) throws IOException
    {
        int width = Integer.parseInt(args[0]);
        int height = Integer.parseInt(args[1]);
        int[] s = new int[args.length - 2];

        // read in the region weights
        int sum = 0;
        for (int i = 0; i < args.length - 2; i++)
        {
            sum += s[i] = Integer.parseInt(args[i + 2]);
        }

        int totalPixels = width * height;

        double multiplier = ((double) totalPixels) / sum;

        // convert region weights to pixel counts
        int runningCount = 0;
        for (int i = 0; i < s.length - 1; i++)
        {
            runningCount += s[i] = (int) (multiplier * s[i]);
        }
        s[s.length - 1] = totalPixels - runningCount;

        Regions regions = new Regions();
        int[][] map = new int[width][height];

        // initialise region starting pixels
        for (int v : s)
        {
            Region region = new Region(v);
            regions.regionList.add(region);
            regions.regionMap.put(region.id, region);

            int x;
            int y;
            do
            {
                x = rand.nextInt(width);
                y = rand.nextInt(height);
            } while (map[x][y] != 0);

            map[x][y] = region.id;
            region.size++;

        }

        // initialise a "height" map that provides cost to claim a unclaimed region. This allows for more natural shaped countries
        int[][] heightMap = new int[width][height];
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < height; j++)
            {
                heightMap[i][j] = rand.nextInt(50);
            }
        }

        boolean equal = false;

        // main loop
        do
        {
            growRegions(map, heightMap, width, height, regions);

            // determine whether regions have reached their desired size
            equal = true;
            for (Region region : regions.regionList)
            {
                equal = equal && region.size == region.desiredSize;
            }

            if (equal)
            {
                HashMap<Integer, Set<Integer>> commonIsolatedRegions = new HashMap<Integer, Set<Integer>>();
                int isolatedRegionId = 0;
                int[][] isolatedRegions = new int[width][height];
                List<Integer> isolatedRegionSize = new ArrayList<Integer>();
                isolatedRegionSize.add(-1); // add dummy entry at index 0 since region ids start at 1

                // go though each pixel and attempt to identify an isolated region from that point if it as not
                // yet been identified... i.e. an enclosed area.
                for (int i = 0; i < width; i++)
                {
                    for (int j = 0; j < height; j++)
                    {
                        if (isolatedRegions[i][j] == 0)
                        {
                            isolatedRegionId++;

                            Point point = new Point(i, j);
                            int size = identifyEnclosedArea(map, isolatedRegions, width, height, point, isolatedRegionId);

                            // add this isolated region id to the group of isolated regions associated with the region at this pixel
                            Set<Integer> isolatedRegionSet = commonIsolatedRegions.get(map[i][j]);
                            if (isolatedRegionSet == null)
                            {
                                isolatedRegionSet = new HashSet<Integer>();
                                commonIsolatedRegions.put(map[i][j], isolatedRegionSet);
                            }
                            isolatedRegionSet.add(isolatedRegionId);
                            isolatedRegionSize.add(size);
                        }
                    }
                }

                // only keep the largest isolated region in each group. Mark the other members in the group areas as unclaimed.
                for (Region region : regions.regionList)
                {
                    Set<Integer> isolatedRegionSet = commonIsolatedRegions.get(region.id);

                    // find the largest isolatedRegion mapped to this region
                    int largestIsolatedRegionId = -1;
                    int largestIsolatedRegionSize = -1;
                    for (Integer isolatedRegionIdentifier : isolatedRegionSet)
                    {
                        if (isolatedRegionSize.get(isolatedRegionIdentifier) > largestIsolatedRegionSize)
                        {
                            largestIsolatedRegionSize = isolatedRegionSize.get(isolatedRegionIdentifier);
                            largestIsolatedRegionId = isolatedRegionIdentifier;
                        }
                    }
                    // remove the largest isolated region (i.e. retain those pixels)
                    isolatedRegionSet.remove(largestIsolatedRegionId);

                    if (isolatedRegionSet.size() > 0)
                    {
                        equal = false;

                        // for all remaining isolated regions mapped to this region, convert to unclaimed areas.
                        for (Integer isolatedRegionIdentifier : isolatedRegionSet)
                        {
                            for (int i = 0; i < width; i++)
                            {
                                for (int j = 0; j < height; j++)
                                {
                                    if (isolatedRegions[i][j] == isolatedRegionIdentifier)
                                        map[i][j] = 0;
                                }
                            }
                        }
                    }
                }
            }

        } while (!equal);

        saveOutputImage("out.final.png", map);
    }

    /**
     * Renders and saves the output image
     * 
     * @param filename
     * @param map
     * @throws IOException
     */
    public static void saveOutputImage(String filename, int[][] map) throws IOException
    {

        final int scale = 1;
        final int width = map.length;
        final int height = map[0].length;
        BufferedImage image = new BufferedImage(width * scale, height * scale, BufferedImage.TYPE_INT_RGB);

        Graphics2D g = (Graphics2D) image.getGraphics();

        for (int j = 0; j < height; j++)
        {
            for (int i = 0; i < width; i++)
            {
                g.setColor(paletteizedColours[map[i][j]]);
                g.fillRect(i * scale, j * scale, scale, scale);
            }
        }

        ImageIO.write(image, "png", new File(filename));
    }

    /**
     * Grows the regions of the world. Firstly by unclaimed cells and then by distributing cells amongst the regions.
     * 
     * @param map
     *            cell to region map
     * @param heightMap
     *            the "height" cost of unclaimed cells. Used to give more natural shapes.
     * @param width
     * @param height
     * @param regions
     */
    public static void growRegions(int[][] map, int[][] heightMap, int width, int height, Regions regions)
    {
        // reset region sizes
        for (Region region : regions.regionList)
        {
            region.size = 0;
            region.boundary.clear();
        }

        // populate corners with adjacent pixel region id... these pixels cannot ever be "grown" into.
        map[0][0] = map[1][0];
        map[width - 1][0] = map[width - 1][5];
        map[width - 1][height - 1] = map[width - 2][height - 1];
        map[0][height - 1] = map[1][height - 1];

        int i, x, y, dx = 0, dy = 0, currHeight, currentId = -1, pixelRegionId;
        Region currRegion = null;
        ;

        // calculate initial region sizes
        for (y = 0; y < height; y++)
        {
            for (x = 0; x < width; x++)
            {
                if (map[x][y] > 0)
                    regions.regionMap.get(map[x][y]).size++;
            }
        }

        // expand regions into surrounding unclaimed pixels.
        // construct a list of region boundary pixels in the process.
        for (y = 1; y < height - 1; y++)
        {
            for (x = 1; x < width - 1; x++)
            {
                int cellId = map[x][y];
                if (cellId > 0)
                {
                    if (cellId != currentId)
                    {

                        currRegion = regions.regionMap.get(map[x][y]);
                        currentId = currRegion.id;
                    }

                    currHeight = heightMap[x][y]++;

                    for (i = 0; i < 4; i++)
                    {
                        switch (i)
                        {
                        case 0:
                            dx = x - 1;
                            dy = y;
                            break;
                        case 1:
                            dx = x + 1;
                            dy = y;
                            break;
                        case 2:
                            dx = x;
                            dy = y - 1;
                            break;
                        case 3:
                            dx = x;
                            dy = y + 1;
                            break;
                        }
                        pixelRegionId = map[dx][dy];
                        switch (pixelRegionId)
                        {
                        // unclaimed cell...
                        case 0:
                            if (heightMap[dx][dy] < currHeight)
                            {
                                map[dx][dy] = currRegion.id;
                                currRegion.size++;
                            }
                            break;
                        // claimed cell...
                        default:
                            if (pixelRegionId != currRegion.id)
                            {
                                currRegion.boundary.add(new BoundaryPixel(dx, dy, pixelRegionId));
                            }
                            break;
                        }
                    }
                }
            }
        }

        HashMap<Integer, List<BoundaryPixel>> neighbourBorders = new HashMap<Integer, List<BoundaryPixel>>();

        // for all regions...
        for (Region region : regions.regionList)
        {
            // that are less than the desired size...
            if (region.size < region.desiredSize)
            {
                neighbourBorders.clear();

                // identify the boundary segment per neighbour of the region
                for (BoundaryPixel boundaryPixel : region.boundary)
                {
                    List<BoundaryPixel> neighbourBorderSegment = neighbourBorders.get(boundaryPixel.otherRegionId);
                    if (neighbourBorderSegment == null)
                    {
                        neighbourBorderSegment = new ArrayList<GenerateRealisticMaps.BoundaryPixel>();
                        neighbourBorders.put(boundaryPixel.otherRegionId, neighbourBorderSegment);
                    }
                    neighbourBorderSegment.add(boundaryPixel);
                }

                out:
                // for each neighbour...
                for (int id : neighbourBorders.keySet())
                {
                    Region neighbourRegion = regions.regionMap.get(id);
                    int surplusPixelCount = neighbourRegion.size - neighbourRegion.desiredSize;
                    // that has surplus pixels...
                    if (surplusPixelCount > 0)
                    {
                        // and convert the border segment pixels to the current region...
                        List<BoundaryPixel> neighbourBorderSegment = neighbourBorders.get(id);
                        int index = 0;
                        while (surplusPixelCount-- > 0 && index < neighbourBorderSegment.size())
                        {
                            BoundaryPixel boundaryPixel = neighbourBorderSegment.get(index++);
                            map[boundaryPixel.x][boundaryPixel.y] = region.id;
                            region.size++;
                            regions.regionMap.get(boundaryPixel.otherRegionId).size--;
                            // until we reach the desired size...
                            if (region.size == region.desiredSize)
                                break out;
                        }
                    }
                }
            }

            // if region contains more pixels than desired...
            else if (region.size > region.desiredSize)
            {
                // and the region has neighbours
                if (region.boundary.size() > 0)
                {
                    // choose a neighbour to off load extra pixels to
                    Region neighbour = regions.regionMap.get(region.boundary.remove(rand.nextInt(region.boundary.size())).otherRegionId);

                    ArrayList<BoundaryPixel> adjustedBoundary = new ArrayList<>();
                    // iterate over the boundary neighbour's boundary pixels...
                    for (BoundaryPixel boundaryPixel : neighbour.boundary)
                    {
                        // and then for those pixels which are of the current region, convert to the neighbour region
                        if (boundaryPixel.otherRegionId == region.id)
                        {
                            map[boundaryPixel.x][boundaryPixel.y] = neighbour.id;
                            neighbour.size++;
                            region.size--;
                            // stop when we reach the region's desired size.
                            if (region.size == region.desiredSize)
                                break;
                        }
                        else
                        {
                            adjustedBoundary.add(boundaryPixel);
                        }
                    }
                    neighbour.boundary = adjustedBoundary;
                }
            }
        }

    }

    /**
     * identifies the area, starting at the given point, in which adjacent pixels are of the same region id.
     * 
     * @param map
     * @param isolatedRegionMap
     *            cells identifying which area that the corresponding map cell belongs
     * @param width
     * @param height
     * @param point
     *            the starting point of the area to be identified
     * @param isolatedRegionId
     *            the id of the region to assign cells with
     * @return the size of the identified area
     */
    private static int identifyEnclosedArea(int[][] map, int[][] isolatedRegionMap, int width, int height, Point point, final int isolatedRegionId)
    {
        ArrayList<Point> stack = new ArrayList<Point>();
        final int EXPECTED_REGION_ID = map[point.x][point.y];
        stack.add(point);
        int size = 0;

        while (stack.size() > 0)
        {
            Point p = stack.remove(stack.size() - 1);
            int x = p.x;
            int y = p.y;
            if (y < 0 || y > height - 1 || x < 0 || x > width - 1 || isolatedRegionMap[x][y] > 0)
                continue;
            int val = map[x][y];
            if (val == EXPECTED_REGION_ID)
            {
                isolatedRegionMap[x][y] = isolatedRegionId;
                size++;
                stack.add(new Point(x + 1, y));
                stack.add(new Point(x - 1, y));
                stack.add(new Point(x, y + 1));
                stack.add(new Point(x, y - 1));
            }
        }

        return size;
    }

}

ব্যাখ্যা (মন্তব্য থেকে)

অ্যালগোরিদমটি বেশ সহজ: প্রথমত মানচিত্রটিকে এলোমেলো ওজন দিয়ে সূচনা করুন, দেশের প্রতিটি অঞ্চলের জন্য এলোমেলো বীজ পিক্সেল চয়ন করুন। দ্বিতীয়ত দাবিবিহীন সংলগ্ন পিক্সেল দাবি করার চেষ্টা করে প্রতিটি অঞ্চল "বৃদ্ধি" করুন। এটি ঘটে যখন বর্তমান পিক্সেলের ওজন দাবিবিহীন ওজনকে ছাড়িয়ে যায়।

একটি অঞ্চলে প্রতিটি পিক্সেল প্রতিটি বৃদ্ধি চক্রের ওজন বাড়িয়ে তোলে। তদুপরি যদি কোনও অঞ্চলে প্রতিবেশী থাকে তবে বর্তমান অঞ্চল বিবেচনা করা হলে কাঙ্ক্ষিতের চেয়ে কম পিক্সেল থাকে, তবে প্রতিবেশীর পছন্দসই চেয়ে আরও বেশি পিক্সেল থাকলে তা প্রতিবেশীর কাছ থেকে পিক্সেল চুরি করবে। বর্তমান অঞ্চলে যদি তার প্রতিবেশীর চেয়ে বেশি পিক্সেল থাকে তবে এটি এলোমেলোভাবে প্রতিবেশী চয়ন করে এবং তারপরে সমস্ত উদ্বৃত্ত পিক্সেল দেয়। যখন সমস্ত অঞ্চল সঠিক আকারের হয়, তৃতীয় ধাপটি এমন কোনও অঞ্চলকে চিহ্নিত এবং রূপান্তর করতে দেখা যায় যা বিভক্ত হয়ে গেছে এবং এখন আর অবিচ্ছিন্ন নয়।

কেবলমাত্র অঞ্চলের বৃহত্তম বিভাজন রাখা আছে এবং অন্যান্য বিভাজনগুলি দাবি ছাড়াই পিক্সেলে রূপান্তরিত হয় এবং দ্বিতীয় পর্বটি আবার শুরু হয়। কোনও অঞ্চলে সমস্ত পিক্সেল সংলগ্ন এবং সমস্ত অঞ্চল সঠিক আকারের না হওয়া পর্যন্ত এটি পুনরাবৃত্তি করে।


ওটা সুন্দর ! আপনার অ্যালগরিদম কীভাবে কাজ করে আপনি কিছুটা ব্যাখ্যা করতে পারেন?
Arnaud

1
গ্রেট! আমি মনে করি কেবল রংগুলি আরও "আর্থি" হতে পারে (তৃতীয়টি আরও ক্যামেললটের গা Pur় বেগুনি যুগের মতো : পি)। আমি মনে করি আপনি আপনার শেষ উদাহরণের জন্য চিত্রটি ভুলে গেছেন।
ক্যালভিনের শখ 21

@ ক্যালভিনের শখগুলি এলোমেলো রঙ নির্বাচন পছন্দ করে ... মনে হচ্ছে আমার কম্পিউটারে বেগুনি রঙের একটি ছদ্মবেশ রয়েছে: পি। ওফ আমি তৃতীয় উদাহরণটি ভুলে যাইনি ... উত্পন্ন এবং আপডেট করবে।
মোগি

12

এই চ্যালেঞ্জ আশ্চর্যজনকভাবে কঠিন। আমি পাইগাম ব্যবহার করে পাইথনে একটি মানচিত্র জেনারেটর লিখেছিলাম। প্রোগ্রামটি রঙের অঞ্চলটিকে ফাঁকা জায়গায় উন্নত করে এবং এমন চিত্রের ফলস্বরূপ মানচিত্রের মতো দেখতে (যদি আপনি স্কুইচ্ট করেন)।

আমার অ্যালগরিদম সবসময় দেশগুলিকে সম্পূর্ণ করে না কারণ বাকী অংশে পর্যাপ্ত জায়গা নাও থাকতে পারে তবে আমি ভেবেছিলাম এটির একটি আকর্ষণীয় প্রভাব হয়েছে এবং আমি এর জন্য আর সময় ব্যয় করব না। অদ্ভুত নীল রঙের প্যাচগুলি বড় হ্রদ হিসাবে বিবেচনা করা যেতে পারে, এবং দেশগুলির মধ্যে বর্ণালী নীল বৈশিষ্ট্যগুলি হ'ল নদী যা সীমানা চিহ্নিত করে (এটি একটি বৈশিষ্ট্য, কোনও বাগ নয়!)।

সুপার শেফুইনের সাথে তুলনা করার জন্য, আমি তাদের প্যারামিটার উদাহরণ ব্যবহার করেছি।

প্যারামিটার: 380 260 233 420 1300 3511 4772 5089 9507 22107 25117 26744

স্ট্যান্ডার্ড পরীক্ষা

প্যারামিটার: 380 260 8 5 6 7 8 4 5 6 7 9 4 6 9 5 8 8 7 5

উদাহরণ 2

ক্যামলোটের অন্ধকার বয়স (213 307 1 1 1)

উদাহরণ 3

আমার আরও বড় উদাহরণ: (640 480 6 1 7 2 9 3 4 5 6 1 9 8 7 44 3 1 9 4 5 6 7 2 3 4 9 3 4 5 9 8 7 5 6 1 2 1 2 1 2 6 7 8 9 63 3)

পূর্ব ইউরোপের বৈশিষ্ট্যযুক্ত আমার আরও বড় উদাহরণ?

এই উদাহরণটি কিছুটা পূর্ব ইউরোপের মতো দেখাচ্ছে?

আরও দেশগুলির সাথে একটি উদাহরণ: 640 480 6 1 7 2 9 3 4 5 6 1 9 8 7 44 3 1 9 4 5 6 7 2 3 4 9 3 4 5 9 8 7 5 6 1 2 1 2 1 2 6 7 8 9 63 5 33 11 88 2 7 9 5 6 2 5 7

মেলো রঙযুক্ত আরও দেশ

আমি আরও উদাহরণস্বরূপ colors = [(80+ri(100), 80+ri(100), 80+ri(100)) for c in counts](এবং মানচিত্রের মতো) পরিসীমা পেতে এই উদাহরণ দিয়ে রঙ জেনারেটরটি পরিবর্তন করেছি ।

পাইথন কোড:

from pygame.locals import *
import pygame, sys, random

BACK = (0,0,200)
ORTH = [(-1,0), (1,0), (0,-1), (0,1)]
PI = 3.141592

random.seed(9999)
def ri(n):
    return int(random.random() * n)

args = [int(v) for v in sys.argv[1:]]
W, H = args[:2]
shares = sorted(args[2:])
ratio = float(W*H) / sum(shares)
counts = [int(s*ratio) for s in shares]
for i in range(W*H - sum(counts)):
    counts[i] += 1

colors = [(2+ri(250), 2+ri(250), 2+ri(250)) for c in counts]
countries = range(len(counts))
random.shuffle(countries)

border = ( set((x,y) for x in (0,W-1) for y in range(H)) |
            set((x,y) for x in range(W) for y in (0,H-1)) )

screen = pygame.display.set_mode((W,H))
screen.fill(BACK)
pix = screen.set_at
def look(p):
    if 0 <= p[0] < W and 0 <= p[1] < H:
        return screen.get_at(p)
    else:
        return None

clock = pygame.time.Clock()

while True:
    dt = clock.tick(300)
    pygame.display.flip()

    if countries:
        country = countries.pop()
        color = colors[country]
        if not countries:
            color = (20,20,200)  # last fill color to be water
        count = counts[country]
        frontier = set()
        plotted = 0
        loc = border.pop()
        while plotted < count:
            pix(loc, color)
            if plotted % 50 == 0:
                pygame.display.flip()
            plotted += 1
            direc = [(loc[0]+dx, loc[1]+dy) for dx,dy in ORTH]
            for dloc in direc:
                if look(dloc) == BACK:
                    frontier.add(dloc)
            border |= frontier
            if frontier:
                loc = frontier.pop()
                border.discard(loc)
            else:
                print 'Country %s cover %u of %u' % (
                    shares[country], plotted, count)
                break
        if not countries:
            fn = 'mapper%u.png' % ri(1000)
            pygame.image.save(screen, fn)

    for event in pygame.event.get():
        if event.type == QUIT: sys.exit(0)
        if not hasattr(event, 'key'): continue
        if event.key == K_ESCAPE: sys.exit(0)

নিশ্চিত নয় যে এটি নিয়মকে সম্মান করে "any pixel in the region can be reached from any other by staying within the region and only moving orthogonally"। আমি বিচ্ছিন্ন পিক্সেল দেখতে পাচ্ছি?
Arnaud

অ্যালগরিদম সেই ধারাবাহিকতা নিয়মটি পূরণ করে যা আপনি উদ্ধৃত করেছেন তবে অন্য ক্ষেত্রে ব্যর্থ। এই বিচ্ছিন্ন পিক্সেলগুলি সেই দেশে "গর্ত" যেখানে পটভূমিটি দেখায়। এই প্রভাবের কারণে এবং অন্যান্য প্রতিটি দেশে বেশ কয়েকটি দেশ তাদের সমস্ত পিক্সেল উত্পন্ন করতে পারে না। কিছু দেশ তাদের বেশিরভাগ পিক্সেল মিস করে । এটি নির্দিষ্ট হিসাবে সমস্ত বিধি পূরণ করে না তবে আমি ভেবেছিলাম এটি একটি আকর্ষণীয় ফলাফল। একটি সঠিক মানচিত্র তৈরি করতে অ্যালগরিদমের জন্য গুরুত্বপূর্ণ কাজের প্রয়োজন হবে।
লজিক নাইট 11

এটি প্রযুক্তিগতভাবে নিয়মের বিপরীতে তবে এটি এখনও দুর্দান্ত। আমি প্রশ্ন করার পরেও এ জাতীয় কিছু চেষ্টা করেছি এবং একই রকম সমস্যা রয়েছে। আমি ভেবেছি তার চেয়েও জটিল!
ক্যালভিনের

8

আসুন অলস হতে হবে এবং এই প্রশ্ন থেকে আমার উত্তর অভিযোজিত !

  1. অ্যালগরিদম উপরের বাম কোণ থেকে শুরু করে একটি "সাপের পাথ" গণনা করে যা পুরো আয়তক্ষেত্রটি পূর্ণ করে। সাপটি কেবল উপরে, নীচে, বাম দিকে, ডানদিকে যেতে পারে।

  2. সাপের পথ অনুসরণ করা হয় এবং প্রথম রঙ, তারপর দ্বিতীয় রঙ ইত্যাদি দিয়ে পূর্ণ হয় ... রঙের শতাংশ বিবেচনায় নেওয়া

  3. এই অ্যালগরিদম প্রচুর সরল রেখা উত্পাদন করে; এটির উন্নতি করতে, আমি তাদের সনাক্ত করি এবং তাদের "তরঙ্গ" দিয়ে প্রতিস্থাপন করি যা একই পরিমাণ পিক্সেল রাখে।

প্যারামিটার: 380 260 233 420 1300 3511 4772 5089 9507 22107 25117 26744

এখানে চিত্র বর্ণনা লিখুন

প্যারামিটার: 380 260 8 5 6 7 8 4 5 6 7 9 4 6 9 5 8 8 7 5

এখানে চিত্র বর্ণনা লিখুন

ক্যামলোটের অন্ধকার বয়স (213 307 1 1 1)

এখানে চিত্র বর্ণনা লিখুন

কোড:

package map;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Random;

import javax.imageio.ImageIO;


public class GenMap2 {

    private enum State { NO, YES, SHIFT };
    public final static int TOP = 1, BOTTOM = 2, LEFT = 4, RIGHT = 8;
    enum Action { ADD_LINE_TOP, ADD_LINE_LEFT, DOUBLE_SIZE, CREATE};

    public static void main(String[] args) throws IOException {

        int w = Integer.parseInt(args[0]), h = Integer.parseInt(args[1]);
        List<Integer> areas = new ArrayList<Integer>();
        int total = 0;
        for (int i = 2; i < args.length; i++) {
            int area = Integer.parseInt(args[i]);
            areas.add(area);
            total += area;
        }
        Collections.sort(areas);
        Collections.reverse(areas);
        int [][] tab = build(w, h);

        BufferedImage dest = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
        int [] black = {0, 0, 0};
        for (int j = 0; j < dest.getHeight(); j++) {
            for (int i = 0; i < dest.getWidth(); i++) {
                dest.getRaster().setPixel(i, j, black);
            }
        }

        int x = 0, y = -1;
        int go = BOTTOM, previous = BOTTOM;

        List<Color> colors = new ArrayList<Color>();
        Random rand = new Random(0); // prog must be deterministic
        while (colors.size() < areas.size()) {
            Color c = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
            boolean ok = true;
            for (Color existing : colors) {
                if (existing.equals(c)) {
                    ok = false;
                    break;
                }
            }
            if (ok) {
                colors.add(c);
            }
        }

        int [][] map = new int[w][h];
        int cpt = 0;
        while (true) {
            if (go == BOTTOM) y++;
            if (go == TOP) y--;
            if (go == LEFT) x--;
            if (go == RIGHT) x++;

            int tmp = (int)(((long)cpt) * total / (w * h));
            int i = 0;
            for (i = 0; i < areas.size(); i++) {
                int area = areas.get(i);
                if (tmp < area) {
                    break;
                }
                tmp -= area;
            }

            map[x][y] = i;

            previous = go;

            go = -1;
            if ((tab[x][y] & TOP) != 0 && previous != BOTTOM) go = TOP;
            if ((tab[x][y] & BOTTOM) != 0 && previous != TOP) go = BOTTOM;
            if ((tab[x][y] & LEFT) != 0 && previous != RIGHT) go = LEFT;
            if ((tab[x][y] & RIGHT) != 0 && previous != LEFT) go = RIGHT;
            if (go == -1) break;
            cpt++;
        }

        String [] src0 = srcPattern(16);
        String [] repl0 = destPattern(16);
        while (findPattern(map, src0, Arrays.asList(repl0, flip(repl0)))){}
        while (findPattern(map, rotate(src0), Arrays.asList(rotate(repl0), rotate(flip(repl0))))){}
        String [] src1 = srcPattern(8);
        String [] repl1 = destPattern(8);
        while (findPattern(map, src1, Arrays.asList(repl1, flip(repl1)))){}
        while (findPattern(map, rotate(src1), Arrays.asList(rotate(repl1), rotate(flip(repl1))))){}
        String [] src2 = srcPattern(4);
        String [] repl2 = destPattern(4);
        while (findPattern(map, src2, Arrays.asList(repl2, flip(repl2)))){}
        while (findPattern(map, rotate(src2), Arrays.asList(rotate(repl2), rotate(flip(repl2))))){}


        for (y = 0; y < h; y++) {
            for (x = 0; x < w; x++) {
                Color c = colors.get(map[x][y]);
                dest.getRaster().setPixel(x, y, new int[] {c.getRed(), c.getGreen(), c.getBlue()});
            }
        }

        ImageIO.write(dest, "png", new FileOutputStream("map.png"));
    }

    private static Random randPat = new Random(0);


    private static String [] srcPattern(int size) {
        String [] ret = new String[size*2];
        for (int i = 0; i < size*2; i++) {
            ret[i] = "";
            for (int j = 0; j < size*4; j++) {
                ret[i] += i < size ? "1" : "2";
            }
        }
        return ret;
    }

    private static String [] destPattern(int size) {
        String [] ret = new String[size*2];
        for (int i = 0; i < size*2; i++) {
            ret[i] = "";
            for (int j = 0; j < size*2; j++) {
                //int target = (int)((1 + Math.sin(j * Math.PI * .5/ size) * .4) * size);
                int target = (int)((1 + (Math.cos(j * Math.PI/ size) - 1) * .2) * size);
                ret[i] += (i < target)  ? '1' : '2';
            }
        }

        for (int i = 0; i < size*2; i++) {
            for (int j = 0; j < size*2; j++) {
                ret[i] += ret[size*2 - 1 - i].charAt(size*2 - 1 - j) == '1' ? '2' : '1';
            }
        }
        return ret;
    }
    private static String [] flip(String [] pat) {
        String [] ret = new String[pat.length];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = new StringBuilder(pat[i]).reverse().toString();

        }
        return ret;
    }
    private static String [] rotate(String [] pat) {
        String [] ret = new String[pat[0].length()];
        for (int i = 0; i < ret.length; i++) {
            ret[i] = "";
            for (int j = 0; j < pat.length; j++) {
                ret[i] += pat[j].charAt(i);
            }
        }
        return ret;
    }

    private static boolean findPattern(int [][] map, String [] src, List<String []> dest) {
        for (int y = 0; y < map[0].length - src.length; y++) {
            for (int x = 0; x < map.length - src[0].length(); x++) {
                int c1 = -1, c2 = -1;
                boolean wrong = false;
                for (int y1 = 0; y1 < src.length; y1++) {
                    for (int x1 = 0; x1 < src[0].length(); x1++) {
                        if (src[y1].charAt(x1) == '1') {
                            if (c1 == -1) {
                                c1 = map[x+x1][y+y1];
                            } else {
                                if (c1 != map[x+x1][y+y1]) {
                                    wrong = true;
                                }
                            }
                        }
                        if (src[y1].charAt(x1) == '2') {
                            if (c2 == -1) {
                                c2 = map[x+x1][y+y1];
                            } else {
                                if (c2 != map[x+x1][y+y1]) {
                                    wrong = true;
                                }
                            }
                        }
                        if (c1 != -1 && c1 == c2) wrong = true;
                        if (wrong) break;
                    }
                    if (wrong) break;
                }
                if (!wrong) {
                    System.out.println("Found match at " + x + " " + y);
                    String [] repl = dest.get(randPat.nextInt(dest.size()));
                    for (int y1 = 0; y1 < src.length; y1++) {
                        for (int x1 = 0; x1 < src[0].length(); x1++) {
                            map[x+x1][y+y1] = repl[y1].charAt(x1) == '1' ? c1 : c2;

                        }
                    }
                    return true;
                }
            }
        }           
        return false;
    }

    public static int [][] build(int width, int height) {
        List<Action> actions = new ArrayList<Action>();
        while (height>1 && width>1) {
            if (height % 2 == 1) {
                height--;
                actions.add(Action.ADD_LINE_TOP);
            }
            if (width % 2 == 1) {
                width--;                
                actions.add(Action.ADD_LINE_LEFT);
            }
            if (height%2 == 0 && width%2 == 0) {
                actions.add(Action.DOUBLE_SIZE);
                height /= 2;
                width /= 2;
            }
        }
        actions.add(Action.CREATE);
        Collections.reverse(actions);
        int [][] tab = null;
        for (Action action : actions) {
            if (action == Action.CREATE) {
                tab = new int[width][height];
                if (height >= width) {
                    for (int i = 0; i < height-1; i++) {
                        tab[0][i] = TOP|BOTTOM;
                    }
                    tab[0][height-1] = TOP;
                } else {
                    tab[0][0] = TOP|RIGHT;
                    for (int i = 1; i < width-1; i++) {
                        tab[i][0] = RIGHT|LEFT;
                    }
                    tab[width-1][0] = LEFT;

                }
            }
            if (action == Action.DOUBLE_SIZE) {
                tab = doubleTab(tab);
            }
            if (action == Action.ADD_LINE_TOP) {
                int [][] tab2 = new int[tab.length][tab[0].length+1];
                for (int i = 0; i < tab.length; i++) {
                    for (int j = 0; j < tab[0].length; j++) {
                        tab2[i][j+1] = tab[i][j];
                    }
                }
                tab2[0][0] = BOTTOM|RIGHT;
                for (int i = 1; i < tab.length-1; i++) {
                    tab2[i][0] = RIGHT|LEFT;
                }
                tab2[tab.length-1][0] = TOP|LEFT;
                mirror(tab2);
                tab = tab2;
            }
            if (action == Action.ADD_LINE_LEFT) {
                int [][] tab2 = new int[tab.length+1][tab[0].length];
                for (int i = 0; i < tab.length; i++) {
                    for (int j = 0; j < tab[0].length; j++) {
                        tab2[i+1][j] = tab[i][j];
                    }
                }
                tab2[0][0] = BOTTOM|RIGHT;
                tab2[1][0] |= LEFT;
                tab2[1][0] -= TOP;
                for (int i = 1; i < tab[0].length-1; i++) {
                    tab2[0][i] = TOP|BOTTOM;
                }
                tab2[0][tab[0].length-1] = TOP|BOTTOM;
                flip(tab2);
                tab = tab2;
            }

        }

        return tab;
    }

    private static void mirror(int [][] tab) {
        for (int i = 0; i < tab.length/2; i++) {
            for (int j = 0; j < tab[0].length; j++) {
                int tmp = tab[tab.length - 1 - i][j];
                tab[tab.length - 1 - i][j] = tab[i][j];
                tab[i][j] = tmp;
            }
        }
        for (int i = 0; i < tab.length; i++) {
            for (int j = 0; j < tab[0].length; j++) {
                if ((tab[i][j] & LEFT)!=0 && (tab[i][j] & RIGHT)==0) {
                    tab[i][j] -= LEFT; tab[i][j] |= RIGHT;
                } else if ((tab[i][j] & RIGHT)!=0 && (tab[i][j] & LEFT)==0) {
                    tab[i][j] -= RIGHT; tab[i][j] |= LEFT;
                }
            }
        }
    }

    private static void flip(int [][] tab) {
        for (int i = 0; i < tab.length; i++) {
            for (int j = 0; j < tab[0].length/2; j++) {
                int tmp = tab[i][tab[0].length - 1 - j];
                tab[i][tab[0].length - 1 - j] = tab[i][j];
                tab[i][j] = tmp;
            }
        }
        for (int i = 0; i < tab.length; i++) {
            for (int j = 0; j < tab[0].length; j++) {
                if ((tab[i][j] & TOP)!=0 && (tab[i][j] & BOTTOM)==0) {
                    tab[i][j] -= TOP; tab[i][j] |= BOTTOM;
                } else if ((tab[i][j] & BOTTOM)!=0 && (tab[i][j] & TOP)==0) {
                    tab[i][j] -= BOTTOM; tab[i][j] |= TOP;
                }
            }
        }
    }


    public static int [][] doubleTab(int [][] tab) {
        boolean [][] shiftTop = new boolean[tab.length][], 
                shiftLeft = new boolean[tab.length][],
                shiftBottom = new boolean[tab.length][],
                shiftRight = new boolean[tab.length][];
        for (int i = 0; i < tab.length; i++) {
            shiftTop[i] = new boolean[tab[i].length];
            shiftLeft[i] = new boolean[tab[i].length];
            shiftBottom[i] = new boolean[tab[i].length];
            shiftRight[i] = new boolean[tab[i].length];
        }

        int x = 0, y = -1;
        for (int i = 0; i < tab.length; i++) {
            if ((tab[i][0] & TOP) != 0) {
                x = i;
            }
        }
        int go = BOTTOM, previous = BOTTOM;
        boolean init = false;
        while (true) {
            if (go == BOTTOM) y++;
            if (go == TOP) y--;
            if (go == LEFT) x--;
            if (go == RIGHT) x++;

            previous = go;

            go = -1;
            if ((tab[x][y] & TOP) != 0 && previous != BOTTOM) go = TOP;
            if ((tab[x][y] & BOTTOM) != 0 && previous != TOP) go = BOTTOM;
            if ((tab[x][y] & LEFT) != 0 && previous != RIGHT) go = LEFT;
            if ((tab[x][y] & RIGHT) != 0 && previous != LEFT) go = RIGHT;
            if (previous == BOTTOM) {
                shiftTop[x][y] = y==0 ? init : shiftBottom[x][y-1];
            }
            if (previous == TOP) {
                shiftBottom[x][y] = shiftTop[x][y+1];
            }
            if (previous == RIGHT) {
                shiftLeft[x][y] = shiftRight[x-1][y];
            }
            if (previous == LEFT) {
                shiftRight[x][y] = shiftLeft[x+1][y];       
            }
            if (go == -1) break;

            if (previous == BOTTOM && go == LEFT) {
                shiftLeft[x][y] = !shiftTop[x][y];
            }
            if (previous == BOTTOM && go == RIGHT) {
                shiftRight[x][y] = shiftTop[x][y];
            }
            if (previous == BOTTOM && go == BOTTOM) {
                shiftBottom[x][y] = shiftTop[x][y];
            }


            if (previous == TOP && go == LEFT) {
                shiftLeft[x][y] = shiftBottom[x][y];
            }
            if (previous == TOP && go == RIGHT) {
                shiftRight[x][y] = !shiftBottom[x][y];
            }
            if (previous == TOP && go == TOP) {
                shiftTop[x][y] = shiftBottom[x][y];
            }

            if (previous == RIGHT && go == TOP) {
                shiftTop[x][y] = !shiftLeft[x][y];
            }
            if (previous == RIGHT && go == BOTTOM) {
                shiftBottom[x][y] = shiftLeft[x][y];
            }
            if (previous == RIGHT && go == RIGHT) {
                shiftRight[x][y] = shiftLeft[x][y];
            }

            if (previous == LEFT && go == TOP) {
                shiftTop[x][y] = shiftRight[x][y];
            }
            if (previous == LEFT && go == BOTTOM) {
                shiftBottom[x][y] = !shiftRight[x][y];
            }
            if (previous == LEFT && go == LEFT) {
                shiftLeft[x][y] = shiftRight[x][y];
            }
        }
        int [][] tab2 = new int[tab.length * 2][];
        for (int i = 0; i < tab2.length; i++) {
            tab2[i] = new int[tab[0].length * 2];
        }

        for (int i = 0; i < tab.length; i++) {
            for (int j = 0; j < tab[0].length; j++) {
                State left = State.NO, right = State.NO, top = State.NO, bottom = State.NO; 
                if ((tab[i][j] & LEFT) != 0) {
                    left = shiftLeft[i][j] ? State.SHIFT : State.YES;
                }
                if ((tab[i][j] & TOP) != 0) {
                    top = shiftTop[i][j] ? State.SHIFT : State.YES;
                }
                if ((tab[i][j] & RIGHT) != 0) {
                    right = shiftRight[i][j] ? State.SHIFT : State.YES;
                }
                if ((tab[i][j] & BOTTOM) != 0) {
                    bottom = shiftBottom[i][j] ? State.SHIFT : State.YES;
                }

                int [] comp = compute(left, top, right, bottom);
                tab2[i*2][j*2] = comp[0];
                tab2[i*2+1][j*2] = comp[1];
                tab2[i*2][j*2+1] = comp[2];
                tab2[i*2+1][j*2+1] = comp[3];
            }
        }
        return tab2;
    }

    private static int [] compute(State left, State top, State right, State bottom) {
        //   |
        // --+
        //
        if (left == State.YES && top == State.SHIFT) {
            return new int[] {LEFT|BOTTOM, TOP|BOTTOM, TOP|RIGHT, TOP|LEFT};// "v^>^";
        }
        if (left == State.SHIFT && top == State.YES) {
            return new int[] {TOP|RIGHT, LEFT|BOTTOM, LEFT|RIGHT, LEFT|TOP}; //"^<>^";
        }
        //   
        // --+
        //   |
        if (left == State.YES && bottom == State.YES) {
            return new int[] {LEFT|RIGHT, LEFT|BOTTOM, RIGHT|BOTTOM, LEFT|TOP}; //">vv<";
        }
        if (left == State.SHIFT && bottom == State.SHIFT) {
            return new int[] {RIGHT|BOTTOM, LEFT|BOTTOM, LEFT|TOP, TOP|BOTTOM}; //">v^v";
        }
        //   |
        //   +--
        //
        if (right == State.SHIFT && top == State.SHIFT) {
            return new int [] {RIGHT|BOTTOM,LEFT|TOP,TOP|RIGHT, LEFT|RIGHT}; //" v<>>";
        }
        if (right == State.YES && top == State.YES) {
            return new int [] {TOP|BOTTOM,RIGHT|BOTTOM,TOP|RIGHT,TOP|LEFT}; //"v>>^";
        }
        //   
        //   +--
        //   |
        if (right == State.YES && bottom == State.SHIFT) {
            return new int [] {RIGHT|BOTTOM, LEFT|RIGHT, TOP|RIGHT, LEFT|BOTTOM}; //"v<>v";
        }
        if (right == State.SHIFT && bottom == State.YES) {
            return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, TOP|BOTTOM, RIGHT|TOP}; //"v<v^";
        }
        //   
        // --+--
        //   
        if (right == State.YES && left == State.YES) {
            return new int [] {LEFT|BOTTOM, RIGHT|BOTTOM, TOP|RIGHT, LEFT|TOP}; 
        }
        if (right == State.SHIFT && left == State.SHIFT) {
            return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, LEFT|TOP, RIGHT|TOP}; 
        }
        //   |
        //   +
        //   |
        if (top == State.YES && bottom == State.YES) {
            return new int [] {TOP|RIGHT, LEFT|BOTTOM, BOTTOM|RIGHT, LEFT|TOP}; 
        }
        if (top == State.SHIFT && bottom == State.SHIFT) {
            return new int [] {RIGHT|BOTTOM, LEFT|TOP, RIGHT|TOP, LEFT|BOTTOM}; 
        }
        //
        //   +--
        //
        if (right == State.YES && bottom == State.NO && left == State.NO && top == State.NO) {
            return new int [] {BOTTOM, RIGHT|BOTTOM, TOP|RIGHT, LEFT|TOP}; 
        }
        if (right == State.SHIFT && bottom == State.NO && left == State.NO && top == State.NO) {
            return new int [] {RIGHT|BOTTOM, LEFT|BOTTOM, TOP, RIGHT|TOP}; 
        }

        //   |
        //   +
        //
        if (top == State.YES && bottom == State.NO && left == State.NO && right == State.NO) {
            return new int [] {TOP|RIGHT, LEFT|BOTTOM, RIGHT, LEFT|TOP}; 
        }
        if (top == State.SHIFT && bottom == State.NO && left == State.NO && right == State.NO) {
            return new int [] {BOTTOM|RIGHT, LEFT|TOP, TOP|RIGHT, LEFT}; 
        }
        //   
        //   +
        //   |
        if (bottom == State.YES && top == State.NO && left == State.NO && right == State.NO) {
            return new int [] {RIGHT, LEFT|BOTTOM, BOTTOM|RIGHT, LEFT|TOP}; 
        }
        if (bottom == State.SHIFT && top == State.NO && left == State.NO && right == State.NO) {
            return new int [] {BOTTOM|RIGHT, LEFT, TOP|RIGHT, LEFT|BOTTOM}; 
        }
        //
        // --+
        //
        if (left == State.YES && bottom == State.NO && right == State.NO && top == State.NO) {
            return new int [] {LEFT|BOTTOM, BOTTOM, TOP|RIGHT, LEFT|TOP}; 
        }
        if (left == State.SHIFT && bottom == State.NO && right == State.NO && top == State.NO) {
            return new int [] {BOTTOM|RIGHT, LEFT|BOTTOM, LEFT|TOP, TOP}; 
        }
        return null;
    }
}

1
আমার দৃষ্টিতে এগুলি খুব বাস্তববাদী মনে হয় না। বেশিরভাগ সংখ্যক সরলরেখার কারণেই ...
বিটা ডেকে

2
@ বেটাডেচে যেহেতু ওপি "যে কোনও স্কেল" নির্দিষ্ট করে, তাই এটিকে কোনও রাষ্ট্র বা জাতির অন্তর্গত হিসাবে কল্পনা করুন। তারপরে আপনি এটি খুব স্কোয়ারড-অফ, তবুও বাস্তববাদী হতে পারেন, অনেকটা নেব্রাসকার কাউন্টি মানচিত্রের মতো
Geobits

1
@ সোজা লাইনগুলি সংশোধন করার জন্য আমি কয়েকটি "তরঙ্গ" যুক্ত করেছি।
Arnaud

@ βετѧΛєҫαγ এটি বাস্তবসম্মত বলে মনে হয় না, তবে মার্কিন যুক্তরাষ্ট্র এবং কানাডার সীমান্তের দিকে নজর রাখে, বেশিরভাগ আফ্রিকার দেশগুলির মধ্যে কিছু সীমানা সমান এটি বেশ কয়েকটি সরল রেখা থেকে তৈরি।
ব্যবহারকারী 902383
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.