Random Connected Area - DFS

https://xcoder.in/2018/04/02/random-connected-area/#DFS

by XadillaX

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/fbbk-json/1.1.1/fjson.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
<input id="length" placeholder="宽高" />
<input id="need-area" placeholder="填充面积" />
<button id="gen">生成</button>
<br />
<canvas id="cvs"></canvas><br /><br />

<img style="display: none;" id="tile" src="http://xcoder-7niu.nbut.ac.cn/basictiles.png" />

CSS

body {
    background: #20262E;
    padding: 20px;
    font-family: Helvetica;
}

#banner-message {
    background: #fff;
    border-radius: 4px;
    padding: 20px;
    font-size: 25px;
    text-align: center;
    transition: all 0.2s;
    margin: 0 auto;
    width: 300px;
}

button {
    background: #0084ff;
    border: none;
    border-radius: 5px;
    padding: 8px 14px;
    font-size: 15px;
    color: #fff;
}

#banner-message.alt {
    background: #0084ff;
    color: #fff;
    margin-top: 40px;
    width: 200px;
}

#banner-message.alt button {
    background: #fff;
    color: #000;
}

JavaScript

class Filler {
    constructor(length, needArea) {
        this.length = length;
        this.needArea = needArea;
    }

    _init() {
        this.map = [];
        this.count = 0;
        for (let i = 0; i < this.length; i++) {
            let row = [];
            for (let j = 0; j < this.length; j++) row.push(".");
            this.map.push(row);
        }
    }

    fill(x, y) {
        const needInit = !arguments[2];
        if (needInit) this._init();

        if (this.map[x][y] === "x") return;

        this.count++;
        this.map[x][y] = "x";

        if (this.count === this.needArea) return Object.assign([], this.map);

        const dirs = _.shuffle([
            [0, 1],
            [0, -1],
            [1, 0],
            [-1, 0]
        ]);
        for (let i = 0; i < 4; i++) {
            const dir = dirs[i];
            let newX = x + dir[0];
            let newY = y + dir[1];

            {
                if (newX < 0 || newX >= this.length || newY < 0 || newY >= this.length) continue;

                // if(newX < 0) newX = this.length - 1;
                // if(newX >= this.length) newX = 0;
                // if(newY < 0) newY = this.length - 1;
                // if(newY >= this.length) newY = 0;
            }

            const ret = this.fill(newX, newY, true);
            if (ret) return ret;
        }

        // 抛弃状态还原就把下面两件代码注释掉
        this.count--;
        this.map[x][y] = ".";
    }
}

function random(max) {
    return Math.round(Math.random() * max);
}

let interval;
let plan = "a";

function draw(map) {
    const c = document.getElementById("cvs");
    const image = document.getElementById("tile");
    const ctx = c.getContext("2d");

    $(c).attr({
        width: 16 * map.length,
        height: 16 * map.length
    });

    for (let i = 0; i < map.length; i++) {
        for (let j = 0; j < map.length; j++) {
            const tileStart = {
                x: map[i][j] === "x" ? 48 : 80,
                y: 16
            };

 ...