Add info to txt file upon button click ASP.NET

I would like to store a int value(increases each time button is pressed) into a .txt file for each person.

I would like to store a int value(increases each time button is pressed) into a .txt file for each person.

I am clueless on how to store each individual's button value upon click. This is what i have came up with. Need help in this.

Actual question: Everybody who votes should be able to see the total number of votes as well as the vote of each candidate. You must use a file to record the vote.

@{
var dataFile = Server.MapPath(@"~/App_Data/data.txt");

string[] votesArr = File.ReadAllText(dataFile).Split(','); // your path
string toWrite = "";

for (int i = 0; i < votesArr.Length; i += 2)
{
    if (votesArr[i].Equals("Harry")) // Equals here is hardcoded, replace with parameter
    {
        votesArr[i + 1] = "" + (Int32.Parse(votesArr[i + 1]) + 1);
    }

    else if (votesArr[i].Equals("John")) // Equals here is hardcoded, replace with parameter
    {
        votesArr[i + 1] = "" + (Int32.Parse(votesArr[i + 1]) + 1);
    }

    else if (votesArr[i].Equals("May")) // Equals here is hardcoded, replace with parameter
    {
        votesArr[i + 1] = "" + (Int32.Parse(votesArr[i + 1]) + 1);
    }
    else if (votesArr[i].Equals("Jane")) // Equals here is hardcoded, replace with parameter
    {
        votesArr[i + 1] = "" + (Int32.Parse(votesArr[i + 1]) + 1);
    }

    toWrite += votesArr[i] + votesArr[i + 1];
}
File.WriteAllText(dataFile, toWrite);

}
<!DOCTYPE html>
<html>
<head>
<title>Elections</title>
</head>
<body>
<p id="1">Harry</p>
<input id="1" type="submit" value="Vote Harry">

&lt;p id="2"&gt;John&lt;/p&gt;
&lt;input id="2" type="submit" value="Vote John"&gt;

&lt;p id="3"&gt;May&lt;/p&gt;
&lt;input id="3" type="submit" value="Vote May"&gt;

&lt;p id="4"&gt;Jane&lt;/p&gt;
&lt;input id="4" type="submit" value="Vote Jane"&gt;

</body>
</html>


Goodbye Javascript! Build an Authenticated Web App in C# with Blazor + ASP.NET Core 3.0

Goodbye Javascript! Build an Authenticated Web App in C# with Blazor + ASP.NET Core 3.0

In this post, you'll see why we say goodbye JavaScript and how to build an Authenticated Web App in C# with Blazor and ASP.NET Core 3.0

Curious what the experience would be like to trade in Javascript for C# on the front end? You are about to find out!

Table of Contents

  • Build a Basic Website with ASP.NET Core 3.0 + Blazor
  • Add User Authentication your Blazor Web App
  • Set Up Your Okta Account to handle the ASP.NET Core 3.0 Blazor App
  • Configure Your Blazor App to use Okta as the External Auth Provider
  • Add User Login to your Blazor Web App UI
  • Test Okta Registration and Login for Your Blazor App

For many years, Javascript (and it’s child frameworks) have had their run of the DOM (Document Object Model) in a browser, and it took having that scripting knowledge to really manipulate client-side UI. About 2 years ago, all of that changed with the introduction of Web Assembly - which allows compiled languages to be interpreted client-side and is fully supported across all browsers now. Microsoft’s answer to this was the creation of Blazor. Allowing C# developers to build their entire stack in .NET, including UI, was an exciting proposition. For some time Blazor has been in preview but is now included as a general release on September 23rd, 2019 along with the next iteration of .NET Core - version 3.0.

In order to build with Blazor and ASP.NET Core 3.0, you need the following prerequisites installed and ready to go:

Build a Basic Website with ASP.NET Core 3.0 + Blazor

Now that you have your dev environment handy, let’s get familiar with what a basic website walkthrough would be like. There are two ways you can utilize this technology: client-side or server-side Blazor. For this example, the server-side option is the best choice for stability, as client-side Blazor is still new and working on the final release. Stay tuned for that implementation!

First, you’ll need to create a Blazor project. To get the latest Blazor project templates to work with Visual Studio or VS Code, simply install them from the command line/terminal from your base repo directory:

dotnet new -i Microsoft.AspNetCore.Blazor.Templates::3.0.0-preview9.19424.4

