How To Build A Minesweeper Clone With JavaScript

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
learning how to build projects is really hard which is why in this video i'm not only going to show you how to build out a mindsuper clone but i'm also going to break it down step by step exactly what i'm doing my thought process and why i do different things that way you can actually learn how to build projects on your own this video actually comes straight from my javascript simplified course if you're interested in taking your javascript skills to the next level learning how to connect the dots and really start building projects on your own you're definitely going to want to check out that course it'll be linked down in the description below if you use the code early you're going to get 20 off but that's only good for the next couple days so make sure you take advantage of that if you're interested [Music] if you go down in the description of this video you're going to see that i have the before code linked it's just a really simple html file and a css file that contains all of the code that you're going to need and really the only important thing to note about this css file if you scroll all the way down here the section down here where we have data status hidden mine number and marked these are statuses that you need to apply to the different grid tiles in order to give them their specific styles so hidden is going to give you a tile that looks like this if you right click on a tile it'll mark it which is this marked style if you click on a tile and it's a mine it's going to give you this red style here and if we refresh that we actually have a fresh game we click on a tile as you can see a tile that has a number on it is going to have the number style applied to it so that's what these different styles are that's pretty much the only thing in the css that you need to be aware of also i want to kind of go over the rules of minesweeper so that you're familiar with them whenever we mark a title this mine's left number is going to decrement and it's okay if this number goes negative as you can see if i mark more than 10 it's going to go negative that is perfectly okay and if you mark a tile you can't click on it with the left click so to mark a tile you right click on it and to open up a tile and reveal it you left click on it and essentially if we can find here a open space i didn't find any there so let's just refresh if we click on a space where there's adjacent tiles next to it that are all empty then it'll reveal all of those tiles to you and essentially the way minesweeper works is there's a specific number of mines in our case 10 is the default we're using and every number tells you how many tiles or how many mines i'm sorry are next to this in the nine by or three by three grid around it so including diagonals so this one means that there's one mine adjacent to this one which in our case is this tile here this two means that there's two mines adjacent to it so it could be any of those including diagonals and so on so you know we could mark here we could mark here we can mark here open these up and so on so that's essentially how minesweeper works and the goal of the game is if you clear out all of the tiles if we just kind of go through here and we clear out all the tiles and just imagine that we actually won the game it'll say that we won and then we can refresh to restart or if we click on a tile that for example is a red tile of mine then it'll reveal all the mines to us and it'll tell us we lose and we can't click on anything else so we just have to refresh and start over again and that right there is all the knowledge you need in order to build out this minesweeper game yourself so if you want to you can try to build this out yourself but if you feel like you get stuck at all you can just come back and watch this video any point and at the very beginning of this video i'm going to explain my thought process of how i get started building this minesweeper game i'm just going to create a really simple script.js file for our javascript and in here i'm just going to start writing a bunch of comments describing exactly how i think this game is going to work so the first thing we need to do is populate the board because as you can see our board is empty there's no tiles inside of our board so number one we need to populate a board with tiles slash minds that's obviously the first thing that we need to do and then once we have the board we need to be able to left click and right click on tiles so we need to be able to left click on tiles right click on tiles that's pretty self-explanatory and going along with these lines if we just kind of go with left clicking on a tile this is going to reveal to us so we could say reveal tiles and by right clicking on a tile we're essentially marking a tile so we need to be able to mark tiles as well finally kind of the last thing that we need to do here is we need to be able to check for win slash loss we need to say do you win did you lose and we also need to be able to check that constantly because as soon as we click on a bad tile or we finish up clicking on all the tiles then we know that we've either won or lost and we want to be able to show a message telling them also before we get started i kind of want to think about the logic of this actual game and how to structure the code there's kind of two parts to this game there's the logic behind the scenes of like checking tiles that are json to figure out what number these things are checking if it's a mine if it's not of mine all of this logic portion is one part of the game and the other part of the game is the actual display of the game itself which you know is giving us the colors and the numbers on the screen and the ability to left click and right click so i kind of want to separate these two different sections like the game logic itself from the actual display of the game i'm going to create a separate file which i just call minesweeper.js and this is where i'm going to put all of the logic so i'm just going to say logic in here and this script.js file if we just move this down a little bit this is going to be for all the display or like the ui so that way our ui is separated from the actual logic of the game this just makes it easier to write our code easier to test our code and so on so if we go back to the script we can kind of see that the very first step is going to be to create a board with titles and minds and this is two parts there's a logic portion and then there's actually a display portion for showing the board the first part the logic part is just creating the board so we can do that in this minesweeper class let's just create a function called create board and this is going to take the board size because we need to know how big our board is it's a square so we just need to know one direction and then we want to have the number of mines these are things that we can configure when we create the board because we need to know how many mines to put on the board and also how big our board overall is going to be now the way that we're going to create this board is actually going to be an array of arrays so let's just come down here and say const board is equal to an empty array and this is going to be the start of our board and each row in our board is another array so you can kind of imagine if we had a 2x2 board we could have something that looks like this you know a one would represent a mine and a zero would represent not a mine in this very simplified case but you can see we have an array of arrays where each entry in the board array is a row and each entry in the row is a cell from left to right so the actual board array looks very similar to the board on screen which will just make it easier to work with everything that's going on so by default our board is going to be empty and then for each row in our case each board size we need to loop through that so we can just say four let x because this is our x direction equals zero and x is less than the size of our board what we need to do is just add one to x so a very simple for loop and we also need to loop through the y direction so i'm going to copy this for loop but this time we're going to do the y direction here make sure all of this is y and since we have a perfect square we can use board size for both of these then for every single x i want to create a new row so we can say row is equal to an empty array and then inside of here i want to create a new tile so we can just say const tile is equal to an object and we know this object is going to have an x and a y property we can use that shorthand notation to specify our x and y and we could just say row.push tile and for now that gives us a board if we make sure here that we push our row into our board so if we kind of condense this for loop you can see we loop over all of our rows we create our row and then we add our row to the board and then here what we're doing is we're creating each tile and adding that into our row for this inner for loop and then finally at the bottom just return our board if we export this function that we can use it inside of our script here we can just say at the top import create board from and we want to get from minesweeper.js make sure that's a period there we can just say console.log create board and let's just say we're going to do a two by two board something very simple to get started with and now all we need to do is make sure we include a script tag that is going to be to script dot js and the type is equal to module so now if we just inspect our page over here we should have that board printed out to the console as you can see we have an array two wide and another array inside of each of those which is two wide and as you can see this first one has x0 y0 x0 y1 and x1 y0 x1 y1 so we essentially created a grid that's 2x2 that fills up all this available space now the next thing that we need to do back in our minesweeper here is actually give us an element that we can display on our screen we need to be able to display a tile on our screen so let's create that element this element very simply is just document dot create element and we're just going to use a simple div now if you remember when i talked about the css down here at the bottom we have our different statuses hidden mine number and marked well i want to create those statuses inside of a const variable so we can just say const tile statuses is equal to and remember we have different styles we have here hidden mine number marked so hidden is going to be equal to the text hidden and this text here is just matching up to the text in our css then we're going to have mine is equal to mine number equal to number and finally marked is equal to oops mark let's make sure this is actually called marked so we'll say marked there we go so we have our different statuses and by default all of our elements are hidden so we can just say element.dataset.status is going to be equal to tilestatuses.hidden by default we want to make this hidden and we can just add that element to our tile so now what happens is if we just accept a little spacing here save this make sure we inspect our page we go over to our console you can see that we now have this element which is a div and this div if we go all the way to the dataset property here has a status of hidden which is going to make it show up hidden when we put it on our grid so obviously the next step is to add it to our grid inside the script here let's just put this inside of a variable we also need to be able to get the board from our html which has here a class of board so what we can just do is say const board element equals document dot get or i will say just query selector of dot board and now we can add each one of these board elements to this board so we need to loop through our board so we can say board dot for each row and then for each row we need to loop through that to get the individual tiles because we have a multi-level array and then we can say board element dot append tile dot element because that's the element that we created inside this mine sweeper here so if we save this you can see that we have these elements being appended to our grid they're very small right now though the reason these are so small is actually because of another thing in our css if we scroll up here aways you'll notice that our board is determined by this size variable and the size variable is currently not set we need to set this size css variable inside of our javascript and right now our board is two by two we've manually set that let's just create some variables called board size which we'll set to two and const number of mines which we're going to set to 2 because that's what we're using here we can say board size and number of mines that way we have these two default variables and then on our board element we say board element dot style now all we need to do is just set property and that property is called hyphen hyphen size we want to set it equal to our board size that essentially tells us that we have a two by two grid and if we change this to b4 for example we've now created a four by four grid or if we bump it all the way up to 10 we now have a 10 by 10 grid on our screen just like we do in this example here i just want to clean this up a little bit so we're going to move some spacing we'll put our style down here below so this is just setting up our board this is setting up our board this is getting some variables this is our constant variables everything still works and now over here we need to add some additional functionality to our tile because when we click on a tile right click or left-click we need to change the status of that tile and right now we have to set the element.dataset.status which is kind of a pain it's not the most easy way so let's just create a getter for our status and this is just going to return our element.dataset.status and let's do a setter as well so we could just say set status which is going to take in a value and we just want to return this i'm sorry not return we want to take this element.dataset.status we want to set it equal to that value and here we just need to make sure we use this so now we can actually get and set the status of our tile directly without having to go through this element.dataset.status you know mumbo-jumbo that's just kind of a lot so now if we just inspect over here and we go to our console make sure that we're logging out our board just like this and we just look at one of our random tiles you can see if we click on status it's going to print out hidden because it's getting that from our element that data set right here dot status is doing that all for us the next thing to do is to actually populate our board with all of the different minds right now we're not doing anything with our minds so the way i want to do this is with a property on our title called mind which will be true or it'll be false depending on if it is a mine or not but for now let's just manually set this to true we're not we're going to do this in a little bit actually make this correct what i want to do is generate where our minds are going to go with this number of minds so we can say const mine positions is equal to a function we're going to create called get mine positions and it's going to take in our board size and the number of mines so essentially all this function is going to do is give us 10 random locations or actually in our case two random locations based on this number of mines inside of our board that are going to be mines so it's going to give us an array of values and this array of values is essentially just x y coordinates which we're going to match up with these x y coordinates here so let's create this get mind positions function function get mine positions takes board size and number of mines and in here let's just create a variable called positions set it to an empty array and then at the bottom we're going to return those positions and then here's where we're going to put all of our mine positions and you may think it's smart to just say you know let's create a loop we'll say let i equal 0 i is less than number of mines i plus plus and you may think okay inside of here we'll just generate some random numbers and put all of our mines inside of this array but the problem is is that when you generate those random numbers maybe you get x equals 1 and y equals 2 for the first spine then it keeps going third fourth fifth sixth seventh and all of a sudden you get another mind that's x equals one and y equals two so they're in the exact same location this would be a problem because then you would have two overlapping entities and we don't want that and we would have no way to know because we're just inside of a for loop so instead i'm going to be using a while loop and i'm going to check the length of our positions and while it's less than the number of minds that we want i want to continue to loop that way if for some reason we accidentally have a mind that gets generated on the same position as an already existing mine we're just going to continue going through our while loop over and over and over again so let's just create a position this position is going to have an x and it's going to have a y and these are going to use a function called random number which we're just going to generate it's going to give us a random number between 0 and the size of our element which is our board size so let's create that function random number and it's going to take a size and for now let's not worry about this function let's just assume that it works and what we need to do is we need to check does this position already exist inside of here so we can say positions dot sum this will return to us true if at least one of the elements in this array matches the thing and we need to create a new function to match position we're going to call that position match so let's create that function just like that position match and this function is going to essentially take two different positions position a and a position b and we want to check to see if they have the same coordinates so we're going to say a dot x is equal to b dot x and the a dot y is equal to b dot y if both of these are true then they're exactly the same position so we can return true from position match so up here we could say for each position which in our case we're just going to abbreviate position to p for each position we want to check if p and position are a match if they are not a match we'll put the double exclamation in the front here so if they're not a match then we're going to add this position to our array so we'll just push the position to our array and this is why we're using the while loop because if they already exist we're just going to skip the adding step and continue running through this while loop until we get one that's not a repeat and also we can use bind to simplify this code right here a little bit so instead of you know calling position match with position every single time we can say that we want to take position match dot bind we don't care what this is so we'll just pass the null we want to bind to the position to a so a will always be our position and then whatever each iteration of our loop through of positions will be is going to be passed in as b so this is just another way to write that code either way works it doesn't really matter now let's write this random number function inside of here we just want to get a random number with math.random multiply it by our size and then in order to make sure this is an integer we can just say math.floor this is going to convert this to an integer and now if we scroll all the way up here we should have some positions and we can just log them out mind positions let's make sure we don't have any other logs anywhere so let's inspect our page go to our console and now we have an array with two elements x3 y9 x6 y8 if we just refresh you can see that we now get x6 y1 x4 y1 so it's just completely random and if we change this to be you know 10 minus for example now you can see that we have 10 different elements in this array so now the final thing that we need to do inside this minesweeper function is actually set the mine so if our mind positions dot sum again we're just checking to see if at least one of these matches so we want to do that position match we can do that same bind trick again so we'll say binds to null and we're going to pass in here our x and y coordinates for our current element so all this is doing essentially is it's saying okay check to see if the positions in our mind positions if one of them matches our current x and y coordinates that's all that this code is doing if the x and y coordinates of our current tile are in the mining positions then we know this is a mine so we return true otherwise we return false and now all the way over here if we just console log our board we should be able to find some tiles that have mine set to true so let's go to the console open this up and you can see inside of here if i just expand this all of these are false go down to this one all of these are false and as you can see here we have two minds that are true so randomly there will be 10 you know set to true throughout all of these different arrays and it's completely random because we have that randomness set up for all of our functions so right here with all this code we've essentially completed step one we populated a board with tiles we have this board variable here as well as a visual representation of it and we also put in all of the minds that we need based on this number of minds really the last thing left to do is make this mind's left text actually show up properly so let's just set this to 2 for now so we can see the difference in our text if we go over to our index html you can see right here is where our text is let's just create a span that we can put the 10 inside of and we can just give it whatever we want we could say like data mine count and then inside of our code here we can say const mine count we'll actually say mine's left there we go text is equal to document dot query selector and this is going to be for mine count and then our minds left text here we can just set equal to our number of minds and of course that didn't quite work so let's make sure we got this right mind count should be data mine count and again of course this mine's left text we need to make sure we set the text content of it there we go we've changed our mind left to 2. if we put this back to 10 this will change to 10 which means in our index we don't even need a number here at all there we go it's just populating for us inside the javascript now the next thing that we need to do inside of our script is steps two and three let me make sure these are indented a little bit so we know what they go with step two is you're figuring out left clicks and step three is figuring out right clicks luckily this is actually pretty straightforward we can say tile.element we want to add an event listener for click this is going to handle our left clicks for us and when we want to handle right clicks we can't use click because this is only for left clicks but for right clicks we can say tile dot element dot add event listener or context menu context menu is what happens whenever you right click in order to make sure that right click menu like this doesn't show up we can just say e dot prevent default now if i save this and right click on a tile it doesn't actually do anything it doesn't pop up this menu so if i right click on any of these tiles we're preventing that default so essentially we're handling left clicks and right clicks so we can kind of remove this now all we have left is revealing and marking and checking for wind loss which is pretty much the bulk of everything so it may seem like a small list but this is actually quite a bit we're actually going to start with marking tiles it may seem like a great idea to start with revealing because that's kind of the main concept of the game but marking tiles is significantly easier and will give us a great head start so inside of this context menu event listener what we need to do is call a function to mark these tiles i want to define this on our minesweeper object because this is actually going to be the logic for the game so we can just say mark file is going to be a function that we create on that minesweeper and in here we just call mark tile we pass it in the tile that we want to mark so now inside of minesweeper here we can create that function export function mark tile and it's going to take in a tile that we want to mark now the very first thing we want to do inside this mark tile function is just check to see if the tile we're marking is eligible to be marked because we can only mark a tile that's hidden or we can unmark a tile that's already marked so we need to make sure we just check here if the title.status is not equal to hidden and the title.status is not equal to marked so we can just say tile status dot marked then we just want to return so essentially here we're just checking is the tile hidden or is the tile marked if it's either hidden or marked continue on otherwise we're just going to return prematurely because if it's not hidden and it's not marked then it means that it's either a mine already revealed or it's a tile that we've already revealed in its number tiles we don't want to be able to mark something that's already been revealed then down here we just need to be able to check are we marking it for the first time or are we unmarking it so if the tile dot status is equal to tile status dot marked this means we need to unmark the tile so we can say tile status is going to be equal to hidden because we're unmarking it otherwise what we need to do is just take our tile.status and we need to set it to our tile status dot marked because now we're marking this tile and that should be all the code that we need to write now if we right click on a tile you can see that it turns yellow and if we right click on it again it removes that marked syntax so we're able to mark all of these different tiles that's just because of what we did with this getter and setter up here by using this setter we're automatically setting the data set status and that data set status is tied to our css right here which changes the background color for us so by using this getter setter we made our code for setting the status really simple and it just propagates throughout all of our entire application making sure it propagates our color and everything like we would expect now the final thing i want to do is when we actually mark a tile i want to change the number here for how many mines are left because if you've marked a tile that means you're saying that there is a mine at that location so i want to remove one from this number and if we unmark something i want to add one to this number so here i want to create a new function which is called list minds left and this function is just going to be inside this file list mine's left and all this is going to do is take our board and count up all of the tiles that are essentially marked so to do that we can just say marked tiles count is equal to we're going to take our board and we're going to reduce it down to one single variable and this is going to be a count variable and we're also going to have each one of our rows inside of here all we need to do is take our count and we just want to add to our account the number of tiles that match this filter and this filter is just going to check to see if this tile is marked so we can say tile dot status is equal to tile statuses dot marked and right now we don't have access to this variable because it's not in the script file we want to import tile statuses and that's going to be coming from minesweeper so let's make sure up here we also export this just like that now if we save both these files that should work and now we have our marked tiles count as long as we make sure we default this to zero so our count starts at zero and each time we just add to our count the number of tiles if we check the length here this length variable will give us the number of tiles that match this filter so it'll just give us the number of tiles that are marked then what we can do is we can take our marked tiles count and our number of mines we just need to subtract the two so this is going to give us how many mines are left the number of mines minus the ones that we've marked as mines and all we need to do is take our mines left text we need to set the text content equal to that if i just spell that correctly now we mark a tile you can see it doesn't make any difference so clearly we have a problem in our code let's just inspect to see if we have an error of course we do tile status is not defined and that's because this is tile statuses that should hopefully fix the problem for us and now when we mark a tile you can see it's properly decrementing our number and when we unmark it it's increasing the number as we would expect also i'm going to kind of get rid of some of these console logs that we have they're just kind of cluttering up our console so there we go that cleaned those up and now our game is working as expected and marking is completely done so we can come over here and cross that off our to-do list now the next step is going to be revealing tiles which is quite a bit more complex so let's create that reveal tile function just like we did with mark tile so inside of here let's just come all the way down export function reveal tile and take in a tile and then there we go inside of here whenever we click on an element we just want to reveal the tile of that tile pretty self-explanatory so now we're calling that function every time we left click on a file and just to make sure it works let's just console log out our tile we just inspect over here into our console click on a tile it prints it out and you can see no matter which one we click on it's always properly printing out over here which is perfect so now just like we did with mark tile i want to first check to make sure the tile was eligible so if the tile dot status is not equal to tilestatus.hidden then i just want to return because we can only reveal tiles that are hidden if the tile is marked i don't want to reveal it and if it's already revealed obviously i don't want to reveal it so this can only happen to tiles that are currently hidden now the next step in this function is i want to check to see if this is a mine so if the tile is a mine then we can just say tile dot status is going to be equal to tilestatus.mine we're going to set that as a mine and we're going to exit out so if we click on a mine we're going to set the status to mine otherwise if we don't click on a mine what we need to do is just take our tile.status and we need to set it to a number so we can say dot number so now if we click on a title you can see that this one was not a mine which is why it has this number style if we click clicking eventually we're going to run into a mine which should show up as red there we go this was a mine so it has the red coloring on it now the next step is to figure out how many mines are next to a tile because this tile right here you know for example should have a one next to it because in all the squares surrounding it including diagonals there is one mind touching it so it should have the number one while if we find one that doesn't have anything next to it for example this tile here has two mines next to it should have the number two inside of it and so on we need to get all the nearby element of a tile that we click on to do that we actually need access to our board so we're gonna pass our board in here to reveal title so we can get to the neighboring tiles and inside of our script let's just make sure we pass in our board just like that now we have access to the board and we can actually get the nearby tiles and that's kind of complicated code so i'm going to create a function called nearby tiles it's just going to take in a board and the tile and we want to get all of the nearby tiles which we're going to call adjacent tiles so this function will get us all the adjacent tiles for the tile we pass in off of this particular board we could say a function nearby tiles extend a board and a tile and inside of here we want to get all the tiles that are adjacent so we can kind of start this out like we do with a lot of our functions we're going to have essentially an empty array of tiles and we're going to add to them before we return and a really easy way to do this is we know we want to get all the tiles in a 3x3 grid so we need to get the tile to the left to the right to the top bottom and the top left top right bottom right bottom left and all of those are within a 1 negative 1 to 1 offset so the tile to the left is negative 1 to the left top left is negative 1 to the left negative 1 upward and so on so we can just do a simple loop which is going to have an x offset which is equal to negative 1 to start make sure i spell that correctly we're going to say while this x offset is less than or equal to 1 because 1 is our max value we want to add 1 to our x offset and we're going to do the exact same thing but for our y offset and this is just going to be essentially the y direction as well and then we can create a tile so we can say khan's tile is equal to the element from our board which is at the x of our current tile so let's just actually destructure this we only care about the x and y so we just destructure it x plus x offset and we also want to get the y plus y offset so this tile is essentially saying okay my current x position plus whatever offset is which is between negative 1 and 1 and my current y position plus whatever the y offset is i want to get the tile at that location and then we can just add that to our tile array this may look complete but there's actually a slight bug with this issue so if we just inspect our page here we'll see that bug in just a little bit if we click on a tile in the middle it works just fine no errors but if we click on a tile in the corner for example you're going to see that we get an error cannot read property 0 of undefined and that's because right here our board x plus x offset or not our x i'm sorry our y is trying to go up negative one it's trying to get a tile that's off of our board so in order to fix this what we need to do essentially is use that optional chaining syntax where we have question mark period so it's saying okay if we have an element in this row then get the element in the y direction then we just need to check that if we have a tile we're going to add it to our list this is going to fix all those bugs so now if we go back to our console and click a title up in the corner you can see no matter what we click on in any of these corners it's always going to work and we're not getting any errors so now that we have access to our tiles let's scroll up here little ways our adjacent tiles let's get the mines that are next to it so we can say mines is equal to adjacent tiles dot filter i want to get any of the tiles that are mine and we're going to use t here so t dot mine anything that returns true there is going to be a mine and then we can just say if mines dot length equals zero then we want to do something otherwise if the mines dot length is not equal to zero so we don't need to worry about anything there we can just say that we want to take our title.element dot text content and set it to our minds.length so now whenever we click on a mine or an element i'm sorry it'll tell us how many mines are nearby as long as there's more than one so here it says there's one mine nearby and if we check this you can see there's exactly one bind in that nine by nine 2 here you can see in this 9x9 or 3x3 sorry these 9 elements there's two mines next to it same thing for this two there's these two elements and so on as you can see there's always at least the number that it says right next to it at all times and for these ones that are marked as zero you can see there's no mines next to them now really the final step for this revealing function is to handle when there's no mines because as you know in this version of the game if we just refresh this here and click when we click on an empty tile it reveals everything else that is empty as well that's adjacent to that tile we clicked on and right now when we click on an empty tile it just shows up as empty so we want to implement that logic so if the mine's length is equal to zero then what we want to do is essentially recursively call this reveal function for all of the adjacent neighbors so we can say adjacent tiles.4 each we want to call that reveal tile function and this reveal tile function takes in the board and the tile so we can use that fancy bind trick we can bind null and our board and then this for each is going to automatically pop in our tile or each individual adjacent tile as the third parameter now if we click on an empty tile if i can find one here you can see it reveals everything next to it and that's just because we're recursively calling this function over and over again so if we click on this tile for example it reveals all of these adjacent tiles and for each one of those tiles that's empty it also reveals all the adjacent tiles and it keeps on doing that over and over and over again until there's no more tiles that are empty to reveal so with that all done we've essentially completed all the logic for our game we can play through the entire game if i just click on everything you'll see that eventually we can clear out the entire board and it looks pretty good overall but right now there's no lose condition and there's no wind condition for example if i got to this location without clicking on any of the mines it should say that i won and if i got to this location and i clicked on a mine by accident then it should say that i lost so what we need to do up here is every time we reveal a tile i want to check game end i just want to see did we win did we lose what is the results so down to here i can say function check game end and if we're taking a look at our list we finished reveal tile and we're on the last step which is check for win loss so i'm going to create two variables const win and cons to lose we're going to create a function called check win and check lose we're going to pass in the board i want to check our board state to see if we won or lost and this is logic we're going to put in here so check whoops check win and we're going to say check lose these are functions on minesweeper so let's actually create them make sure that we do this up with all of our other exported functions at the top it just looks a little bit cleaner that way here we go export function check when it takes in our board let's just copy this exact thing and we're going to have for checking our lose condition so before we write out these functions let's actually continue down the logic inside of here for what we do if we win or lose so immediately if we win or if we lose we want to stop the ability for the user to click on any of these tiles because we don't want them to keep revealing things it's actually a little bit difficult to remove the event listeners that are already bound to the tile so instead we're going to take advantage of event propagation i'm going to take our entire board element i want to add an event listener to that on click and inside of here what i want to do is i want to call a function called stop prop and i want this to be in the capture phase so essentially what is going to happen is the capture phase occurs before the bubble phase so our tile elements here they're using the bubble phase so their events are going to fire after this click event and we can call this a stop prop function so we can say it's function stop prop it's going to take in e we just say e dot stop immediate propagation make sure i spell propagation correctly and call this as a function and this just stops the event from going further down so it's never going to get to our individual tiles to call these events for us and we want to make sure we also do this on context menu as well and now if we save no matter if we win or if we lose we're going to stop the event propagation so let's just say that we're going to set check win to true so if we come inside of minesweeper check when we're going to set to true to return that and now after we click on our first tile it won't let us click on any other tiles if we right click it's just going to do a normal right click because it's stopping the propagation from getting all the way down there and that's just because we're making sure we're automatically returning true here if we don't do that we can continue to you know click and right click all that we want to with no problems now the next thing that i want to do is actually change our text up here depending on if we win or we lose so we come in here we have a class of subtext we can just get that by coming up here and saying const text we'll just say message text is equal to document.query selector is dot sub text just like that and then down here we can say if we win then we want to display some text and if we lose we want to display some different text we can say message text dot text contents equals you lose i'm sorry this should say you win and down here it'll say you lose there we go so now if inside of our function of check win we automatically return true and i click it's going to change to you win if i put that inside of check lose instead now it's going to say that you lose and on top of showing the text you lose when we lose i want to reveal the position of all the minds because if i click on a mind you can see it shows all the mind positions and that's a really nice thing to know so that way that people can know if they are correct or not so to do this inside of our script if we lose take our board we're going to loop through each row we're going to take our row and loop through for each tile and all we want to do is we want to say if our tile is a mine then i want to reveal it reveal tile board and tile so now if we just set check lose to true and we click it's going to reveal all the tiles to us one interesting thing to note though if we just mark a bunch of tiles here real quick that should be enough now we click you'll notice we've count we get one two three four five six seven eight nine ten okay that was a bad example redo we mark a bunch of these hopefully a mine will be underneath of one of them i just kind of got unlucky with that last one so we marked all of these now when we click you can see we have one two three four five six seven which means three of the mines are in this yellow area i want to remove all of the marks so that way we can reveal these tiles because as you remember in our mind sweeper code when we reveal a tile we only reveal if it's hidden these marked tiles are unable to be revealed so first of all i want to say if the tile dot tile status is equal to tile statuses dot marked this should be status here then i want to mark the tile this is essentially just going to say okay if the tile is currently marked mark it again so that it becomes unmarked now if i mark a bunch of tiles and i click it's going to unmark all those tiles and if there's a mind behind any of them it'll reveal it for us so now that's essentially the logic for the display the only thing left is to actually make these functions over here for check win and lose do more than just return true and false so we're going to do check lose first it's pretty simple we just need to see is there a mine that's been revealed so board dot sum we don't see is there any it doesn't matter we just need at least one and we can return row dot sum for each one of the tiles and all we need to check is if the title.status is equal to tilestatus.mine if we have a single mine revealed then we lose so let's check that situation let's just keep clicking until we click on a mine you can see we clicked on it it said you lose and revealed all the mines that works as expected so now let's write out our winning code this is going to be a little bit more complex essentially the way we want our winning code to work is we want to check every single tile and we want to make sure that every single tire is either revealed as a number in our case with these numbers here or it is hidden or it is marked with a flag and if the tile is hidden or marked with a flag we need to make sure that it's a mine so if every single tile that's not revealed is a mine then we are a winner so to do this we need to of course say board.every because we want to make sure every tile meets this criteria so if every tile in the row which means we need to do row.every and inside of here we can say title and here we can do a return so first i want to check is the tile a number which means it's been revealed okay so t dot status is equal to tile status dot number that's good and i want to say or if the tile is a mine and it meets the following criteria so if it's a mine and it's either marked or it is hidden so if the tile that status is equal to hidden or if the tile that status is equal to marked so let's just kind of look at this code again real quick first we're saying is the tile a number tile which means it's been revealed if so good that's perfect otherwise is the tile a mine and is it either hidden or marked so this is just saying to make sure that every tile that's either hidden or marked is a mine if that's the case then we won and instead of making me go through and play the entire game to see if i win i'm just going to reduce the number of mines down to like three so hopefully if we click somewhere we should see a really simple there's a mine here here and here so this should be counting us as a win but right now it's not for some reason so let's inspect to see if we have an error and of course we do reference error t is not defined so let's come inside of here this should say tile instead of t now if i come in here and i just click we can see that there's a tile in these three locations so it says that we win if we do this one more time and we mark some of these let's just say we mark these three and then reveal the rest of these you can see again it says we win so it doesn't matter if they're marked or if they're hidden as long as the only tiles left unrevealed are mines then we win i really hope you enjoyed the process of how i took this large project and broke it down into small easy to execute tasks that eventually came together to build out the full mindsuper project if you did enjoy this and want to see other projects like this definitely check out my full javascript simplified course and use the code early to get twenty percent off but that's only good for the next couple days
Info
Channel: Web Dev Simplified
Views: 21,707
Rating: undefined out of 5
Keywords: webdevsimplified, minesweeper, minesweeper js, minesweeper javascript, minesweeper project, minesweeper clone, minesweeper javascript code, minesweeper tutorial, minesweeper js tutorial, minesweeper code tutorial, minesweeper code, minesweeper project tutorial, minesweeper js project, minesweeper javascript project, ms js, minesweeper tutorial code, minesweeper program, minesweeper programming, create minesweeper, program minesweeper, write minesweeper, build minesweeper, js
Id: kBMnD_aElCQ
Channel Id: undefined
Length: 43min 14sec (2594 seconds)
Published: Sat Apr 10 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.