Avoid using undefined where possible

Fixes #86.
This commit is contained in:
Florine W. Dekker 2020-08-13 11:13:00 +02:00
parent f94ee57811
commit 71d61a8916
Signed by: FWDekker
GPG Key ID: B1B567AF58D6EE0F
6 changed files with 31 additions and 20 deletions

View File

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

View File

@ -9,7 +9,7 @@ import alea from "alea";
* @param seed the seed for the random number generator
* @returns the array that was given to this function to shuffle
*/
export function shuffleArrayInPlace(array: any[], seed: number | undefined = undefined): any[] {
export function shuffleArrayInPlace(array: any[], seed: number): any[] {
const rng = alea("" + seed);
for (let i = array.length - 1; i > 0; i--) {
@ -56,10 +56,10 @@ export function range(length: number, beginAt: number = 0): number[] {
*
* @param onSuccess the function to invoke once the font has loaded
* @param onFailure the function to invoke if the font cannot be loaded
* @param timeout the maximum time in milliseconds to wait for the font to load
* @param timeout the maximum time in milliseconds to wait for the font to load, or `null` if there is no limit
*/
export function waitForForkAwesome(onSuccess: () => void, onFailure: () => void,
timeout: number | undefined = undefined): void {
timeout: number | null = null): void {
const canvas = document.createElement("canvas");
const ctx = canvas.getContext("2d")!;
const fontSize = 36;
@ -73,7 +73,7 @@ export function waitForForkAwesome(onSuccess: () => void, onFailure: () => void,
ctx.textBaseline = "middle";
const startTime = performance.now();
const failTime = timeout === undefined ? undefined : startTime + timeout;
const failTime = timeout === null ? null : startTime + timeout;
requestAnimationFrame(fontOnload);
/**
@ -83,7 +83,7 @@ export function waitForForkAwesome(onSuccess: () => void, onFailure: () => void,
*/
function fontOnload(time: number): void {
const currentCount = getPixelCount();
if (failTime !== undefined && time > failTime) onFailure();
if (failTime !== null && time > failTime) onFailure();
else if (currentCount < targetPixelCount) requestAnimationFrame(fontOnload);
else onSuccess();
}

View File

@ -124,7 +124,7 @@ export class Field {
* @param orElse the value to return if there is no square at the given coordinates
* @returns the square at the given coordinates, or `orElse` if there is no square there
*/
getSquareOrElse(coords: { x: number, y: number }, orElse: any = undefined): Square | any {
getSquareOrElse(coords: { x: number, y: number }, orElse: any = null): Square | any {
return this.squares[coords.y]?.[coords.x] ?? orElse;
}
@ -514,7 +514,7 @@ export class Square {
this.field.getSquareOrElse({x: this.x - 1, y: this.y + 1}),
this.field.getSquareOrElse({x: this.x, y: this.y + 1}),
this.field.getSquareOrElse({x: this.x + 1, y: this.y + 1}),
].filter(it => it !== undefined);
].filter(it => it !== null);
}
return this._neighbors!;

View File

@ -17,7 +17,7 @@ import {Overlay} from "./UI";
*/
export class Game {
private readonly statistics = new LocalStatistics();
private statisticsTimer: number | undefined = undefined;
private statisticsTimer: number | undefined;
private readonly canvas: HTMLCanvasElement;
private readonly difficultySelect: HTMLSelectElement;
@ -264,7 +264,7 @@ export class Game {
);
this.statisticsOverlay = new Overlay(
$("#statisticsOverlay"),
undefined,
null,
$("#statisticsCloseForm")
);
this.statisticsResetForm = $("#statisticsResetForm");
@ -319,7 +319,7 @@ export class Game {
case 2:
if (!this.leftDown) {
const square = this.field.getSquareOrElse(coords);
if (square !== undefined) {
if (square !== null) {
if (square.hasFlag) {
this.field.toggleFlag(coords);
if (preferences.marksEnabled)

View File

@ -191,9 +191,10 @@ export class Solver {
* @param knowns the uncovered squares that the solver should consider
* @param adjacentSquaresOnly `true` if the solver should only look at the squares adjacent to `known` and not at
* all squares in the field. Enabling this option increases complexity, but may uncover some edge cases
* @returns the solution that has been found
* @private
*/
private matrixSolve(field: Field, knowns: Square[], adjacentSquaresOnly: boolean): ([number, Square] | undefined)[] {
private matrixSolve(field: Field, knowns: Square[], adjacentSquaresOnly: boolean): Solution {
if (knowns.length === 0) return [];
let unknowns: Square[];
@ -241,11 +242,10 @@ export class Solver {
* Applies the given solution to the field.
*
* @param field the field to apply the solution to
* @param solution an array in which each `undefined` element is ignored, and each pair contains a square and the
* number `1` if the square contains a mine or the number `0` if the square does not contain a mine
* @param solution the solution to apply
* @private
*/
private applySolution(field: Field, solution: ([number, Square] | undefined)[]): void {
private applySolution(field: Field, solution: Solution): void {
solution.forEach(target => {
if (target === undefined) return;
@ -450,3 +450,14 @@ export class Matrix {
this.cells[rowA].map((it, i) => this.cells[rowA][i] + this.cells[rowB][i] * factor);
}
}
/**
* A partial solution to a field.
*
* Each element of the array describes an instruction to apply to the field. If the instruction is `undefined`, then
* nothing should be done. Otherwise, the tuple describes the instruction: If the number is 0, the associated square
* should be uncovered because it definitely does not contain a mine. Otherwise, the number is 1 and the associated
* square should be flagged because it definitely contains a mine.
*/
type Solution = ([number, Square] | undefined)[]

View File

@ -3,8 +3,8 @@
*/
export class Overlay {
private readonly overlay: HTMLDivElement;
private readonly submitForm: HTMLFormElement | undefined;
private readonly cancelForm: HTMLFormElement | undefined;
private readonly submitForm: HTMLFormElement | null;
private readonly cancelForm: HTMLFormElement | null;
/**
@ -17,9 +17,9 @@ export class Overlay {
*/
constructor(
overlay: HTMLDivElement,
submitForm: HTMLFormElement | undefined,
cancelForm: HTMLFormElement | undefined,
onSubmit: (() => void) | undefined = undefined
submitForm: HTMLFormElement | null,
cancelForm: HTMLFormElement | null,
onSubmit: (() => void) | null = null
) {
this.overlay = overlay;
overlay.addEventListener(