'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();