-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathghost-legs.js
155 lines (136 loc) Β· 3.7 KB
/
ghost-legs.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
let columns; // # of columns
let rows; // # of rows
// cells: 1 dimensional array to store swap information
// index sequence: top-to-down first, then left-to-right
// each cell represents border top and border left
// '-' to denote swap at top, undefined to denote without swap
let cells;
let heads; // thead text
let feet; // tfoot text
const CELL_SWAP = '-';
const CELL_DEFAULT = undefined;
function reset() {
columns = 4;
rows = 10;
cells = Array(columns * rows).fill(CELL_DEFAULT);
heads = Array(columns).fill("");
feet = Array(columns).fill("");
}
function getColumns() {
return columns;
}
function getRows() {
return rows;
}
function addSwap(col, row) {
checkAddSwap(col, row);
const index = col * rows + row;
cells[index] = CELL_SWAP;
}
function removeSwap(col, row) {
if (col < 0 || col >= columns - 1) {
throw new Error("invalid col");
}
if (row < 0 || row >= rows) {
throw new Error("invalid row");
}
cells[col * rows + row] = CELL_DEFAULT;
}
function checkAddSwap(col, row) {
if (col < 0 || col >= columns - 1) {
throw new Error("invalid col");
}
if (row < 0 || row >= rows) {
throw new Error("invalid row");
}
const index = col * rows + row;
if (index - rows >= 0 && cells[index - rows] == CELL_SWAP) {
throw new Error("invalid swap position");
}
if (index + rows < columns * rows && cells[index + rows] == CELL_SWAP) {
throw new Error("invalid swap position");
}
}
function addColumn() {
columns += 1;
heads.push("");
cells.push(...Array(rows).fill(CELL_DEFAULT));
feet.push("");
}
// constant to denote running route in a cell
const ROUTE_TOP = 'T';
const ROUTE_LEFT = 'L';
const ROUTE_TOP_LEFT = 'A';
function runRoute(col) {
if (col < 0 || col >= columns) {
throw new Error("invalid col");
}
const cellsRoute = Array(columns * rows).fill(CELL_DEFAULT);
let currentCol = col;
for (let r = 0; r < rows; r += 1) {
// check left swap
if (currentCol > 0) {
if (cells[(currentCol - 1) * rows + r] === CELL_SWAP) {
cellsRoute[(currentCol - 1) * rows + r] = ROUTE_TOP_LEFT;
currentCol = currentCol - 1
continue;
}
}
// check right swap
if (currentCol < columns - 1) {
if (cells[currentCol * rows + r] === CELL_SWAP) {
cellsRoute[currentCol * rows + r] = ROUTE_TOP;
cellsRoute[(currentCol + 1) * rows + r] = ROUTE_LEFT;
currentCol = currentCol + 1
continue;
}
}
// no swap
cellsRoute[currentCol * rows + r] = ROUTE_LEFT;
}
return { cellsRoute, colEnd: currentCol };
}
function shuffleHeads() {
for (let i = heads.length - 1; i > 0; i -= 1) {
const j = Math.floor(Math.random() * (i + 1));
[heads[i], heads[j]] = [heads[j], heads[i]];
}
}
function shuffleFeet() {
for (let i = feet.length - 1; i > 0; i -= 1) {
const j = Math.floor(Math.random() * (i + 1));
[feet[i], feet[j]] = [feet[j], feet[i]];
}
}
function setHead(col, value) {
if (col < 0 || col >= columns || col >= heads.length) {
throw new Error("invalid col");
}
heads[col] = value;
}
function setFoot(col, value) {
if (col < 0 || col >= columns || col >= feet.length) {
throw new Error("invalid col");
}
feet[col] = value;
}
reset();
export {
cells,
heads,
feet,
getColumns,
getRows,
reset,
addSwap,
removeSwap,
addColumn,
ROUTE_TOP,
ROUTE_LEFT,
ROUTE_TOP_LEFT,
runRoute,
shuffleHeads,
shuffleFeet,
setHead,
setFoot,
};