Random Connected Area - DFS real

https://xcoder.in/2018/04/02/random-connected-area/#我错了之『真·单连通区域』

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);
        }
    }
    
    willBreak(x, y) {
        let u = false, d = false, l = false, r = false;
        let lu = false, ld = false, ru = false, rd = false;
        if(x - 1 >= 0 && this.map[x - 1][y] === 'x') u = true;
        if(x + 1 < this.length && this.map[x + 1][y] === 'x') d = true;
        if(y - 1 >= 0 && this.map[x][y - 1] === 'x') l = true;
        if(y + 1 < this.length && this.map[x][y + 1] === 'x') r = true;
        if(x - 1 >= 0 && y - 1 >= 0 && this.map[x - 1][y - 1] === 'x') lu = true;
        if(x - 1 >= 0 && y + 1 < this.length && this.map[x - 1][y + 1] === 'x') ru = true;
        if(x + 1 < this.length && y - 1 >= 0 && this.map[x + 1][y - 1] === 'x') ld = true;
        if(x + 1 < this.length && y + 1 < this.length && this.map[x + 1][y + 1] === 'x') rd = true;
        
        // 情况 1
        if((l & r) ^ (u & d)) return true;
        
        // 情况 2
        if(l + r + u + d === 1) {
            if(l && (ru || rd)) return true;
            if(r && (lu || ld)) return true;
            if(u && (ld || rd)) return true;
            if(d && (lu || ru)) return true;
        }
        
        // 情况 3
        if(l + r + u + d === 2) {
            // 情况 1 已经被 return 了,所以相加为 2 的肯定是共享顶点
            if(l && u && rd) return true;
            if(l && d && ru) return true;
            if(r && u && ld) return true;
            if(r && d && lu) return true;
        }
        
        return false;
    }

    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...