'use strict';
let xSize = 1;
let ySize = 1;
let minesToPlace = 1;
let totalSpaces = xSize * ySize;
let goingRight = false;
let errorFlags = {
rows: false,
columns: false,
mines: false,
};
function setupMinefield() {
let mineField = new Array(ySize);
for (let i = 0; i < ySize; i++){
mineField[i] = new Array(xSize);
}
for (let i = 0; i < ySize; i++){
for (let j = 0; j < xSize; j++){
mineField[i][j] = 0;
}
}
return mineField;
}
function getRandomInt(max) {
return Math.floor(Math.random() * Math.floor(max));
}
function fillWithMines(mineField){
let locationsSet = new Set();
while (locationsSet.size < minesToPlace){
locationsSet.add(getRandomInt(totalSpaces-1));
}
for (let mineLocation of locationsSet){
let yField = Math.floor(mineLocation / xSize);
let xField = mineLocation % xSize;
//alert("location=" + mineLocation + ", yField=" + yField + ", xField=" + xField);
mineField[yField][xField] = "B";
}
}
function updateAllSweeperValues(mineField){
for (let i = 0; i < ySize; i++){
for (let j = 0; j < xSize; j++){
if (mineField[i][j] != "B"){
updateSweeperValue(mineField,i,j);
}
}
}
}
function updateSweeperValue(mineField,yPos,xPos){
let xMax = xSize - 1;
let yMax = ySize - 1;
if (yPos == 0 && xPos == 0){
if (mineField[yPos+1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos+1] == "B") mineField[yPos][xPos]++;
}
else if (yPos == 0 && xPos == xMax){
if (mineField[yPos+1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos-1] == "B") mineField[yPos][xPos]++;
}
else if (yPos == yMax && xPos == 0){
if (mineField[yPos-1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos+1] == "B") mineField[yPos][xPos]++;
}
else if (yPos == yMax && xPos == xMax){
if (mineField[yPos-1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos-1] == "B") mineField[yPos][xPos]++;
}
else if (yPos == 0){
if (mineField[yPos][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos+1] == "B") mineField[yPos][xPos]++;
}
else if (yPos == yMax){
if (mineField[yPos][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos+1] == "B") mineField[yPos][xPos]++;
}
else if (xPos == 0){
if (mineField[yPos+1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos] == "B") mineField[yPos][xPos]++;
}
else if (xPos == xMax){
if (mineField[yPos+1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos] == "B") mineField[yPos][xPos]++;
}
else{
if (mineField[yPos+1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos+1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos] == "B") mineField[yPos][xPos]++;
if (mineField[yPos-1][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos][xPos-1] == "B") mineField[yPos][xPos]++;
if (mineField[yPos+1][xPos-1] == "B") mineField[yPos][xPos]++;
}
}
function convertToDiscordEmoji(input){
switch (input){
case 0:
return ":zero:";
case 1:
return ":one:";
case 2:
return ":two:";
case 3:
return ":three:";
case 4:
return ":four:";
case 5:
return ":five:";
case 6:
return ":six:";
case 7:
return ":seven:";
case 8:
return ":eight:";
case "B":
return ":bomb:";
default:
return ":poop:";
}
}
function getDiscordTextForm(mineField){
let mineFieldString = "Total mines: " + minesToPlace + "\n";
for (let i = 0; i < ySize; i++){
for (let j = 0; j < xSize; j++){
mineFieldString += ("||" + convertToDiscordEmoji(mineField[i][j]) + "|| ");
}
mineFieldString += "\n";
}
return mineFieldString;
}
function changeHeader(){
let image = document.querySelector("#header");
let imageNumber = image.src.slice(-5,-4);
let newImage = "images/header-";
if (imageNumber == 1 || imageNumber == 3){
newImage = newImage + "2.png";
goingRight = !goingRight;
}
else if (imageNumber == 2 && goingRight){
newImage += "3.png";
}
else if (imageNumber == 2 && !goingRight){
newImage += "1.png";
}
image.setAttribute("src", newImage);
}
function generateAndDisplay(){
let input = document.querySelector("#rowsInput").value;
if (!verifyDimension(input)){
//alert("ERROR: Rows value should be from 1 to 30, inclusive");
return;
}
ySize = input;
input = document.querySelector("#columnsInput").value;
if (!verifyDimension(input)){
//alert("ERROR: Columns value should be from 1 to 30, inclusive");
return;
}
xSize = input;
totalSpaces = xSize * ySize;
input = document.querySelector("#minesInput").value;
if(!verifyMinesNum(input)){
//alert("ERROR: Number of mines should be from 1 to 1 less than the size of minefield, inclusive");
return;
}
minesToPlace = input;
let minefield = setupMinefield();
fillWithMines(minefield);
updateAllSweeperValues(minefield);
let minefieldString = getDiscordTextForm(minefield);
if (!verifyChars(minefieldString)){
//alert("ERROR: Minefield is larger than the discord character limit");
minefieldString = "(Generated minefield is larger than the discord character limit.)\n" +
"(Although row and column limit is 30, if a value near the top end is used, the other dimension should be very small to compensate.)";
changeFooter("error");
}
else changeFooter("ok");
let textField = document.querySelector("#outputField");
textField.value = minefieldString;
}
function verifyDimension(input){
let num = parseInt(input);
if (num < 1 || num > 30) return false;
return true;
}
function verifyMinesNum(input){
let num = parseInt(input);
if (num < 0 || num > totalSpaces - 1) return false;
return true;
}
function verifyChars(inputString){
if (inputString.length > 2000) return false;
return true;
}
function checkErrors(){
let ySize = document.querySelector("#rowsInput").value;
let xSize = document.querySelector("#columnsInput").value;
if (this.name == "Rows"){
if (!verifyDimension(ySize)){
errorFlags.rows = true;
}
else errorFlags.rows = false;
}
if (this.name == "Columns"){
if (!verifyDimension(xSize)){
errorFlags.columns = true;
}
else errorFlags.columns = false;
}
if (errorFlags.rows == false && errorFlags.columns == false){
totalSpaces = xSize * ySize;
if (!verifyMinesNum(document.querySelector("#minesInput").value)){
errorFlags.mines = true;
}
else errorFlags.mines = false;
}
}
function updateErrorMessageAndButton(){
let errorField = document.querySelector("#errorField");
let errorMessage = "
Error:
";
if (errorFlags.rows){
errorMessage += "Number of columns must be in the range of 1 to 30
";
}
if (errorFlags.columns){
errorMessage += "Number of rows must be in the range of 1 to 30
";
}
if (!errorFlags.rows && !errorFlags.columns && errorFlags.mines){
errorMessage += "Number of mines must be in the range of 0 to (Rows * Columns) minus 1
";
}
if (!errorFlags.rows && !errorFlags.columns && !errorFlags.mines){
errorMessage = "";
document.querySelector("#generateButton").disabled = false;
changeFooter("ok");
}
if (errorMessage != "") {
document.querySelector("#generateButton").disabled = true;
changeFooter("error");
let textField = document.querySelector("#outputField");
textField.value = "";
}
errorField.innerHTML = errorMessage;
}
function changeFooter(changeTo){
let image = document.querySelector("#footer");
if (changeTo == "ok") image.setAttribute("src", "images/footer-ok.png");
if (changeTo == "error") image.setAttribute("src", "images/footer-error.png");
}
function updateAllOnPage(thisCheater = undefined){
if(this == undefined){
checkErrors.call(thisCheater);
}
else{
checkErrors.call(this);
}
updateErrorMessageAndButton();
generateAndDisplay();
}
document.body.addEventListener("click", changeHeader);
document.querySelector("button").addEventListener("click", generateAndDisplay);
document.querySelector("#rowsInput").addEventListener("change", updateAllOnPage);
document.querySelector("#columnsInput").addEventListener("change", updateAllOnPage);
document.querySelector("#minesInput").addEventListener("change", updateAllOnPage);
document.querySelector("#rowsInput").addEventListener('keyup', function(event){
if (event.key == "Enter"){
updateAllOnPage(document.querySelector("#rowsInput"));
}
});
document.querySelector("#columnsInput").addEventListener('keyup', function(event){
if (event.key == "Enter"){
updateAllOnPage(document.querySelector("#columnsInput"));
}
});
document.querySelector("#minesInput").addEventListener('keyup', function(event){
if (event.key == "Enter"){
updateAllOnPage(document.querySelector("#minesInput"));
}
});
generateAndDisplay();