When i change a frame size, like 3×3, 4×4, 5×5 etc. canvas draw n number of times constantly calculation in progression. I can’t figure out where the error might be. Can you help me fix this bug. I suspect that the problem is in the function call in the class, or in one of the functions.
Code snippet and screenshot picture i attached
JavaScript
x
236
236
1
const defaultFrame = 4;
2
3
class GeneratePage {
4
constructor() {
5
this.element = `
6
<div class="wrapper">
7
<div class="control">
8
<button type="button" class="btn btn__start"><span>Shuffle and start</span></button>
9
<button type="button" class="btn btn__stop"><span>Stop</span></button>
10
<button type="button" class="btn btn__save"><span>Save</span></button>
11
<button type="button" class="btn btn__results"><span>Results</span></button>
12
</div>
13
<div class="info">
14
<p class="info__moves">Move: <span class="info__step">0</span></p>
15
<p class="info__time">Time: <span class="info__timepass">00:00</span></p>
16
</div>
17
<div class="frame">
18
<p class="frame__title">Frame: <span class="frame__selection">4x4</span></p>
19
<div class="frame__wrapper">
20
<p class="frame__select">Choose frame size:</p>
21
<select class="frame__list" name="frames">
22
<option class="frame__option" value="3">3x3</option>
23
<option class="frame__option" value="4" selected>4x4</option>
24
<option class="frame__option" value="5">5x5</option>
25
<option class="frame__option" value="6">6x6</option>
26
<option class="frame__option" value="7">7x7</option>
27
<option class="frame__option" value="8">8x8</option>
28
</select>
29
</div>
30
</div>
31
</div>
32
</div>
33
`;
34
this.generate();
35
}
36
37
generate = () => {
38
document.body.innerHTML = this.element;
39
};
40
}
41
42
class Game {
43
constructor(context, cellSize, framesize) {
44
this.nowstate = framesize;
45
console.log(this.nowstate);
46
this.list = document.querySelector('.frame__list');
47
this.selection = document.querySelector('.frame__selection');
48
this.color = '#008aff';
49
50
this.context = context;
51
this.cellSize = cellSize;
52
53
this.clicks = 0;
54
55
this.state = Game.checkSize(this.nowstate);
56
this.eventHandlers();
57
}
58
59
eventHandlers = () => {
60
this.list.addEventListener('change', (e) => this.changeSize(e));
61
};
62
63
changeSize = (e) => {
64
e.preventDefault();
65
const nowstate = e.target.value;
66
this.selection.textContent = `${nowstate}x${nowstate}`;
67
Game.createPuzzle(nowstate);
68
};
69
70
static getClicks() {
71
return this.clicks;
72
}
73
74
static checkSize = (n) => {
75
const matrix = [];
76
for (let i = 0; i < n; i += 1) {
77
matrix.push([]);
78
}
79
for (let i = 0; i < n; i += 1) {
80
for (let j = 0; j < n; j += 1) {
81
matrix[i][j] = n * i + j + 1;
82
}
83
}
84
matrix[n - 1][n - 1] = 0;
85
return matrix;
86
};
87
88
cellView = (x, y) => {
89
this.context.fillStyle = this.color;
90
this.context.fillRect(
91
x + 1,
92
y + 1,
93
this.cellSize - 2,
94
this.cellSize - 2,
95
);
96
};
97
98
numView = () => {
99
this.context.font = '1.8em Montserrat';
100
this.context.textAlign = 'center';
101
this.context.textBaseline = 'middle';
102
this.context.fillStyle = '#000';
103
};
104
105
draw = () => {
106
for (let i = 0; i < this.nowstate; i += 1) {
107
for (let j = 0; j < this.nowstate; j += 1) {
108
if (this.state[i][j] > 0) {
109
this.cellView(
110
j * this.cellSize,
111
i * this.cellSize,
112
);
113
this.numView();
114
this.context.fillText(
115
this.state[i][j],
116
j * this.cellSize + this.cellSize / 2,
117
i * this.cellSize + this.cellSize / 2,
118
);
119
}
120
}
121
}
122
};
123
124
getNullCell = () => {
125
for (let i = 0; i < this.nowstate; i += 1) {
126
for (let j = 0; j < this.nowstate; j += 1) {
127
if (this.state[j][i] === 0) {
128
return { x: i, y: j };
129
}
130
}
131
}
132
return false;
133
};
134
135
move = (x, y) => {
136
const nullCell = this.getNullCell();
137
const canMoveVertical = (x - 1 === nullCell.x || x + 1 === nullCell.x) && y === nullCell.y;
138
const canMoveHorizontal = (y - 1 === nullCell.y || y + 1 === nullCell.y) && x === nullCell.x;
139
140
if (canMoveVertical || canMoveHorizontal) {
141
this.state[nullCell.y][nullCell.x] = this.state[y][x];
142
this.state[y][x] = 0;
143
this.clicks += 1;
144
}
145
};
146
147
victory = () => {
148
const combination = this.checkSize(this.nowstate);
149
let res = true;
150
for (let i = 0; i < this.nowstate; i += 1) {
151
for (let j = 0; j < this.nowstate; i += 1) {
152
if (combination[i][j] !== this.state[i][j]) {
153
res = false;
154
break;
155
}
156
}
157
}
158
return res;
159
};
160
161
static getRandomBool = () => {
162
if (Math.floor(Math.random() * 2) === 0) {
163
return true;
164
}
165
return false;
166
};
167
168
mix = (count, n) => {
169
let x;
170
let y;
171
for (let i = 0; i < count; i += 1) {
172
const nullCell = this.getNullCell();
173
174
const verticalMove = Game.getRandomBool();
175
const upLeft = Game.getRandomBool();
176
177
if (verticalMove) {
178
x = nullCell.x;
179
if (upLeft) {
180
y = nullCell.y - 1;
181
} else {
182
y = nullCell.y + 1;
183
}
184
} else {
185
y = nullCell.y;
186
if (upLeft) {
187
x = nullCell.x - 1;
188
} else {
189
x = nullCell.x + 1;
190
}
191
}
192
193
if (x >= 0 && x <= n - 1 && y >= 0 && y <= n - 1) {
194
this.move(x, y);
195
}
196
}
197
198
this.clicks = 0;
199
};
200
201
static createPuzzle = (n) => {
202
let canvas = document.getElementById('puzzle');
203
if (canvas) {
204
canvas.remove();
205
console.log('remove');
206
}
207
const wrapper = document.querySelector('.wrapper');
208
canvas = document.createElement('canvas');
209
canvas.setAttribute('id', 'puzzle');
210
canvas.classList.add('game');
211
console.log(canvas);
212
wrapper.insertBefore(canvas, document.querySelector('.frame'));
213
214
// canvas = document.getElementById('puzzle');
215
216
canvas.width = 280;
217
canvas.height = 280;
218
219
const context = canvas.getContext('2d');
220
context.fillRect(0, 0, canvas.width, canvas.height);
221
222
const cellSize = canvas.width / n;
223
const game = new Game(context, cellSize, n);
224
game.mix(300, n);
225
game.draw();
226
};
227
}
228
229
class Application {
230
constructor() {
231
new GeneratePage;
232
Game.createPuzzle(defaultFrame);
233
}
234
}
235
236
new Application();
JavaScript
1
2
1
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}main{display:block}h1{font-size:2em;margin:.67em 0}hr{box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:rgba(0,0,0,0)}abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline;-webkit-text-decoration:underline dotted currentColor;text-decoration:underline dotted currentColor}b,strong{font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-0.25em}sup{top:-0.5em}img{border-style:none}button,input,optgroup,select,textarea{font-family:inherit;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details{display:block}summary{display:list-item}template{display:none}[hidden]{display:none}
2
@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Light.ttf) format("truetype");font-weight:300;font-style:normal;font-display:swap}@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Regular.ttf) format("truetype");font-weight:400;font-style:normal;font-display:swap}@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Medium.ttf) format("truetype");font-weight:500;font-style:normal;font-display:swap}@font-face{font-family:"Montserrat";src:url(fonts/Montserrat-Bold.ttf) format("truetype");font-weight:700;font-style:normal;font-display:swap}.btn{background-image:linear-gradient(135deg, #008aff, #86d472);border-radius:6px;box-sizing:border-box;color:#fff;display:block;height:50px;font-size:1em;font-weight:700;padding:4px;position:relative;text-decoration:none;width:7em;z-index:2;border:none;outline:none;cursor:pointer}.btn span{align-items:center;background:#0e0e10;border-radius:6px;display:flex;justify-content:center;height:100%;transition:background .5s ease;width:100%}.btn span:hover{background:rgba(0,0,0,0)}.btn:hover{color:#fff}html{scroll-behavior:smooth}*{padding:0;margin:0;box-sizing:border-box}body{font-family:"Montserrat",sans-serif;display:flex;flex-direction:column;align-items:center;padding:40px 20px 20px 20px}.wrapper{margin:0 auto;display:flex;flex-direction:column;align-items:center}.control{display:flex;flex-wrap:wrap;justify-content:center;gap:10px}.info{display:flex;gap:50px;margin-top:15px;font-weight:500;font-size:1.3rem}.game{margin-top:15px;border:1px solid #000}.frame{margin-top:15px;display:flex;flex-direction:column;align-items:center}.frame__title{font-weight:400;font-size:1.1rem}.frame__wrapper{margin-top:15px;display:flex;align-items:baseline}.frame__list{border:none;outline:none;max-width:100%;font-size:1.1rem;font-weight:400;padding:8px 10px 8px 10px;background-color:rgba(0,0,0,0);cursor:pointer}.frame__list:active,.frame__list:focus{outline:none;box-shadow:none}.frame__select{display:inline;margin-right:10px;font-size:1.1rem;font-weight:400}
JavaScript
1
13
13
1
<!DOCTYPE html>
2
<html lang="en">
3
<head>
4
<meta charset="UTF-8">
5
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7
<meta name="description" content="gem puzzle game">
8
<meta name="keywords" content="rsschool puzzle">
9
<title>Gem Puzzle</title>
10
</head>
11
<body>
12
</body>
13
</html>
Advertisement
Answer
Because you don’t deleting the event from frame__list.
You can delete event by using EventTarget.removeEventListener()
Or
By replacing node box.replaceWith(box.cloneNode(true));