Minesweeper-JS/scripts/game.js
2024-05-08 13:51:57 -04:00

392 lines
No EOL
8.8 KiB
JavaScript

// Variables
/// Game
var tilesGrid = [];
var tilesShown = [];
var flagsGrid = [];
var playing = true;
/// For loops
var rippling = false;
/// Games
var flags = gridBombs;
// Functions
/// Private
function _checkWin(){
// Matches
var matches = 0;
for(var y = 0; y < gridHeight; y++){
for(var x = 0; x < gridWidth; x++){
if(flagsGrid[y*gridHeight+x]
&& tilesGrid[y*gridHeight+x]){
matches++;
}
}
}
if(matches >= gridBombs){
_winGame();
}
}
function _updateScreen(){
// Mode of tile?
var tileMode = 0;
// Thing
for(var y = 0; y < gridHeight; y++){
for(var x = 0; x < gridWidth; x++){
// Drawing with CANVAS
let _tileWidth = UI_Canvas.width / gridWidth;
let _tileHeight = UI_Canvas.height / gridHeight;
// Drawing
/// New Object
ctx.beginPath();
/// Color?
ctx.fillStyle = "#ffffff";
// Game over, show mines
if(!playing
&& tilesGrid[y*gridHeight+x] == 1){
tileMode = 0;
}
// Numbered tiles
else if(!tilesGrid[y*gridHeight+x]
&& tilesShown[y*gridHeight+x]){
tileMode = 1;
}
// Flag tiles
else if(flagsGrid[y*gridHeight+x]){
tileMode = 2;
}
// Standard tiles
else{
tileMode = 3;
}
// What tile mode do we use?
switch(tileMode){
case 0:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 2,0, 16,16);
break;
case 1:
// Todo: Add numbered tiles support
switch(_getNumber(x,y)){
case "":
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 3,0, 16,16);
break;
case 1:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 0,1, 16,16);
break;
case 2:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 1,1, 16,16);
break;
case 3:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 2,1, 16,16);
break;
case 4:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 3,1, 16,16);
break;
case 5:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 0,2, 16,16);
break;
case 6:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 1,2, 16,16);
break;
case 7:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 2,2, 16,16);
break;
case 8:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 3,2, 16,16);
break;
}
break;
case 2:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 1,0, 16,16);
break;
case 3:
drawTileMap("data/icons.png", x, y, _tileWidth, _tileHeight, 0,0, 16,16);
break;
}
}
}
// Win check
_checkWin();
// UI
UI_Flags.textContent = flags;
console.log(flags);
}
function _startGrid(){
/*
This is different from _createGrid
this will just start up the systems.
_createGrid will be triggered when you first click
making the grid spawn
*/
// Reset grid
tilesGrid = [];
tilesShown = [];
// Loops for Grids
for(var y = 0; y < gridHeight; y++){
for(var x = 0; x < gridWidth; x++){
// Add to shown
tilesGrid.push(0);
tilesShown.push(0);
flagsGrid.push(0);
}
}
}
function _createGrid(){
// Mouse to cursor pos
// Get mouse position
var _mx = mousePosition[0];
var _my = mousePosition[1];
// Convert it to local grid space
_mx -= UI_Canvas.offsetLeft;
_my -= UI_Canvas.offsetTop;
// Convert _mx and _my to be able to be used to find the tile the user wants
let _x = Math.floor(_mx / (UI_Canvas.width / gridWidth));
let _y = Math.floor(_my / (UI_Canvas.height / gridHeight));
// Random Bombs
for(var i = 0; i < gridBombs; i++){
// Placeholder positions
var _bx = 0;
var _by = 0;
// Checking for an unused space
while(true){
_bx = parseInt(Math.random() * 10);
_by = parseInt(Math.random() * 10);
if(tilesGrid[_by*gridHeight+_bx] == 0
&& _bx != _x && _by != _y){
break;
}
}
// Apply position
tilesGrid[_by*gridHeight+_bx] = 1;
}
}
function _chkTile(x,y){
return tilesGrid[y*gridHeight+x];
}
function _setTile(x,y, val){
tilesShown[y*gridHeight+x] = val;
}
function _getNumber(x,y){
// Result number
var result = 0;
// Go through all tiles
for(var _y = y-1; _y < y+2; _y++){
for(var _x = x-1; _x < x+2; _x++){
if((_y >= 0 && _y < gridHeight)
&& (_x >= 0 && _x < gridWidth)){
if(_chkTile(_x,_y) > 0){
result++;
}
}
}
}
if(result == 0){
result = "";
}
// Return result
return result;
}
function spawnRipple(x, y) {
// Tile with bombs near?
if(_getNumber(x,y) != ""){
rippling = false;
return;
}
// Checking if this is a bad tile..
for (var _y = -1; _y < 2; _y++) {
for (var _x = -1; _x < 2; _x++) {
// Checking for things that will cause it to fail
if (_x == 0 && _y == 0) {
continue;
}
if (x + _x < 0 || x + _x >= gridWidth || y + _y < 0 || y + _y >= gridHeight) {
continue;
}
// No diagonal
if((_x == -1 && _y == -1)
|| (_x == -1 && _y == 1)
|| (_x == 1 && _y == -1)
|| (_x == 1 && _y == 1)){
continue;
}
// Bombs near?
if(_getNumber(x+_x, y+_y) != ""){
tilesShown[(y + _y) * gridWidth + (x + _x)] = 1;
continue;
}
// The beef and potatoes!
if (!tilesShown[(y + _y) * gridWidth + (x + _x)] && !_chkTile(x + _x, y + _y)) {
tilesShown[(y + _y) * gridWidth + (x + _x)] = 1;
spawnRipple(x + _x, y + _y);
}
}
}
// Checking for a fail
for (var _y = -1; _y < 2; _y++) {
for (var _x = -1; _x < 2; _x++) {
// Checking for things that will cause it to fail
if (_x == 0 && _y == 0) {
continue;
}
if (x + _x < 0 || x + _x >= gridWidth || y + _y < 0 || y + _y >= gridHeight) {
continue;
}
// The beef and potatoes!
if (!tilesShown[(y + _y) * gridWidth + (x + _x)] && !_chkTile(x + _x, y + _y)) {
return;
}
}
}
// Failing..
rippling = false;
}
function _revealTiles(x, y) {
// Are we clicking on a flag?
if(flagsGrid[y*gridHeight+x] != 0){return};
// Set clicked tile
_setTile(x, y, 1);
// RIPPLE EFFECT METHOD
rippling = true;
// Force ripple ending if things carry on forever
setTimeout(function(){
rippling = false;
}, 1500);
// Ripple!
while(rippling){
spawnRipple(x,y);
}
// You messed up..
if (tilesGrid[y * gridWidth + x]) {
_endGame();
}
}
function _clickTile(){
// The whole reason I was going to use Divs is because
// It would have been easier but.. No.. Of course not
// Javascript is Never simple or it never works like C/C++ does.
// Get mouse position
var _mx = mousePosition[0];
var _my = mousePosition[1];
// Convert it to local grid space
_mx -= UI_Canvas.offsetLeft;
_my -= UI_Canvas.offsetTop;
// Convert _mx and _my to be able to be used to find the tile the user wants
let _x = Math.floor(_mx / (UI_Canvas.width / gridWidth));
let _y = Math.floor(_my / (UI_Canvas.height / gridHeight));
console.log(_x, _y);
// Check if we need to init the grid
let sum = 0;
for(var i = 0; i < tilesGrid.length; i++){
sum += tilesGrid[i];
}
if(sum == 0){
_createGrid();
}
// Update
_revealTiles(_x, _y);
}
function _addFlag(event){
// Prevent default
event.preventDefault();
// Too many flags?
if(flags <= 0){
return;
}
// Get mouse position
var _mx = mousePosition[0];
var _my = mousePosition[1];
// Convert it to local grid space
_mx -= UI_Canvas.offsetLeft;
_my -= UI_Canvas.offsetTop;
// Convert _mx and _my to be able to be used to find the tile the user wants
let _x = Math.floor(_mx / (UI_Canvas.width / gridWidth));
let _y = Math.floor(_my / (UI_Canvas.height / gridHeight));
// Now, let's add the flag!
flagsGrid[_y*gridHeight+_x] = !flagsGrid[_y*gridHeight+_x];
console.log("New Flag: " + flagsGrid[_y*gridHeight+_x]);
}
function _getFlags(){
flags = gridBombs;
for(var y = 0; y < gridHeight; y++){
for(var x = 0; x < gridWidth; x++){
if(flagsGrid[y*gridHeight+x] == 1){
flags--;
}
}
}
}
/// Public
function _endGame(){
alert("YOU HIT A MINE!");
playing = false;
}
function _winGame(){
alert("You Won!");
}
function _onUpdate(){
// Drawing:
_getFlags();
_updateScreen();
}
function _onStart(){
// Init
_startGrid();
// Start loop
thread = window.setInterval(_onUpdate, 3);
}
// Events
window.addEventListener("load", _onStart);
UI_Canvas.addEventListener("click", _clickTile);
UI_Canvas.addEventListener("contextmenu", _addFlag);