Visual Studio (16.3 or later) will detect that the templates have been installed and surface them to you without the need for any additional extensions. Now it’s time to scaffold your new project. From your parent directory of code repositories, execute the following command:

dotnet new blazorserver -o OktaBlazorAspNetCoreServerSide

Once it’s been run, open up the OktaBlazorAspNetCoreServerSide folder in Visual Studio Code. Once loaded, if you look in the bottom right-hand corner of the IDE you will see a permission request to add assets to the build. Select Yes.

Now that everything has been loaded up, return to your command line/terminal and run the project.

dotnet run

Launch your browser of choice and navigate to https://localhost:5001. You should see a templated website.

Add User Authentication your Blazor Web App

ASP.NET Core 3.0 has brought along with it some hefty changes to the libraries and dependencies from previous versions of .NET Core. To get started with using an external OAuth provider, like Okta, there is a NuGet package you need to add to the project. Fire up your command line/terminal window in VS Code and add the Okta .NET SDK:

dotnet add package Okta.Sdk --version 1.4.0

In 3.0, ASP.NET Core ships as part of the .NET Core shared framework. The metapackage that was used for 2.x apps is no longer used. The first line of your project file that references the Web SDK is what pulls in the shared assemblies for ASP.NET Core.

For user authentication with OAuth, there is an additional layer of information you will use, called Open ID Connect (OIDC). While much of handling authentication is baked into the new 3.0 framework, OIDC is not included, so you’ll need to add a quick reference to that.

dotnet add package Microsoft.AspNetCore.Authentication.OpenIdConnect --version 3.0.0-preview9.19424.4

Authentication works by redirecting users to the Okta website, where they will log in with their credentials, and then be returned to your site via the URL you will configure in the next section. Add the following code to the very top of your appsettings.json file, inside of the first brackets, and separate it from the rest of the settings by adding a comma after it.

"Okta": {
   "Issuer": "https://okta.okta.com/oauth2/default",
   "ClientId": "{yourClientId}",
   "ClientSecret": "{yourClientSecret}"
 }

Your file should look like this:

Just to make sure everything still can run, go ahead and execute dotnet run again.

Set Up Your Okta Account to handle the ASP.NET Core 3.0 Blazor App

Execute the following steps to configure Okta so that users can register themselves for an account.

  1. From the Administrative Dashboard, hover over Users and click Registration
  2. Click Enable Registration
  3. Save the changes

Once you have access to your account you can proceed to the Dashboard using a link like the one below: https://okta.okta.com/admin/dashboard

On the Dashboard, click Applications in the main menu and on the Application screen, click Add Application. Then select Web and click Next.

On the Create New Application screen, set the following values:

Click Done, then click Edit next to General Settings on your newly created Okta app. Edit the following values: Logout redirect URIs: https://localhost:5001/signout-callback-oidc Initiate login URI: https://localhost:5001/authorization-code/callback

Once you’ve saved those values, scroll down and take note of the ClientID and ClientSecret.

ClientId refers to the client ID of the Okta application ClientSecret refers to the client secret of the Okta application Issuer will need the text {yourOktaDomain} replaced with your Okta domain, found at the top-right of the Dashboard page.

You will use your Okta account settings to update those values in the appsettings.json file in your project. For an even more secure way to store those values

Configure Your Blazor App to use Okta as the External Auth Provider

Great! Now that Okta has been configured and is ready to go, there are a few changes that need to be made to the application startup.

Add these using statements to your Startup.cs file:

using Microsoft.AspNetCore.Authentication.OpenIdConnect; 
using Microsoft.AspNetCore.Authentication.Cookies; 
using Microsoft.IdentityModel.Tokens;

Replace all the code in the ConfigureServices method with the code below.

public void ConfigureServices(IServiceCollection services)
{
   services.AddRazorPages();
   services.AddServerSideBlazor();
   services.AddSingleton<WeatherForecastService>();
   services.AddAuthorizationCore();
   services.AddAuthentication(sharedOptions =>
   {
       sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
       sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
       sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
   })
   .AddCookie()
   .AddOpenIdConnect(options =>
   {
       options.ClientId = Configuration["okta:ClientId"];
       options.ClientSecret = Configuration["okta:ClientSecret"];
       options.Authority = Configuration["okta:Issuer"];
       options.CallbackPath = "/authorization-code/callback";
       options.ResponseType = "code";
       options.SaveTokens = true;
       options.UseTokenLifetime = false;
       options.GetClaimsFromUserInfoEndpoint = true;
       options.Scope.Add("openid");
       options.Scope.Add("profile");
       options.TokenValidationParameters = new TokenValidationParameters
       {
           NameClaimType = "name"
       };
   });
}

