minesweeper-for-web v3.0.4
minesweeper-for-web
This is Minesweeper as a WebComponent. Once you integrate it as described further, the game just follows the standard rules. To place a flag just press ctrl, alt or the meta key while clicking on a field.
Getting Started
Install the package via npm or yarn and deliver the script to the user.
This can be done via import, require or just inserting a script tag.
npm i minesweeper-for-webyarn add minesweeper-for-webAttributes
| Param | Type | Description | Default |
|---|---|---|---|
columns | number | Amount of columns of the board. | 9 |
rows | number | Amount of rows of the board. | 9 |
bombs | number | Amount of bombs of the board. | 10 |
long-press-threshold | number | Amount of milliseconds required to trigger a long press (placing a flag). A value of zero or below disabled the long press functionality overall. | 500 |
disable-question-marks | boolean | Disables the functionality to place question marks. | false |
flag-placement-mode | boolean | Enables the flag placement mode. A mode where every click places a flag instead of revealing the field. | false |
restart-selector | string | If present, attaches a click event listener to the element to trigger a restart. | |
bomb-counter-selector | string | If present, changes the textContent of the provided element to the amount of bombs minus the amount of placed flags. |
Events
By default, each event contains the current game state in event.detail.game. To discourage cheating, no events should be logged in the browser console.
| Name | Type | Cancelable | Description | detail |
| ------------- | ------------- | ------------------ | ------------------------- | ------ |
| minesweeper:game-won | GameWonEvent| :x: | User just won the game | board: MinesweeperBoard current game state |
| minesweeper:game-lost | GameLostEvent| :x: | User just lost the game | board: MinesweeperBoard current game state |
| minesweeper:field-click | FieldClickEvent| :white_check_mark: | User clicked a field | board: MinesweeperBoard current game statetarget: FieldTarget target of the clickfield: HTMLElement clicked field |
| minesweeper:field-long-press | FieldLongPressEvent| :white_check_mark: | User long pressed a field | board: MinesweeperBoard current game statetarget: FieldTarget target of the long pressfield: HTMLElement long pressed field |
| minesweeper:field-interaction | FieldInteractionEvent| :x: | Game state change occurred | board: MinesweeperBoard current game statetarget: FieldTarget target of the interactioninteraction: Interaction interaction information |
Usage
Basic usage
Just a basic 9x9 / 10 Mines minesweeper game. Further examples can be combined.
<minesweeper-game></minesweeper-game>
<script type="module">
import 'minesweeper-for-web';
// Alternatives:
// import 'minesweeper-for-web/custom-element';
// import 'minesweeper-for-web/custom-element.min';
</script>Custom tag name
Define your own custom tag name
<custom-minesweeper-game></custom-minesweeper-game>
<script type="module">
import { MinesweeperGame } from 'minesweeper-for-web/minesweeper-game';
// Alternative:
// import { MinesweeperGame } from 'minesweeper-for-web/minesweeper-game.min';
window.customElements.define('custom-minesweeper-game', MinesweeperGame);
</script>Provide left-bomb-counter container
To keep the user informed how many mines are left, after subtracting the number of placed flags, just provide a container for the counter.
<p><span id="bomb-counter"></span> Mines</p>
<minesweeper-game bomb-counter-selector="#bomb-counter"></minesweeper-game>
<script type="module">
import 'minesweeper-for-web';
</script>Provide a restart button
Provide a selector where a "click"-event will be attached to, to restart the game.
<minesweeper-game restart-selector="#restart-game-button"></minesweeper-game>
<button id="restart-game-button">Restart!</button>
<script type="module">
import 'minesweeper-for-web';
</script>Disable Long Press
Provide a number lower or equal to 0 to disable the long press functionality.
<minesweeper-game long-press-threshold="0"></minesweeper-game>
<script type="module">
import 'minesweeper-for-web';
</script>Trigger Restart via JavaScript
Write custom logic to restart the game.
<minesweeper-game id="minesweeper"></minesweeper-game>
<button id="restart-game-button-confirm">Restart with Confirm!</button>
<script type="module">
import 'minesweeper-for-web';
window.addEventListener('DOMContentLoaded', () => {
const minesweeper = document.querySelector('#minesweeper');
document.querySelector('#restart-game-button-confirm').addEventListener('click', (event) => {
event.preventDefault();
if (window.confirm('Are you sure, that you want to restart the game?')) {
minesweeper.restartGame();
}
});
});
</script>Custom win/lose event listener
Attach an EventListener for the win/lose events.
<minesweeper-game id="minesweeper"></minesweeper-game>
<script type="module">
import 'minesweeper-for-web';
window.addEventListener('DOMContentLoaded', () => {
const minesweeper = document.querySelector('#minesweeper');
minesweeper.addEventListener('game-won', () => {
console.log('win');
});
minesweeper.addEventListener('game-lost', () => {
console.log('lose');
});
});
</script>Different initial game configurations
Of course you can provide different configurations for the game.
<minesweeper-game rows="30" columns="16" bombs="99"></minesweeper-game>
<script type="module">
import 'minesweeper-for-web';
</script>Providing a selectable gamemode
Furthermore you can implement some own logic to create a selectable gamemode
<select name="select-game-mode" id="select-game-mode">
<option value="easy" selected>Easy - 9x9 / 10 Mines</option>
<option value="normal">Normal - 16x16 / 40 Mines</option>
<option value="hard">Hard - 16x30 / 99 Mines</option>
</select>
<minesweeper-game id="minesweeper"></minesweeper-game>
<script type="module">
import 'minesweeper-for-web';
function getGameModeConfiguration(currentGameMode) {
switch (currentGameMode) {
case 'hard':
return {
columns: 30,
rows: 16,
bombs: 99,
};
case 'normal':
return {
columns: 16,
rows: 16,
bombs: 40,
};
default: // 'easy'
return {
columns: 9,
rows: 9,
bombs: 10,
};
}
}
window.addEventListener('DOMContentLoaded', () => {
const minesweeper = document.querySelector('#minesweeper');
document.querySelector('#select-game-mode').addEventListener('change', (event) => {
event.preventDefault();
const gameModeConfiguration = getGameModeConfiguration(event.target.value);
minesweeper.setGameModeConfiguration(gameModeConfiguration);
});
});
</script>Example
Try it out at CodePen.

