Random Connected Area - Frenzied 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
'use strict';
const BFS_HOLE = Symbol('bfsHole');
const DELETE_FRONTIER = Symbol('deleteFrontier');
const GET_CONTIGUOUS = Symbol('getContiguous');
const IS_INSIDE_MAT = Symbol('isInsideMat');
const IS_FRONTIER = Symbol('isFrontier');
const IS_BREAKING_SIMPLY_CONNECTED = Symbol('isBreakingSymplyConnected');
const PUT_FRONTIER = Symbol('putFrontier');
const RANDOM_COOR = Symbol('randomCoor');
const RANDOM_FRONTIER = Symbol('randomFrontier');
const FILL_FAT = Symbol('fillFat');
const FILL_DFS = Symbol('fillDFS');
const UPDATE_FRONTIERS = Symbol('updateFrontier');
const FRONTIER_EXIST = Symbol('frontierExist');
function random(max) {
return Math.round(Math.random() * max);
}
class Filler4 {
constructor(length, needArea) {
this.length = length;
this.needArea = needArea;
}
[BFS_HOLE](start1, start2) {
const mat = _.cloneDeep(this.mat);
let which;
let q1 = [ start1 ];
let q2 = [ start2 ];
const fill1 = [];
const fill2 = [];
if(!this[IS_INSIDE_MAT](start1)) {
which = 2;
q1 = [];
}
if(!this[IS_INSIDE_MAT](start2)) {
which = 1;
q2 = [];
}
// 双队列 BFS,哪个先结束就哪个
while(true) {
// 执行队列 1
if(q1.length) {
const coor = q1.shift();
if(this[IS_INSIDE_MAT](coor) && mat[coor.x][coor.y] === '.') {
const x = coor.x, y = coor.y;
if(coor.x === 0 || coor.x === this.length - 1 || coor.y === 0 || coor.y === this.length - 1) {
// q1 在单连通区域之外,不需要继续搜索
q1 = [];
which = 2;
} else {
mat[coor.x][coor.y] = 'x';
fill1.push(coor);
q1.push({ x: x - 1, y });
q1.push({ x: x + 1, y });
q1.push({ x, y: y - 1 });
...