ASP.NET Core 3.0 has new options to configure the services in this file. UseAuthorization has been newly added to 3.0 project templates.

In the Configure() method of your Startup.cs file add this line just before the app.UseEndpoints() method:

app.UseAuthentication();
app.UseAuthorization();

In this example, you'll see there's a new UseEndpoints method in Startup.cs. This is what enables the new endpoint routing system in ASP.NET Core. All 3.0 project templates use that now. Think of this as a more performant routing system.

Add User Login to your Blazor Web App UI

Time to add some user personalization to this app! Open Shared/MainLayout.razor and add the following HTML right before the About link.

<AuthorizeView>
<Authorized>
           <a href="Identity/Account/Manage">Hello, @context.User.Identity.Name!</a>
           <a href="Identity/Account/LogOut">Log out</a>
   </Authorized>
   <NotAuthorized>
           <a href="Identity/Account/Register">Register</a>
           <a href="Identity/Account/Login">Log in</a>
   </NotAuthorized>
</AuthorizeView>

Using <AuthorizeView> is the easiest way to access authentication data, and is useful when you need to display a user’s name. The <AuthorizeView> component exposes a context variable of type AuthenticationState. In order to add this state to our app, open App.razor and wrap the HTML you see with <CascadingAuthenticationState> tags at the parent level. It should look like this:

<CascadingAuthenticationState>
   <Router AppAssembly="@typeof(Program).Assembly">
       ...
   </Router>
</CascadingAuthenticationState>

Test Okta Registration and Login for Your Blazor App

That’s it! To test it out, go back to the command line/terminal and execute dotnet run.

Then navigate to http://localhost:5001 in your browser. Click Login and you should be redirected to the Okta Sign-In Page.

Because you configured your Okta org for self-registration, there should be an option at the bottom of the widget to allow users to register for a new account.

Now you have a website with a working login and user registration form. Your website also allows users to recover lost passwords. By repeating these steps you can create a network of tools that your users can access all with the same login.

All of that and not one line of Javascript. The future is looking bright for C#, give it a go with Blazor!

Thanks for reading

If you liked this post, please do share/like it with all of your programming buddies!

Follow us on Facebook | Twitter

Further reading

JavaScript Programming Tutorial - Full JavaScript Course for Beginners

Blazor CRUD Using Google Cloud Firestore

Build amazing web apps with ASP.NET Core 3.0

Create a desktop app with Electron, React and C#

Originally published at https://developer.okta.com



Using Parcel.js in an ASP.NET Core Application

Using Parcel.js in an ASP.NET Core Application

In this post, we’re going to take an ASP.NET website template that uses Bootstrap 4 and set it up to use Parcel-generated bundles instead.

In this post, we’re going to take an ASP.NET website template that uses Bootstrap 4 and set it up to use Parcel-generated bundles instead.

Parcel.js is a “Blazing fast, zero configuration web application bundler.” In this post, we’re going to take an ASP.NET Core website template that uses Bootstrap 4 and set it up to use Parcel-generated bundles instead.

ASP.NET Core supports bundling and minifying static assets at design-time using the community supported BuildBundlerMinifier package that can be configured in a bundleconfig.json file. However it’s not well suited for scenarios that would benefit from a deploy-time bundling strategy, i.e. assets are built during deployment and output files are not checked in.

This is where Parcel.js comes in. Parcel is a “Blazing fast, zero configuration web application bundler.” The zero-configuration bit is its major selling point because it allows you to get started with minimal effort.

In this post, we’re going to take an ASP.NET website template that uses Bootstrap 4 and set it up to use Parcel-generated bundles instead.

Create & Set Up a New ASP.NET Project

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
 	{
  "name": "aspnet-parcel-exp",
  "private": true,
  "version": "0.1.0"
}


  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
javascriptnpm install --save-dev [email protected]

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]
npm install [email protected]

If everything went right, your package.json should look something like this:

