Close this HELP window 
MINESWEEPER  HELP 

This minesweeper clone by parks@uh.edu

  1. About Minesweeper

    "Minesweeper was a Microsoft original, written by Robert Donner and Curt Johnson, and hasn't changed much over the years (released by MS in 1990)."

    "A game by Jerimac Ratiff named the Cube is often referred to as a predecessor of Minesweeper, although the similarities of the two do not really extend beyond the fact that both games have mines as focal point."

    http://www.techradar.com/us/news/gaming/the-most-successful-game-ever-a-history-of-minesweeper-596504

    or:

  2. How to play

    The simplist version of the game directions I found (here) says:

    1. Left click a tile to test if it is a mine. The number of mines in the areas around that tile will be revealed.
    2. Right-click a tile to plant a flag and mark a square as containing a mine.
    3. You win the minesweeper game by marking all the mines with flags.
    4. If you click on a mine, you die!

    Other instructional pages:

  3. Cheats

  4. Reasons for this minesweep clone

    This minesweep clone was written to look at some interesting programming issues that arise in proramming the game logic. Caveates for this clone:

    This clone DOES NOT provide for "chording" (Pressing BOTH left and right mouse buttons)
    This clone does NOT use the "?" (that allows suspicious cells to be marked)
    This clone does NOT protect you on your first click in the minefield.
    You CAN die on the first click.

    Get see/get code for this clone:

    1. Load the game page here;
    2. In IE: (1) click "View"; then click "Source" on the page

    Here are some of the coding issues addressed:

  5. Using a stack

    A stack is a list that is the analogy of a "stack of paper" (or a stack of anything else).

    • Items that are placed on the stack are placed on the "top of the stack" (this is called a "push")
    • Items removed from the stack are taken off the "top of the stack" (this is called a "pop")
    • A stack is said to have a last-in-first-out (LIFO) behavior. The most recent item "pushed" on to the stack is the first that can be "popped" (i.e., removed)
    • It is the opposite of a queue (a waiting line) where it behaves as a first-in-first-out (FIFO) behavior

    A stack is typically implemented as an array. The array initially has NO elements (i.e., zero length). Items are "pushed" on to the stack, thereby increasing the "length of the array". Items are "popped" off the stack and this reduces the length of the array. When the array has zero elements, the stack is "empty".

    1. stack creation

      In javascript you implement a stack named "stack" by creating an array without specifying its size:

      • stack_array_name=new Array()

        e.g., stack=New Array()

      There two javascript stack methods that can be performed are:

    2. stack_array_name.length = stack_array_name.push (1st item[,2nd item]... );

      • One or more items can be pushed onto the stack
      • The method returns the new length of the stack (i.e., stack_array_name.length)
      • This method changes the length of the stack (i.e., stack_array_name.length)
      • Items that can be pushed are: numbers, strings, arrays, boolean

    3. item_returned = stack_array_name.pop();

      • The pop method return the value (a number, string, array or boolean) from the top of the stack
      • This method changes the length of the stack by 1 (i.e., stack name.length is reduced by 1)

    4. stack length

      • stack_array_name.length
      • When the array has zero elements, the stack is "empty".

    5. code example from my minesweep clone

      function swp (ss2) // **********  process left click
      {
       // ss2 is a string with the click's "row number" followed by a comma,
       // followed by the "column number")
      
      if (running)
        {
        var v=ss2.split(",");
        rowval=parseInt(v[0]);
        colval=parseInt(v[1]);
        locv=(rowval-1)*cmax+(colval-1); // this is the image number
        tval=t2[rowval][colval]; // tval can be: -1 (a mine);
      // 0 thru 8 (number of adjacent cells with mines)
        setflags();
        if (tval==0)
           {
      //
      //    IF THE CELL IS EMPTY (i.e., t2[i][j]==0) then push the location
      //    (i.e., row and col) onto the stack
      //    the string "row value" + "," + "col value" is pushed
      //
            s.push(ss2);
           }
        else
           {
      	  if (tval == -1) // uncovered a mine! you lose!
               {
                 document.images(locv).src="msexp.gif"; // show red mine
                 running=false; // turn off the game
                 game_stats(); // show the new statistics
                 clearInterval(game_timer); // stop the game timer
                 timer_on=false;
                 alert ("you hit a mine. You lose");
               }
            else
               {
      		 // show the number if not 0 or -1
                document.images[locv].src="msnum"+tval.toString()+".gif";
      
               }
           }
      
      //
      //  ARE THERE ANY EMTPY CELL ON THE STACK?
      //
      //  This loops runs until all the adjacent empty cells are processed
      //
        while  (s.length>0) // while empty cells remain on the stack
           {
            // alert ("stack length in while="+s.length);
            top_of_stack=s.pop(); // get the top of the stack
            // alert ("top_of_stack="+top_of_stack);
            v=top_of_stack.split(",");
            rowval=parseInt(v[0]);
            colval=parseInt(v[1]);
            locv=(rowval-1)*cmax+(colval-1);
            tval=t2[rowval][colval];
      	  document.images[locv].src="msnum0.gif"; // show the empty image
      //
      //    LOOK AT ALL the  ADJACENT CELLS -- EITHER:
      //    SHOW THEM IF THEY ARE A NUMBER
      //    OR push THEM ON THE STACK IF THEY ARE EMPTY (i..e., zero)
      //
            t3[rowval][colval]=1; // flag this empty cell as "been processed"
            //
            //*** look at all 8 adjacent cells
            //
            push_or_show(rowval,colval,-1,-1); // three to the left
            push_or_show(rowval,colval,-1, 0);
            push_or_show(rowval,colval,-1, 1);
      
            push_or_show(rowval,colval, 0,-1); // above and below
            push_or_show(rowval,colval, 0, 1);
      
            push_or_show(rowval,colval, 1,-1); // three to the right
            push_or_show(rowval,colval, 1, 0);
            push_or_show(rowval,colval, 1, 1);
      
           } // end while
      
        } //end is running
      
      }
      
      function push_or_show(r,c,ra,ca) // ***************** push or show
      {
       newr=r+ra;
       newc=c+ca;
       tval=t2[newr][newc];
      //
      // if one of the row or column values is outside the table skip it
      //
       if ( newr <1 || newr >rmax || newc <1 || newc > cmax)
          {
      
          }
       else
          {
      //    the cell must be empty AND not have been previously processed
           if ( tval==0 && t3[newr][newc]==0)
              {
      //
      // push ANY EMPTY CELL on to the stack to process later
      //
              s.push (newr.toString()+","+newc.toString() );
              }
               else // show the cell value
              {
                locv=(newr-1)*cmax+(newc-1);
                document.images[locv].src="msnum"+tval.toString()+".gif";
                t3[newr][newc]=1; // record that the cell is has been processed
              }
          }
      }
      

  6. Using a cookie to store data locally

    This minesweeper clone uses a cookie to store the data Performance Data and the user's name. Browser recognize the document.cookie object. Then a cookie can be set by saying:

    document.cookie = some cookie name = some cookie value;expires=a date in GMT format;

    Each cookie must have:

    1. a "name=value" where "name" is the name of the cookie, and "value" is the value to be assigned to the cookie followed by a semicolon
    2. an "expires=date" where date is in Greenwich Mean Time (GMT) format followed by a semicolon. To set a date in the correct format:

    So first we create a date object like this:

    var date = new Date();

    Now we must decide when the cookie expires. If we choose to determine expiration by specifying how many days from today we calculate:

    date.setTime(date.getTime()+(days*24*60*60*1000));

    This javascript setTime function measure time in milliseconds since January 1, 1970. So "date.getTime()" retrives the number of milliseconds that have transpired between January 1 , 1970 and now, and then it must add the number of milliseconds that will transpire "days" hence (24*60*60*1000 is the number of milliseconds in one day).

    Then we must convert the time to GMT by using the ".toGMTString()" method. The resulting "set_cookie" function is shown below.

    Therefore three standard cookie javascript functions that are needed:

    1. set the cookie

      We pass three arguments to this function: "cookie name", "cookie value" and how many "days" before the cookie expires:

      function set_cookie (cookie_name,cvalue,days)
      {
        if (days)
           {
      		     var date = new Date();
      		     date.setTime(date.getTime()+(days*24*60*60*1000));
      		     var expires = "; expires="+date.toGMTString();
      	    }
       	else
            var expires = "";
       	document.cookie = cookie_name+"="+cvalue+expires+";"
      }
      

    2. retrieve the cookie

      This function retrieves the value of the cookie. It requires that pass the function the name of the cookie ("c_name"). If the cookie is not found the function returns and empty string.

      function get_cookie(cookie_name)
      {
          if (document.cookie.length > 0)
             {
              c_start = document.cookie.indexOf(cookie_name + "=");
              if (c_start != -1)
                 {
                  c_start = c_start + c_name.length + 1;
                  c_end = document.cookie.indexOf(";", c_start);
                  if (c_end == -1) c_end = document.cookie.length;
                  cvalue=unescape(document.cookie.substring(c_start, c_end));
                  // alert ("cvalue in get_cookie="+cvalue);
                  return cvalue;
                }
            }
          return "";
      }
      

    3. to kill (i.e., delete) a cookie

      This function kills a cookie by passing the "set_cookie" and date in the past:

      1. "cookie_name"
      2. an empty string
      3. a -1 which sets the expiration date to yesterday and the cookie is immediately deleted

      function kill_cookie(cookie_name)
      {
        set_cookie(cookie_name,"",-1);
      }
      

    This minesweeper clone uses these three functions to remember the Performance Data. For each of the the three game sizes you store in a cookie the values for each game type:

    1. games played
    2. wins (winning percentage is also calculated from as wins/payed*100)
    3. best game (i.e., shortest succesful elapsed time)

    The cookie tasks are then:

    1. user can accept cookie or not?

      Based on the user's security settings, the first task is to see if the user can accept a cookie or not. This can be accomplished by trying the write a cookie to see what happens.

      This "areCookies Enabled" function writes a cookie named "testing" with a value of "Hello" and sets it to expire tommorrow using the "Set_cookie" function. Then the function reads the cookie using "get_cookie" function. If it finds the cookie, it kills the cookie.

      The function returns "true" if the cookie was written and read ok. It returns "false" if the cookie could NOT be written, then read.

      function areCookiesEnabled()
      {
              var r = false;
              set_cookie("testing", "Hello", 1);
              if (get_cookie("testing") != null)
                 {
                  r = true;
                  kill_cookie("testing");
                 }
              return r;
      }
      

    2. The primary cookie processing function "findallcookies()" is shown below.

      1. It first performs "areCookiesEnabled()" function. Based on the outcome ("true" or "false") the global variable "cookies_ok" is set to "true" or "false".

      2. The program then gets the user name from the textbox. It edits the username and checks to see if the user name length is >0 and < 8. if the name is NOT >0 and < 8 it asks the user to try again.
      3. if "cookies_ok" is "true" AND the user name length is > 0 and < 8:

        The function checks for the existence of a cookie names: "mswp"+(user name)

        If it finds the cookie, the user must have previously saved the performance data and the function gets the nine values from the cookie and sets the game_count, number of games won and best time for each of the three game types

        hen the function hides the user name entry textbox and displays the "play", "save" and "help" buttons

    function findallcookies()
    {
        cookies_ok=false;
        if (areCookiesEnabled())
           {
            cookies_ok=true;
            // alert ("cookies enabled");
           }
        else
           {
            cookies_ok=false;
            // alert ("cookies NOT enabled");
            return;
           }
    
       uid="";
       var uidtemp=document.getElementsByName("uidv").item(0).value;
       if (uidtemp.length > 8)
          {
          alert ("Name must be 8 or less characters. Try Again");
          return;
          }
       else
          {
           if (uidtemp.length < 1)
             {
              alert ("Name cannot be blank. You must enter a Name. Try Again.");
              return;
             }
           else
            {
             uid=uidtemp;
            }
         }
       cn="mswp"+uid;
       if (cookies_ok)
          {
           tempval=get_cookie(cn);
           if (tempval.length != 0 )
              {
               // alert ("got cookie read this: "+tempval);
               var cookie_data=tempval.split("-");
               game_count[0]=cookie_data[0];
               won[0]=cookie_data[1];
               best_time[0]=cookie_data[2];
               game_count[1]=cookie_data[3];
               won[1]=cookie_data[4];
               best_time[1]=cookie_data[5];
               game_count[2]=cookie_data[6];
               won[2]=cookie_data[7];
               best_time[2]=cookie_data[8];
               game_stats();
               // alert ("read old performance data from cookie OK");
             }
          else
             {
              // alert ("No old performance data found");
             }
          document.getElementById("login_box").style.display="none";
          document.getElementById("button_box").style.display="inline";
          }
    }