TypeScript
The whole package is written in TypeScript and therefore provides a strongly typed system via the core export of the package:
<!-- some-file.html -->
<minesweeper-game id="minesweeper"></minesweeper-game>// some-file.ts
import 'minesweeper-for-web/custom-element';
import { FieldInteractionEvent, FieldInteractionType } from 'minesweeper-for-web/core';
import type { MinesweeperGame } from 'minesweeper-for-web/core';
const minesweeperGame = document.querySelector('#minesweeper') as MinesweeperGame;
minesweeperGame.addEventListener(
'minesweeper:field-interaction',
(event: FieldInteractionEvent) => {
const { interaction } = event.detail;
switch (interaction.type) {
case FieldInteractionType.Unveiled:
console.log('Revealed field value:', interaction.value);
break;
case FieldInteractionType.FlagAction:
case FieldInteractionType.QuestionMarkAction:
console.log('Performed action:', interaction.action);
break;
}
}
);Engine
The engine can be used as a standalone library (commonjs and esm) via the engine export of the package. This enables the usage of the engine in every application (server- or client-side).
import { MinesweeperEngine } from 'minesweeper-for-web/engine';
const engine = new MinesweeperEngine();
// Creates a board with 10 columns, 12 rows and 10 bombs
engine.createBoard(10, 12, 10);
// Unveils the field in the first row and second column (indexes)
engine.selectField(0, 1);
// Follows the specification of `selectField`
engine.toggleFlag(0, 2);
// Nothing happens since a flag is present on that field
engine.selectField(0, 2);
// Follows the specification of `selectField`
engine.toggleQuestionMark(0, 3);
// Still unveils the field regardless of the question mark
engine.selectField(0, 3);
if (engine.isGameOver) {
// Restarts the game with the initial configuration
engine.restart();
}const { MinesweeperEngine } = require('minesweeper-for-web/engine');
const engine = new MinesweeperEngine();
// ...License
Icons Copyright
All rights for the icons used in this project belongs to their original creators: https://commons.wikimedia.org/wiki/Category:Minesweeper
The icons "bomb_red.svg" and "bomb.svg" are based on "number-0.svg" and "flag_missed.svg" is based on "bomb.svg".
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
6 years ago
6 years ago
6 years ago