-
Notifications
You must be signed in to change notification settings - Fork 0
/
map3.js
181 lines (169 loc) · 6.68 KB
/
map3.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
const boardInit = [
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
['O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O','O'],
]
// clone array so i don't lose a reference to the original one (for testing more than once)
var board = boardInit.map(function(arr) {
return arr.slice();
});
/* const board = [
['O','O','O','O','O'],
['O','O','O','O','O'],
['O','O','O','O','O'],
['O','O','O','O','O'],
['O','O','O','O','O'],
]; */
const maxIndex = board.length - 1;
let movesLeft = 9;
let minimum = movesLeft;
let biggestIndex = 0;
const top = ({x, y}) => ({x: x-1, y});
const right = ({x, y}) => ({x, y: y+1});
const left = ({x, y}) => ({x, y: y-1});
const bottom = ({x, y}) => ({x: x+1, y});
// TODO simple testind for un-odd boards (it's 2 am and i need to sleep)
const center = () => ({x: maxIndex/2, y: maxIndex/2});
const rand = () => Boolean(Math.round(Math.random() * 2));
function valid({x, y}) {
if(x < 0 || x > maxIndex || y < 0 || y > maxIndex) {
return false;
}
if(board[x][y] !== 'O'){
return false;
}
return {x,y};
}
// random the array to get random initial nodes (it can start in any direction)
function shuffleArray(array) {
// Durstenfeld shuffle
// https://en.wikipedia.org/wiki/Fisher–Yates_shuffle#The_modern_algorithm
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
function getMoves(from, moves) {
let available = ['TOP', 'RIGHT', 'BOTTOM', 'LEFT'];
// remove the ability for nodes to trackback
switch(from) {
case 'TOP':
available.splice(2, 1); // remove bottom :(
break;
case 'RIGHT':
available.splice(3, 1); // remove left
break;
case 'BOTTOM':
available.splice(0, 1); // remove up
break;
case 'LEFT':
available.splice(1, 1); // remove right
break;
}
const move = [];
// run to the number of available moves and set random movements;
for(let i = 0; i < moves; i++) {
const randd = Math.floor(Math.random() * available.length);
move.push(available[randd]);
// remove selected move so it doesn't repeat and i get more corridors
available.splice(randd, 1);
}
return shuffleArray(move);
}
let lastFilled = [];
function fill({x, y}, from, index = 0) {
// id valid, has moves left, line is not bigger than half of the max
if(valid({x,y}) && movesLeft && index <= minimum){
//board[x][y] = {TOP: '^', RIGHT: '>', LEFT: '<', BOTTOM: '_', CENTER: 'X'}[from]; // print last move in cell
board[x][y] = '_'; // print a simple _
//board[x][y] = from === 'CENTER' ? 'X' : '_'; // print a simple _ except when its the center where it will print a X
//board[x][y] = index; // print index of the line
lastFilled.push({x,y, i: index});
movesLeft--; // remove one from the global max moves
move = getMoves(from, from === 'CENTER' ? 4 : 1); // all nodes can move one except the center that can create the 4 initial nodes
move.forEach((m) => {
switch(m) {
case 'TOP':
fill(top({x,y}), 'TOP', index + 1);
break;
case 'RIGHT':
fill(right({x,y}), 'RIGHT', index + 1);
break;
case 'BOTTOM':
fill(bottom({x,y}), 'BOTTOM', index + 1);
break;
case 'LEFT':
fill(left({x,y}), 'LEFT', index + 1);
break;
}
});
//debug
if(index > biggestIndex) {
biggestIndex = index;
}
}
}
function fillMinimum() {
lastFilled.reverse();
for(let node of lastFilled) {
if(!node){
return;
}
const x = node.x;
const y = node.y;
let area = [
valid(top({x,y})),
valid(right({x,y})),
valid(bottom({x,y})),
valid(left({x,y}))];
area = shuffleArray(area);
for(let move of area) {
if(move) {
return fill(move, 'CENTER');
}
}
}
}
// test one
/* console.time("runTime");
fill(center(), 'CENTER');
console.timeEnd("runTime");
console.log(`Moves Left: ${movesLeft}\nBiggest Line: ${biggestIndex}`);
console.log(board.map((l) => l.join('|'))); */
// test multiple
for(_ in '_'.repeat(20)) {
fill(center(), 'CENTER');
if (movesLeft && movesLeft > minimum) {
do{
fillMinimum();
} while(movesLeft > minimum);
}
console.log(`Left: ${movesLeft}\nBiggest Line: ${biggestIndex}`)
console.log(board.map((l) => l.join('|')));
var board = boardInit.map(function(arr) {
return arr.slice();
});
movesLeft = 20;
biggestIndex = 0;
}