Improve performance of `uncover`

Fixes #36.
This commit is contained in:
Florine W. Dekker 2020-08-01 15:12:26 +02:00
parent e65a587261
commit 10050fe1e2
Signed by: FWDekker
GPG Key ID: B1B567AF58D6EE0F
2 changed files with 9 additions and 5 deletions

View File

@ -1,6 +1,6 @@
{
"name": "minesweeper",
"version": "0.0.49",
"version": "0.0.50",
"description": "Just Minesweeper!",
"author": "Felix W. Dekker",
"browser": "dist/bundle.js",

View File

@ -124,6 +124,8 @@ export class Field {
* Handles the event when a square is clicked, which includes moving the mine if the player hits a mine on the first
* click.
*
* This function should not be invoked when the square was already covered and is uncovered again.
*
* @param square the square that was clicked on
*/
onUncover(square: Square): void {
@ -143,7 +145,7 @@ export class Field {
.filter(it => it.hasMine)
.forEach(it => {
const candidate = this.squareList
.find(it => !it.hasMine && it !== square && square.getNeighbors().indexOf(it) < 0);
.find(it => !it.hasMine && it !== square && square.getNeighbors().indexOf(it) < 0);
if (candidate === undefined) return;
it.hasMine = false;
@ -152,7 +154,7 @@ export class Field {
}
if (!square.hasMine) {
this.coveredRemaining = this.squareList.filter(it => !it.hasMine && it.isCovered).length;
this.coveredRemaining--;
if (this.coveredRemaining === 0) {
this.endTime = Date.now();
this.squareList.filter(it => it.isCovered && !it.hasFlag).forEach(it => it.flag());
@ -265,16 +267,18 @@ export class Square {
* Uncovers this square, revealing the contents beneath.
*/
uncover(): void {
if (!this.isCovered || this.hasFlag || this.field.won || this.field.lost) return;
if (this.field.won || this.field.lost) return;
const uncoverQueue: Square[] = [this];
while (uncoverQueue.length > 0) {
const next = uncoverQueue.pop()!;
if (!next.isCovered || next.hasFlag) continue;
next.isCovered = false;
next.hasFlag = false;
this.field.onUncover(next); // Also moves mine on first click
if (!next.hasMine && next.getNeighborCount(it => it.hasMine) === 0)
if (!next.hasMine && next.getNeighborCount(it => it.hasMine || it.hasFlag) === 0)
uncoverQueue.push(...next.getNeighbors().filter(it => it.isCovered));
}
}