{
  "name": "aspnet-parcel-exp",
  "private": true,
  "version": "0.1.0",
  "devDependencies": {
    "parcel-bundler": "^1.11.0"
  },
  "dependencies": {
    "bootstrap": "^4.2.1",
    "jquery": "^3.3.1",
    "jquery-validation": "^1.19.0",
    "jquery-validation-unobtrusive": "^3.2.11",
    "popper.js": "^1.14.7"
  }
}


Set Up an Asset Bundle Using Parcel.js

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
 	/AspNetParcelExp/ # project root
  - .sassrc       # sass configuration
  - assets/       # front end assets root
    - scss/       # Place for all styles
      - site.scss
    - js/         # Place for all scripts
      - site.js
    - bundle.js   # Entry point for our output bundle


  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
// Import styles  
import './scss/site.scss'  

// Setup jquery
import $ from 'jquery'
window.$ = window.jQuery = $

// Import other scripts
import 'bootstrap'  
import 'jquery-validation'  
import 'jquery-validation-unobtrusive'  

import './js/site'


We import everything we depend on. ‘bootstrap’ for example refers to the …/node_modules/bootstrap/ folder. If you want to import a specific file from a package only, you may do that too. The above code should be straightforward, except for maybe jQuery, which I’ll explain in a bit.

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
 	{
  "includePaths": [
    "./node_modules/"
  ]
}


This will allow referencing package folders without a full path to it. See parcel-bundler/parcel#39 for more information.

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
 	@import "~bootstrap/scss/bootstrap";


You may also just include the bootstrap SCSS files that you actually need to keep the output size down. Since we’re trying to replicate the template, we could also paste the code in the original template’s site.css here after the line.

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
 	"scripts": {
  "build": "parcel build assets/bundle.js --out-dir wwwroot/dist/",
  "watch": "parcel watch assets/bundle.js --out-dir wwwroot/dist/"
},

This adds scripts that can be invoked as npm run build to build, for example. It passes the bundle.js entry point to Parcel, and instructs it to generate output files in the wwwroot/dist/ using the --out-dir option.

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
npm run build

You should now see a bundle.css, bundle.js and a bundle.map file in the wwwroot/dist directory (the directory we specified for the build script above). It’s a good idea to ignore the wwwroot/dist from version control.

  1. Create a web project that uses Razor Pages. To do this on the command line, run:
  2. dotnet new webapp --name AspNetParcelExp cd AspNetParcelExp
  3. Delete the folders under wwwroot. (You may delete this later on, if you want it for reference — our goal is to generate these files using Parcel and use those instead.)
  4. Install npm Dependencies
  5. Add a package.json file to the project root like the following:
 	<script src="~/dist/bundle.js" 
        asp-append-version="true"></script>
 	And replace the stylesheet <link> tags with:
 	<link rel="stylesheet" 
      href="~/dist/bundle.css" 
      asp-append-version="true" />


That’s it. If you did everything right, running the program should display the same output as with the old files.

If it feels like a lot of work, it’s probably because you aren’t familiar with the npm, SCSS, etc., so take your time.

Watching Changes

Rather than running npm run build each time you make changes, you can use HMR (Hot Module Replacement), which will detect pages and reload for you, so that you don’t have to do it.

Open a new terminal instance and run npm run watch. Keep this running while performing any dev changes — it’ll speed you up.

Add a Pre-Publish Task

Add the following to the AspNetParcelExp.csproj file right before the closing

</Project> tag:
<Target Name="ParcelBeforePublish" 
        BeforeTargets="PrepareForPublish">
  <Exec Command="npm run build" />
</Target>


Now, every time you create a publish package, it will run the npm build script. This is particularly important in Continuous Delivery scenarios, because the wwwroot/dist is (usually) not under version control, and the build environment needs to build the files before deploying. You may test this step using dotnet publish: you’ll see output from parcel-bundler.

If you want the task to be run every time is the project is built, change PrepareForPublish to BeforeBuild.

A Note on CommonJS Modules

The parcel-bundler generates a CommonJS module, which means it doesn’t pollute the global window object. Now this can be a problem sometimes, because some libraries — particularly the old ones — have always been polluting window.

Take jQuery for instance. Libraries that require jQuery perform a test on the window object to check if it’s got a jQuery or a $ property. Since CommonJS libraries don’t pollute window, these checks will fail. So we’ll need to manually pollute the window object ourselves. We did that for jquery in bundle.js using:

import $ from 'jquery'
window.$ = window.jQuery = $

This is one thing you need to remember when using Parcel.js or other similar bundlers.

A few pointers and ideas

  • You do not have to use SCSS. LESS or even plain CSS is completely fine.
  • Parcel.js doesn’t have a config file of its own, unlike Grunt or webpack. You may, however, have config files for each tool, and parcel-bundler will honor them. E.g. tsconfig.json for typescript, .sassrc for SCSS, etc.
  • Parce.js has built-in support for PostCSS. For example, to automatically add CSS prefixes to the generated output using the autoprefixer-postcss plugin, add the following to .postcssrc at the project root:
 	{ 
  "plugins": { 
    "autoprefixer": true 
  } 
}


  • You do not have to use SCSS. LESS or even plain CSS is completely fine.
  • Parcel.js doesn’t have a config file of its own, unlike Grunt or webpack. You may, however, have config files for each tool, and parcel-bundler will honor them. E.g. tsconfig.json for typescript, .sassrc for SCSS, etc.
  • Parce.js has built-in support for PostCSS. For example, to automatically add CSS prefixes to the generated output using the autoprefixer-postcss plugin, add the following to .postcssrc at the project root:

Building a minesweeper game using Javascript, HTML and CSS

Building a minesweeper game using Javascript, HTML and CSS

In this article, you'll learn how to build minesweeper using JavaScript, HTML and CSS. I also used jQuery, a JavaScript library that is helpful for interacting with html. Whenever you see a function call with a leading dollar sign, that is jQuery at work

In this article, you'll learn how to build minesweeper using JavaScript, HTML and CSS. I also used jQuery, a JavaScript library that is helpful for interacting with html. Whenever you see a function call with a leading dollar sign, that is jQuery at work

If you want to learn how to build minesweeper with JavaScript, the first step is understanding how the game works. Let’s jump right in and talk about the rules.

Rules of the Game
  1. The minesweeper board is a 10 x 10 square. We could make it other sizes, like the classic Windows version, but for demonstration purposes we will stick to the smaller, “beginner” version of the game.
  2. The board has a predetermined number of randomly placed mines. The player cannot see them.
  3. Cells can exist in one of two states: opened or closed. Clicking on a cell opens it. If a mine was lurking there, the game ends in failure. If there is no mine in the cell, but there are mines in one or more of its neighboring cells, then the opened cell shows the neighboring mine count. When none of the cell’s neighbors are mined, each one of those cells is opened automatically.
  4. Right clicking on a cell marks it with a flag. The flag indicates that the player knows there is a mine lurking there.
  5. Holding down the ctrl button while clicking on an opened cell has some slightly complicated rules. If the number of flags surrounding the cell match its neighbor mine count, and each flagged cell actually contains a mine, then all closed, unflagged neighboring cells are opened automatically. However, if even one of these flags was placed on the wrong cell, the game ends in failure.
  6. The player wins the game if he/she opens all cells without mines.
Data Structures

Cell

JavaScript code representing a minesweeper cell.

Each cell is an object that has several properties:

  • id: A string containing the row and column. This unique identifier makes it easier to find cells quickly when needed. If you pay close attention you will notice that there are some shortcuts I take related to the ids. I can get away with these shortcuts because of the small board size, but these techniques will not scale to larger boards. See if you can spot them. If you do, point them out in the comments!
  • row: An integer representing the horizontal position of the cell within the board.
  • column: An integer representing the vertical position of the cell within the board.
  • opened: This is a boolean property indicating whether the cell has been opened.
  • flagged: Another boolean property indicating whether a flag has been placed on the cell.
  • mined: Yet another boolean property indicating whether the cell has been mined.
  • neighborMineCount: An integer indicating the number of neighboring cells containing a mine.

Board

JavaScript code representing our game board.

Our board is a collection of cells. We could represent our board in many different ways. I chose to represent it as an object with key value pairs. As we saw earlier, each cell has an id. The board is just a mapping between these unique keys and their corresponding cells.

After creating the board we have to do two more tasks: randomly assign the mines and calculate the neighboring mine counts. We’ll talk more about these tasks in the next section.

Algorithms

Randomly Assign Mines

JavaScript code for randomly assigning mines to cells.

