Add more preferences for automatic hints

This commit is contained in:
Florine W. Dekker 2022-11-26 16:47:52 +01:00
parent b60c7609cf
commit 85d71faa3f
Signed by: FWDekker
GPG Key ID: D3DCFAA8A4560BE0
5 changed files with 63 additions and 26 deletions

View File

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

View File

@ -138,11 +138,12 @@
<header>
<hgroup>
<h1>Preferences</h1>
<h2>
Configure the gameplay to your liking.
</h2>
<h2>Configure the gameplay to your liking.</h2>
</hgroup>
</header>
<article>
Options marked with * make the game considerably easier, and are not recommended except for learning.
</article>
<form id="preferences-form">
<input role="switch" type="checkbox" id="preferences-enable-marks" autofocus />
<label for="preferences-enable-marks">Right-clicking a square twice places a question mark.</label>
@ -150,12 +151,21 @@
<input role="switch" type="checkbox" id="preferences-show-too-many-flags-hints" />
<label for="preferences-show-too-many-flags-hints">
Highlight squares with too many flags around them in red.
Highlight squares in red if there are too many adjacent flags.
</label>
<br /><br />
<input role="switch" type="checkbox" id="preferences-show-chordable-hints" />
<label for="preferences-show-chordable-hints">Highlight squares that can be chorded in blue.</label>
<label for="preferences-show-chordable-hints">
*Highlight squares in green if they can be
<a href="https://www.minesweeper.info/wiki/Chord">chorded</a>.
</label>
<br /><br />
<input role="switch" type="checkbox" id="preferences-show-all-neighbors-are-mines-hints" />
<label for="preferences-show-all-neighbors-are-mines-hints">
*Highlight squares in green if all neighbors have mines.
</label>
</form>
<footer>
<a role="button" href="#" id="preferences-cancel" class="secondary">Cancel</a>

View File

@ -9,6 +9,10 @@ import {Preferences} from "./Preferences";
* Displays a Minesweeper field.
*/
export class Display {
private readonly errorColor: string = "rgba(255, 0, 0, 0.3)";
private readonly hintColor: string = "rgba(0, 0, 255, 0.3)";
private readonly safeColor: string = "rgba(0, 255, 0, 0.5)";
private readonly scale: number = 30;
private readonly minSquareWidth: number = 6;
@ -301,19 +305,35 @@ export class Display {
private drawHints(ctx: CanvasRenderingContext2D): void {
if (this.field == null) return;
if (this.preferences.showTooManyFlagsHints) {
let madeMistakes = false;
let showsHint = false;
if (this.hintSquare != null) {
ctx.save();
ctx.fillStyle = "rgba(255, 0, 0, 0.3)";
this.field.squareList
ctx.fillStyle = this.hintColor;
ctx.fillRect(this.hintSquare.x * this.scale, this.hintSquare.y * this.scale, this.scale, this.scale);
ctx.restore();
showsHint = true;
}
if (!showsHint && this.preferences.showTooManyFlagsHints) {
ctx.save();
ctx.fillStyle = this.errorColor;
madeMistakes = madeMistakes || this.field.squareList
.filter(it => !it.isCovered)
.filter(it => it.getNeighborCount(it => it.hasMine) < it.getNeighborCount(it => it.hasFlag))
.forEach(square => ctx.fillRect(square.x * this.scale, square.y * this.scale, this.scale, this.scale));
.map(square => ctx.fillRect(square.x * this.scale, square.y * this.scale, this.scale, this.scale))
.length > 0;
ctx.restore();
}
if (this.preferences.showChordableHints) {
if (
!showsHint && !madeMistakes &&
(this.preferences.showChordableHints || this.preferences.showAllNeighborsAreMinesHints)
) {
ctx.save();
ctx.fillStyle = "rgba(0, 0, 255, 0.3)";
ctx.fillStyle = this.safeColor;
this.field.squareList
.filter(it => !it.isCovered)
.filter(it => {
@ -321,18 +341,14 @@ export class Display {
const flags = it.getNeighborCount(it => it.hasFlag);
const covered = it.getNeighborCount(it => it.isCovered);
return mines === flags && covered !== flags;
return (
(this.preferences.showChordableHints && mines === flags && covered !== flags) ||
(this.preferences.showAllNeighborsAreMinesHints && mines === covered && mines !== flags)
);
})
.forEach(square => ctx.fillRect(square.x * this.scale, square.y * this.scale, this.scale, this.scale));
ctx.restore();
}
if (this.hintSquare != null) {
ctx.save();
ctx.fillStyle = "rgba(0, 255, 0, 0.3)";
ctx.fillRect(this.hintSquare.x * this.scale, this.hintSquare.y * this.scale, this.scale, this.scale);
ctx.restore();
}
}
/**

View File

@ -181,24 +181,27 @@ export class Game {
);
// Preferences
const enableMarksInput = $("#preferences-enable-marks");
const showTooManyFlagsHintsInput = $("#preferences-show-too-many-flags-hints");
const enableMarks = $("#preferences-enable-marks");
const showTooManyFlagsHints = $("#preferences-show-too-many-flags-hints");
const showAllNeighborsAreMinesHints = $("#preferences-show-all-neighbors-are-mines-hints");
const showChordableHints = $("#preferences-show-chordable-hints");
const preferencesDialog = new ModalDialog({
dialog: $("#preferences-dialog"),
openButton: $("#preferences-open"),
onOpen: () => {
enableMarksInput.checked = preferences.marksEnabled;
showTooManyFlagsHintsInput.checked = preferences.showTooManyFlagsHints;
enableMarks.checked = preferences.marksEnabled;
showTooManyFlagsHints.checked = preferences.showTooManyFlagsHints;
showChordableHints.checked = preferences.showChordableHints;
showAllNeighborsAreMinesHints.checked = preferences.showAllNeighborsAreMinesHints;
},
form: $("#preferences-form"),
closeButton: $("#preferences-cancel"),
submitButton: $("#preferences-submit"),
onSubmit: () => {
preferences.marksEnabled = enableMarksInput.checked;
preferences.showTooManyFlagsHints = showTooManyFlagsHintsInput.checked;
preferences.marksEnabled = enableMarks.checked;
preferences.showTooManyFlagsHints = showTooManyFlagsHints.checked;
preferences.showChordableHints = showChordableHints.checked;
preferences.showAllNeighborsAreMinesHints = showAllNeighborsAreMinesHints.checked;
preferencesDialog.close();
}

View File

@ -43,6 +43,14 @@ export class Preferences {
this.storage.setBoolean("showChordableHints", value);
}
get showAllNeighborsAreMinesHints(): boolean {
return this.storage.getBoolean("showAllNeighborsAreMinesHints", false);
}
set showAllNeighborsAreMinesHints(value: boolean) {
this.storage.setBoolean("showAllNeighborsAreMinesHints", value);
}
get showTooManyFlagsHints(): boolean {
return this.storage.getBoolean("showTooManyFlagsHints", true);
}