Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
mamayaya1
GitHub Repository: mamayaya1/game
Path: blob/main/projects/connect3/connect3.js
4626 views
1
const colours = ["red", "orange", "yellow", "dodgerblue", "limegreen", "darkorchid", "hotpink"],
2
shapes = ["minus", "circle", "triangle", "plus", "square", "hexagon", "dot"],
3
BOARD_SIZE = 8,
4
score = {
5
set(n) {
6
score.number = n;
7
squareElem.dataset.score = n;
8
},
9
add(n) {
10
this.set(n + this.number);
11
}
12
};
13
class Tile {
14
constructor(x, y, colour, entering = false) {
15
this.colour = -1;
16
17
this.element = document.createElement("span");
18
this.element.addEventListener("click", e => {
19
if (selectedTile === 'DONTSELECT');
20
else if (selectedTile) {
21
if (selectedTile.x === this.x && Math.abs(selectedTile.y - this.y) === 1
22
|| selectedTile.y === this.y && Math.abs(selectedTile.x - this.x) === 1) {
23
let lastPositions = {
24
me: [this.x, this.y],
25
selectedTile: [selectedTile.x, selectedTile.y, selectedTile.elem]
26
};
27
selectedTile.moveTileTo(this.x, this.y);
28
this.moveTo(selectedTile.x, selectedTile.y);
29
selectedTile = null;
30
31
if (!startMurderSpree(200)) {
32
selectedTile = 'DONTSELECT';
33
setTimeout(() => {
34
lastPositions.selectedTile[2].moveTo(lastPositions.selectedTile[0], lastPositions.selectedTile[1]);
35
this.moveTo(lastPositions.me[0], lastPositions.me[1]);
36
selectedTile = null;
37
}, 200);
38
}
39
return;
40
} else {
41
if (selectedTile.cancel() === this) return;
42
}
43
}
44
if (!selectedTile) {
45
this.element.classList.add("active");
46
selectedTile = {
47
x: this.x,
48
y: this.y,
49
moveTileTo: (x, y) => {
50
this.moveTo(x, y);
51
this.element.classList.remove("active");
52
},
53
cancel: () => {
54
this.element.classList.remove("active");
55
selectedTile = null;
56
return this;
57
},
58
elem: this
59
};
60
}
61
}, false);
62
63
switch (colour) {
64
case "bomb":
65
this.element.classList.add("bomb");
66
default:
67
this.element.classList.add(shapes[colour]);
68
this.element.style.backgroundColor = colours[colour];
69
this.colour = colour;
70
}
71
72
if (entering) this.element.classList.add("entering");
73
squareElem.appendChild(this.element);
74
75
this.x = x;
76
this.y = y;
77
this.moveTo(x, y);
78
}
79
remove(animate = true, addNewItem = true) {
80
if (animate) {
81
this.element.classList.add("exiting");
82
this.element.addEventListener("animationend", e => {
83
squareElem.removeChild(this.element);
84
}, false);
85
}
86
else squareElem.removeChild(this.element);
87
tileElems[this.y][this.x] = null, tiles[this.y][this.x] = null;
88
for (let tempY = this.y; tempY--;) tileElems[tempY][this.x].moveTo(this.x, tempY + 1);
89
if (addNewItem) {
90
new Tile(this.x, 0, Math.floor(Math.random() * colours.length), true);
91
}
92
if (selectedTile && selectedTile.elem === this) selectedTile = null;
93
}
94
moveTo(x, y) {
95
if (tileElems[this.y][this.x] === this) tileElems[this.y][this.x] = null, tiles[this.y][this.x] = null;
96
this.element.style.left = ((this.x = x) * 45 + 20) + "px";
97
this.element.style.top = ((this.y = y) * 45 + 20) + "px";
98
tileElems[y][x] = this, tiles[y][x] = this.colour;
99
}
100
}
101
function startMurderSpree(wasRightAfterTransition = false) {
102
let foundMatches,
103
combo = 0,
104
toRemove = [];
105
while ((foundMatches = checkForMatches(tiles)).length) {
106
for (let i = foundMatches.length; i--;) for (let j = foundMatches[i].length; j--;) {
107
let tile = tileElems[foundMatches[i][j][1]][foundMatches[i][j][0]];
108
if (!toRemove.includes(tile)) {
109
toRemove.push(tile);
110
tiles[foundMatches[i][j][1]][foundMatches[i][j][0]] = NaN;
111
}
112
}
113
combo++;
114
}
115
let killing = () => {
116
for (let i = toRemove.length; i--;) toRemove[i].remove();
117
score.add(toRemove.length * 100);
118
startMurderSpree(400);
119
};
120
if (combo !== 0) {
121
if (wasRightAfterTransition) setTimeout(killing, wasRightAfterTransition);
122
else killing();
123
}
124
return combo !== 0;
125
}
126
function checkForMatches(tiles) {
127
function getCoords(x, y, ywise = true, frontOffset = 0, sideOffset = 0) {
128
return [x + (ywise ? sideOffset : frontOffset), y + (ywise ? frontOffset : sideOffset)];
129
}
130
function getTile(coords) {
131
return tiles[coords[1]][coords[0]];
132
}
133
function areSameColour(tile1, tile2) { // -1 is wildcard; NaN is a unique tile
134
return tile1 === -1 || tile2 === -1 || tile1 === tile2;
135
}
136
function actuallyCheckForMatches(x, y, ywise) {
137
let coords = getCoords(x, y),
138
colour = getTile(coords),
139
matches = [coords],
140
frontCoord = ywise ? y : x,
141
sideCoord = ywise ? x : y;
142
for (let i = 1; i < 6 && frontCoord - i >= 0; i++) {
143
let coords = getCoords(x, y, ywise, -i);
144
if (areSameColour(colour, getTile(coords))) matches.push(coords);
145
else break;
146
}
147
if (matches.length >= 3) {
148
let actualMatches = [matches];
149
for (let i = matches.length; i--;) {
150
let sideMatches = [getCoords(x, y, ywise, -i)],
151
leftIsDone = false,
152
rightIsDone = false;
153
for (let j = 1; j < 6; j++) {
154
let leftCoords = getCoords(x, y, ywise, -i, -j),
155
rightCoords = getCoords(x, y, ywise, -i, j);
156
if (!leftIsDone && sideCoord - j >= 0 && areSameColour(colour, getTile(leftCoords))) sideMatches.push(leftCoords);
157
else leftIsDone = true;
158
if (!rightIsDone && sideCoord + j < 8 && areSameColour(colour, getTile(rightCoords))) sideMatches.push(rightCoords);
159
else rightIsDone = true;
160
if (leftIsDone && rightIsDone) break;
161
}
162
if (sideMatches.length >= 3) actualMatches.push(sideMatches);
163
}
164
return actualMatches;
165
}
166
return false;
167
}
168
for (let y = BOARD_SIZE; y--;) for (let x = BOARD_SIZE; x--;) {
169
if (y > 1) {
170
let matches = actuallyCheckForMatches(x, y, true);
171
if (matches) return matches;
172
}
173
if (x > 1) {
174
let matches = actuallyCheckForMatches(x, y, false);
175
if (matches) return matches;
176
}
177
}
178
return [];
179
}
180
let squareElem = document.createElement("div"),
181
tiles = [],
182
tileElems = [];
183
squareElem.classList.add("grid");
184
for (let y = 8; y--;) {
185
let row = [];
186
for (let x = 8; x--;) row.push(Math.floor(Math.random() * colours.length));
187
tiles.push(row);
188
}
189
let foundMatches;
190
while ((foundMatches = checkForMatches(tiles)).length) {
191
for (let i = 3; i--;) tiles[foundMatches[0][i][1]][foundMatches[0][i][0]] = Math.floor(Math.random() * colours.length);
192
}
193
let selectedTile = null;
194
for (let y = 8; y--;) {
195
let elemRow = [];
196
tileElems[y] = elemRow;
197
for (let x = 8; x--;) new Tile(x, y, tiles[y][x]);
198
}
199
document.body.appendChild(squareElem);
200
score.set(0);
201