One of the first things we have to do before a game of minesweeper can be played is assign mines to cells. For this, I created a function that takes the board and the desired mine count as parameters.

For every mine we place, we must generate a random row and column. Furthermore, the same row and column combination should never appear more than once. Otherwise we would end up with less than our desired number of mines. We must repeat the random number generation if a duplicate appears.

As each random cell coordinate is generated we set the *mined *property to true of the corresponding cell in our board.

I created a helper function in order to help with the task of generating random numbers within our desired range. See below:

Helper function for generating random integers.

Calculate Neighbor Mine Count

JavaScript code for calculating the neighboring mine count of each cell.

Now let’s look at what it takes to calculate the neighboring mine count of each cell in our board.

You’ll notice that we start by looping through each row and column on the board, a very common pattern. This will allow us to execute the same code on each of our cells.

We first check if each cell is mined. If it is, there is no need to check the neighboring mine count. After all, if the player clicks on it he/she will lose the game!

If the cell is not mined then we need to see how many mines are surrounding it. The first thing we do is call our **getNeighbors **helper function, which returns a list of ids of the neighboring cells. Then we loop through this list, add up the number of mines, and update the cell’s *neighborMineCount *property appropriately.

Won’t you be my neighbor?

Let’s take a closer look at that **getNeighbors **function, as it will be used several more times throughout the code. I mentioned earlier that some of my design choices won’t scale to larger board sizes. Now would be a good time to try and spot them.

JavaScript code for getting all of the neighboring ids of a minesweeper cell.

The function takes a cell id as a parameter. Then we immediately split it into two pieces so that we have variables for the row and the column. We use the **parseInt **function, which is built into the JavaScript language, to turn these variables into integers. Now we can perform math operations on them.

Next, we use the row and column to calculate potential ids of each neighboring cell and push them onto a list. Our list should have eight ids in it before cleaning it up to handle special scenarios.

A minesweeper cell and its neighbors.

While this is fine for the general case, there are some special cases we have to worry about. Namely, cells along the borders of our game board. These cells will have less than eight neighbors.

In order to take care of this, we loop through our list of neighbor ids and remove any id that is greater than 2 in length. All invalid neighbors will either be -1 or 10, so this little check solves the problem nicely.

We also have to decrement our index variable whenever we remove an id from our list in order to keep it in sync.

Is it mined?

Okay, we have one last function to talk about in this section: isMined.

JavaScript function that checks if a cell is mined.

The **isMined **function is pretty simple. It just checks if the cell is mined or not. The function returns a 1 if it is mined, and a 0 if it is not mined. This feature allows us to sum up the function’s return values as we call it repeatedly in the loop.

That wraps up the algorithms for getting our minesweeper game board set up. Let’s move on to the actual game play.

Opening A Cell

JavaScript code that executes when a minesweeper cell is opened.

Alright let’s dive right into this bad boy. We execute this function whenever a player clicks on a cell. It does a lot of work, and it also uses something called recursion. If you are unfamiliar with the concept, see the definition below:

Recursion: See recursion.

Ah, computer science jokes. They always go over so well at bars and coffee shops. You really ought to try them out on that cutie you’ve been crushing on.

Anyways, a recursive function is just a function that calls itself. Sounds like a stack overflow waiting to happen, right? That’s why you need a base case that returns a value without making any subsequent recursive calls.

Our function will eventually stop calling itself because there will be no more cells that need to be opened. We could have written this code without recursion, but I thought you all might want to see an example of it in action.

Handle Click Explained

The **handleClick **function takes a cell id as a parameter. We need to handle the case where the player pressed the ctrl button while clicking on the cell, but we will talk about that in a later section.

Assuming the game isn’t over and we are handling a basic left click event, there are a few checks we need to make. We want to ignore the click if the player already opened or flagged the cell. It would be frustrating for the player if an inaccurate click on an already flagged cell ended the game.

If neither of those are true then we will proceed. If a mine is present in the cell we need to initiate the game over logic and display the exploded mine in red. Otherwise, we will open the cell.

If the opened cell has mines surrounding it we will display the neighboring mine count to the player in the appropriate font color. If there are no mines surrounding the cell, then it is time for our recursion to kick in. After setting the background color of the cell to a slightly darker shade of gray, we call **handleClick **on each unopened neighboring cell without a flag.

Helper Functions

Let’s take a look at the helper functions we are using inside the **handleClick **function. We’ve already talked about getNeighbors, so we’ll skip that one. Let’s start with the **loss **function.

JavaScript code that gets called whenever the player has lost the game.

When a loss occurs, we set the variable that tracks this and then display a message letting the player know that the game is over. We also loop through each cell and display the mine locations. Then we stop the clock.

Second, we have the **getNumberColor **function. This function is responsible for giving us the color corresponding to the neighboring mine count.

JavaScript code that gets passed a number and returns a color.

I tried to match up the colors just like the classic Windows version of minesweeper does it. Maybe I should have used a switch statement, but I already took the screen shot, and it’s not really a big deal. Let’s move on to what the code looks like for putting a flag on a cell.

Flagging A Cell

JavaScript code for putting a flag on a minesweeper cell.

Right clicking on a cell will place a flag on it. If the player right clicks on an empty cell and we have more mines that need to be flagged we will display the red flag on the cell, update its flagged property to true, and decrement the number of mines remaining. We do the opposite if the cell already had a flag. Finally, we update the GUI to display the number of mines remaining.

Opening Neighboring Cells

JavaScript code for handling ctrl + left click

We have covered the actions of opening cells and marking them with flags, so let’s talk about the last action a player can take: opening an already opened cell’s neighboring cells. The **handleCtrlClick **function contains the logic for this. This player can perform this action by holding ctrl and left clicking on an opened cell that contains neighboring mines.

The first thing we do after checking those conditions is build up a list of the neighboring flagged cells. If the number of flagged cells matches the actual number of surrounding mines then we can proceed. Otherwise, we do nothing and exit the function.

If we were able to proceed, the next thing we do is check if any of the flagged cells did not contain a mine. If this is true, we know that the player predicted the mine locations incorrectly, and clicking on all of the non-flagged, neighboring cells will end in a loss. We will need to set the local *lost *variable and call the **loss **function. We talked about the **loss **function earlier in the article.

If the player did not lose, then we will need to open up the non-flagged neighboring cells. We simply need to loop through them and call the **handleClick **function on each. However, we must first set the *ctrlIsPressed *variable to false to prevent falling into the **handleCtrlClick **function by mistake.

Starting A New Game

We are almost done analyzing all of the JavaScript necessary to build minesweeper! All that we have left to cover are the initialization steps necessary for starting a new game.

JavaScript code for initializing minesweeper

The first thing we do is initialize a few variables. We need some constants for storing the html codes for the flag and mine icons. We also need some constants for storing the board size, the number of mines, the timer value, and the number of mines remaining.

Additionally, we need a variable for storing if the player is pushing the ctrl button. We utilize jQuery to add the event handlers to the document, and these handlers are responsible for setting the *ctrlIsPressed *variable.

Finally, we call the **newGame **function and also bind this function to the new game button.

Helper Functions

JavaScript code for starting a new game of minesweeper.

Th **newGame **function is responsible for resetting our variables so that our game is in a ready-to-play state. This includes resetting the values that are displayed to the player, calling initializeCells, and creating a new random board. It also includes resetting the clock, which gets updated every second.

Let’s wrap things up by looking at initializeCells.

JavaScript code for attaching click handlers to cells and checking for the victory condition.

The main purpose of this function is to add additional properties to our html game cells. Each cell needs the appropriate id added so that we can access it easily from the game logic. Every cell also needs a background image applied for stylistic reasons.

We also need to attach a click handler to every cell so that we can detect left and right clicks.

The function that handles left clicks calls handleClick, passing in the appropriate id. Then it checks to see if every cell without a mine has been opened. If this is true then the player has won the game and we can congratulate him/her appropriately.

The function that handles right clicks calls handleRightClick, passing in the appropriate id. Then it simply returns false. This causes the context menu not to pop up, which is the default behavior of a right click on a web page. You wouldn’t want to do this sort of thing for a standard business CRUD application, but for minesweeper it is appropriate.

Conclusion

Congrats on learning how to build minesweeper with JavaScript! That was a lot of code, but hopefully it makes sense after breaking it up into modules like this. We could definitely make more improvements to this program’s reusability, extensibility, and readability. We also did not cover the HTML or CSS in detail. If you have questions or see ways to improve the code, I’d love to hear from you in the comments!