Add more preferences for automatic hints
This commit is contained in:
parent
b60c7609cf
commit
85d71faa3f
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "minesweeper",
|
"name": "minesweeper",
|
||||||
"version": "0.84.0",
|
"version": "0.85.0",
|
||||||
"description": "Just Minesweeper!",
|
"description": "Just Minesweeper!",
|
||||||
"author": "Florine W. Dekker",
|
"author": "Florine W. Dekker",
|
||||||
"browser": "dist/bundle.js",
|
"browser": "dist/bundle.js",
|
||||||
|
|
|
@ -138,11 +138,12 @@
|
||||||
<header>
|
<header>
|
||||||
<hgroup>
|
<hgroup>
|
||||||
<h1>Preferences</h1>
|
<h1>Preferences</h1>
|
||||||
<h2>
|
<h2>Configure the gameplay to your liking.</h2>
|
||||||
Configure the gameplay to your liking.
|
|
||||||
</h2>
|
|
||||||
</hgroup>
|
</hgroup>
|
||||||
</header>
|
</header>
|
||||||
|
<article>
|
||||||
|
Options marked with * make the game considerably easier, and are not recommended except for learning.
|
||||||
|
</article>
|
||||||
<form id="preferences-form">
|
<form id="preferences-form">
|
||||||
<input role="switch" type="checkbox" id="preferences-enable-marks" autofocus />
|
<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>
|
<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" />
|
<input role="switch" type="checkbox" id="preferences-show-too-many-flags-hints" />
|
||||||
<label for="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>
|
</label>
|
||||||
<br /><br />
|
<br /><br />
|
||||||
|
|
||||||
<input role="switch" type="checkbox" id="preferences-show-chordable-hints" />
|
<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>
|
</form>
|
||||||
<footer>
|
<footer>
|
||||||
<a role="button" href="#" id="preferences-cancel" class="secondary">Cancel</a>
|
<a role="button" href="#" id="preferences-cancel" class="secondary">Cancel</a>
|
||||||
|
|
|
@ -9,6 +9,10 @@ import {Preferences} from "./Preferences";
|
||||||
* Displays a Minesweeper field.
|
* Displays a Minesweeper field.
|
||||||
*/
|
*/
|
||||||
export class Display {
|
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 scale: number = 30;
|
||||||
private readonly minSquareWidth: number = 6;
|
private readonly minSquareWidth: number = 6;
|
||||||
|
|
||||||
|
@ -301,19 +305,35 @@ export class Display {
|
||||||
private drawHints(ctx: CanvasRenderingContext2D): void {
|
private drawHints(ctx: CanvasRenderingContext2D): void {
|
||||||
if (this.field == null) return;
|
if (this.field == null) return;
|
||||||
|
|
||||||
if (this.preferences.showTooManyFlagsHints) {
|
let madeMistakes = false;
|
||||||
|
let showsHint = false;
|
||||||
|
|
||||||
|
if (this.hintSquare != null) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.fillStyle = "rgba(255, 0, 0, 0.3)";
|
ctx.fillStyle = this.hintColor;
|
||||||
this.field.squareList
|
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.isCovered)
|
||||||
.filter(it => it.getNeighborCount(it => it.hasMine) < it.getNeighborCount(it => it.hasFlag))
|
.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();
|
ctx.restore();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.preferences.showChordableHints) {
|
if (
|
||||||
|
!showsHint && !madeMistakes &&
|
||||||
|
(this.preferences.showChordableHints || this.preferences.showAllNeighborsAreMinesHints)
|
||||||
|
) {
|
||||||
ctx.save();
|
ctx.save();
|
||||||
ctx.fillStyle = "rgba(0, 0, 255, 0.3)";
|
ctx.fillStyle = this.safeColor;
|
||||||
this.field.squareList
|
this.field.squareList
|
||||||
.filter(it => !it.isCovered)
|
.filter(it => !it.isCovered)
|
||||||
.filter(it => {
|
.filter(it => {
|
||||||
|
@ -321,18 +341,14 @@ export class Display {
|
||||||
const flags = it.getNeighborCount(it => it.hasFlag);
|
const flags = it.getNeighborCount(it => it.hasFlag);
|
||||||
const covered = it.getNeighborCount(it => it.isCovered);
|
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));
|
.forEach(square => ctx.fillRect(square.x * this.scale, square.y * this.scale, this.scale, this.scale));
|
||||||
ctx.restore();
|
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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -181,24 +181,27 @@ export class Game {
|
||||||
);
|
);
|
||||||
|
|
||||||
// Preferences
|
// Preferences
|
||||||
const enableMarksInput = $("#preferences-enable-marks");
|
const enableMarks = $("#preferences-enable-marks");
|
||||||
const showTooManyFlagsHintsInput = $("#preferences-show-too-many-flags-hints");
|
const showTooManyFlagsHints = $("#preferences-show-too-many-flags-hints");
|
||||||
|
const showAllNeighborsAreMinesHints = $("#preferences-show-all-neighbors-are-mines-hints");
|
||||||
const showChordableHints = $("#preferences-show-chordable-hints");
|
const showChordableHints = $("#preferences-show-chordable-hints");
|
||||||
const preferencesDialog = new ModalDialog({
|
const preferencesDialog = new ModalDialog({
|
||||||
dialog: $("#preferences-dialog"),
|
dialog: $("#preferences-dialog"),
|
||||||
openButton: $("#preferences-open"),
|
openButton: $("#preferences-open"),
|
||||||
onOpen: () => {
|
onOpen: () => {
|
||||||
enableMarksInput.checked = preferences.marksEnabled;
|
enableMarks.checked = preferences.marksEnabled;
|
||||||
showTooManyFlagsHintsInput.checked = preferences.showTooManyFlagsHints;
|
showTooManyFlagsHints.checked = preferences.showTooManyFlagsHints;
|
||||||
showChordableHints.checked = preferences.showChordableHints;
|
showChordableHints.checked = preferences.showChordableHints;
|
||||||
|
showAllNeighborsAreMinesHints.checked = preferences.showAllNeighborsAreMinesHints;
|
||||||
},
|
},
|
||||||
form: $("#preferences-form"),
|
form: $("#preferences-form"),
|
||||||
closeButton: $("#preferences-cancel"),
|
closeButton: $("#preferences-cancel"),
|
||||||
submitButton: $("#preferences-submit"),
|
submitButton: $("#preferences-submit"),
|
||||||
onSubmit: () => {
|
onSubmit: () => {
|
||||||
preferences.marksEnabled = enableMarksInput.checked;
|
preferences.marksEnabled = enableMarks.checked;
|
||||||
preferences.showTooManyFlagsHints = showTooManyFlagsHintsInput.checked;
|
preferences.showTooManyFlagsHints = showTooManyFlagsHints.checked;
|
||||||
preferences.showChordableHints = showChordableHints.checked;
|
preferences.showChordableHints = showChordableHints.checked;
|
||||||
|
preferences.showAllNeighborsAreMinesHints = showAllNeighborsAreMinesHints.checked;
|
||||||
|
|
||||||
preferencesDialog.close();
|
preferencesDialog.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,6 +43,14 @@ export class Preferences {
|
||||||
this.storage.setBoolean("showChordableHints", value);
|
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 {
|
get showTooManyFlagsHints(): boolean {
|
||||||
return this.storage.getBoolean("showTooManyFlagsHints", true);
|
return this.storage.getBoolean("showTooManyFlagsHints", true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue