0

I've recently learned about IIFEs, and I'm trying to incorporate them in a Minesweeper game. I'm aware of the Module pattern and how it can return objects. I use it in my addMines function to return an array. I'd like to do something similar with my distanceToMine function. My goal is to return an object that shows the distance to each mine--something that I can access with other functions. The problem I've run into is (I think) related to using Jquery's .each function. I can't access any of the code that I use inside of the .each function.

One possible solution I thought of was maybe replacing .each for a for loop, but then I have difficulty accessing the data attributes that I need to access (var thisCell). On line 130 I console.log() the object that I'd like to return.

What's the best way of going about returning the object on line 130 named obj so that I can access it outside of the function? Is it still possible to use the .each function and access the code within it? If so, how?

$(document).ready(function(){
makeGrid();
//addMines();
detectBombs();
distanceToMine();
})

var makeGrid  = (function () {
    return function () {
      var row = 9;
      for (var i=0;i<row;i++){
        $(".divTableBody").append("<div class='divTableRow'></div>") }
      for (i=0;i<row;i++){
        $(".divTableRow").append("<div class='divTableCell'></div>") }
        $(".divTableCell").each( function(i) {
              $(this).attr('data', (i+1))
            //  $(this).append(i+1)
            });
    };
})();

var addMines = (function () {

var mineArray = [];
for (var i = 1; i < 82;i++) {
mineArray.push(i)
}

    return {
      shuffle: function (array) {

    var currentIndex = array.length, temporaryValue, randomIndex;

    while (0 !== currentIndex) {

      randomIndex = Math.floor(Math.random() * currentIndex);
      currentIndex -= 1;

      temporaryValue = array[currentIndex];
      array[currentIndex] = array[randomIndex];
      array[randomIndex] = temporaryValue;
    }

    return array;
  },

  get: function (){
  addMines.shuffle(mineArray);
  mineArray = mineArray.splice(1,10)
    return mineArray
  }

    };
})();

var mineArray = addMines.get()

var detectBombs  = (function () {
    return function () {
    //  var mineArray = addMines.get()
      console.log(mineArray.sort())

      $(".divTableCell").on("click", function(){
        //console.log($(this).attr("data"))
        for (var i=0;i<mineArray.length;i++) {
          if ( $(this).attr("data") == mineArray[i] ) {
            for (var j = 0;j<82;j++) {
              $('*[data="' + mineArray[j] + '"]').html('<i class="fa fa-bomb" aria-hidden="true"></i>')
              .css("background-color", "white" )
              $('*[data="' + j + '"]').css("background-color", "white" )
             }
          }
         }
      })
    };
})();



var distanceToMine  = (function () {
    return function () {


//The following code to find matching array values was taken from this answer:
//https://stackoverflow.com/questions/12433604/how-can-i-find-matching-values-in-two-arrays

      Array.prototype.diff = function(arr2) {
          var ret = [];
          this.sort();
          arr2.sort();
          for(var i = 0; i < this.length; i += 1) {
              if(arr2.indexOf( this[i] ) > -1){
                  ret.push( this[i] );
              }
          }
          return ret;
      };

      var arr = [];

      $(".divTableCell").each( function(i) {

        var thisCell =  parseInt($(this).attr("data"));
        var up = (thisCell - 9);
        var right = (thisCell + 1);
        var down = (thisCell + 9);
        var left = (thisCell - 1);
        var diagonalRightUp = (thisCell - 8);
        var diagonalRightDown = (thisCell + 10);
        var diagonalLeftUp = (thisCell - 10);
        var diagonalLeftDown = (thisCell + 8);
        var direction = [up,right,down,left,diagonalRightUp,diagonalRightDown,diagonalLeftUp,diagonalLeftDown];


        var adjacentNumbers = direction.filter(function(num){
            return num > 0 && num <= 81
        })
           var mineDistances = mineArray.diff(adjacentNumbers)

          arr.push(mineDistances.length)

          });
          //https://stackoverflow.com/questions/4215737/convert-array-to-object

          var obj = arr.reduce(function(acc, cur, i) {
            acc[i] = cur;
            return acc;
          }, {});

          console.log(obj)



      };
})();
.divTable{
 display: table;
 width: 50%;
  padding: 50px;
}
.divTableRow {
 display: table-row;
}
.divTableHeading {
 background-color: #EEE;
 display: table-header-group;
}
.divTableCell, .divTableHead {
 border: 1px solid #999999;
 display: table-cell;
 padding: 20px 20px;
  vertical-align: top;
  box-shadow: 1px 1px 1px;
  background-color: grey;
  border-radius: 5px;
}


.divTableBody {
 display: table-row-group;
}

.open {
 background-color: white;
}
<!DOCTYPE html>

<html lang="en">

<head>

  <title>MineSweeper</title>

  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1">

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>

  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>

  <link rel="stylesheet" href="style.css">

  <script type="text/javascript" src="script.js"></script>

  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script src="https://use.fontawesome.com/eeb147990f.js"></script>


</head>

<body>

  <div class="container">

    <center>
      <h1>Minesweeper</h1>

      <div id="container">

        <div class="divTable">
            <div class="divTableBody">

            </div>
          </div>


      </div>
    </center>

  </div>

</body>

</html>
Pat Mellon
  • 360
  • 2
  • 5
  • 12
  • 1
    You will have multiple objects due to looping each element in the collection. What format do you want them returned as? Might want to look at using [map()](http://api.jquery.com/map/) instead of `each` to build an array of them – charlietfl Jul 16 '17 at 20:46
  • Note it makes no sense extending global object (like Array) prototypes inside such a function. Consider moving that into global context – charlietfl Jul 16 '17 at 20:53
  • I thought it would be better to return an object because then I can use the keys as references when I look at each data attribute. But I could work with an array as well. I'm able to create the object that I want. Towards the end of my js code, I log it. I just can't access it outside of the distanceToMine function, and I'm thinking it has something to do with the .each function being another function inside of the distanceToMine function. – Pat Mellon Jul 16 '17 at 21:51
  • But that is only one instance. There are multiple due to `each`. Make that object a property of an object declared outside `each` and return the outer object once each completes. To be honest I don't see why you need IIFE for that use case either – charlietfl Jul 17 '17 at 12:04
  • I understand what you're saying about the one instance now. I'll try implementing your suggestion later today. I'm still learning about IIFEs. I was under the impression that you should generally always use them--that they're somehow better than other functions that just sit in the global space. Is this incorrect? When are IIFEs appropriate or necessary? – Pat Mellon Jul 17 '17 at 17:22
  • I figured out how to access the object outside of the function! Instead of using `each` I just used a for loop. I set my variable `thisCell` equal to the `i` from the for loop, and it worked the same as `each`. Then I adjusted the IIFE to the module pattern that I use in my `mineArray` function so that I could return the object. I was so wrapped up with using `each` that I couldn't see this solution. But I still need to learn when it's appropriate to even use IIFEs. I appreciate you taking the time to offer your help! – Pat Mellon Jul 18 '17 at 00:20

0 Answers0