SoFunction
Updated on 2025-04-12

Vue2+JS realizes mine-sweeping game

Implementation steps

1. Scene layout implementation

The layout is a classic square layout. For the aesthetics of the scene, you can find several color matching websites as reference.

Problem occurs: First initialize the corresponding square coordinates of a two-dimensional array, and then render it in turnorRender blank blocks directly through the expected number of rows and columns

the difference:Directly initializing a two-dimensional array can perform some attribute operations on the coordinates, such as marking, whether it is a mine, etc., which will be much more convenient when operating later. The disadvantage is that a lot of calculations are required during initialization (because when clicking a safe coordinate, you need to display the number of mines around, and the edge situation must also be considered). When rendering a blank square, you can then calculate the coordinates when clicking, and only the attributes of the block need to be calculated.

Here I chose the form of rendering blank squares.

Code implementation

The element-ui component was used

template

<div class="layout">
  <div class="row" v-for="row in " :key="row">
    <div
      class="cell"
      :style="{ width:  edgeLength, height: edgeLength }"
      v-for="col in "
      :key="col">
      <div
        class="block"
        @click="open(row, col, $event)"
        @="sign(row, col, $event)"
      >
        // The logic here is now ignored, you just need to make the layout first        <template v-if="areaSign[`${row}-${col}`] === 'fail'">
          <img src="../../assets/svg/" alt="">
        </template>
        <template v-else-if="areaSign[`${row}-${col}`] === 'tag'">
          <img src="../../assets/svg/" alt="">
        </template>
        <template v-else-if="areaSign[`${row}-${col}`] === 'normal'">
        </template>
        <template v-else>
          {{areaSign[`${row}-${col}`]}}
        </template>
      </div>
    </div>
  </div>
</div>

style:

<style scoped lang="less">
.container {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-direction: column;
  margin-top: 100px;
  .typeChoose {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    margin-bottom: 20px;
    .item {
      margin: 0 10px;
    }
  }
  .layout {
    width: 500px;
    height: 500px;
    .row {
      display: flex;
      justify-content: center;
      align-items: center;
      .cell {
        border: 1px solid #735E30;
        caret-color: transparent;
        cursor: pointer;
        line-height: 50px;
        .block {
          height: 100%;
          background: #292E17;
        }
        .block:hover {
          background: #96875F;
        }
        .opened {
          height: 100%;
          background: #E8E0D8;
        }
      }
    }
  }
}
</style>

2. Initialize the event

Generate random two-dimensional arrays of mines

Because the layout has been generated through blank blocks, we only need to care about generating random mine coordinates

Code implementation

/*
  * type: The number of mines in the current mode (define the number yourself)
  * mineList: mine coordinate array
  * layoutConfig: {
  * row: the number of rows of layout
  * col: Number of columns laid out
  * }
  */   

// Generate a random mine coordinate arrayinitMineListRange () {
  while ( &lt; ) {
    ()
  }
},
// Generate a single mine coordinate and put it in a mine coordinate array (mineList)initMineItem () {
  const position = ([1, ], [1, ])
  if (!(position, )) {
    (position)
  }
},
// Generate a random coordinate within a given rangeinitPositionRange ([xStart, xEnd], [yStart, yEnd]) {
  return [(xStart, xEnd), (yStart, yEnd)]
},
// Generate a random integer in a given rangenumRange (start, end) {
  return ((() * (end - start + 1))) + start
},
// Determine whether the position in the parameter already exists and the positionList in the parameterhasPositionIn (position, positionList) {
  ( === 2, 'position length &lt; 2, not a position item')
  return (p =&gt; {
    return p[0] === position[0] &amp;&amp; p[1] === position[1]
  })
}

3. Game action (action)

Refers to some operations in the game and a series of changes caused by a certain operation

Click on the square

Analysis: Three situations will occur after clicking on the block

  • There are no mines within the nine-grid range of this block
  • There are mines in the nine-grid direction of this square
  • Sticking to the point of a missed game (game over)

The corresponding three situations require different manifestations

The first case: (There are no mines within the nine-grid range of the square)

In this case, you only need to change the style of the square to the clicked style (class="opened"

The second case: (There are mines in the nine-grid direction of the square)

Modify the style toopened, and the number of surrounding mines needs to be calculated (the edge case needs to be considered, i.e. whether the current coordinate is at the edge)

The third situation: (step on the mine)

Modify the style toopened, and display landmines to prompt the user to end the game

Code implementation

Because the block is a blank object before clicking, an object is needed to store the properties or status of the block (areaSign

/*
 * areaSign: Object key: Coordinate ('1-2') value: Status
 * gameProcess: Is the current game in progress?
 * statusEnum: Enumeration Block state enum value (fail, normal, tag)
 */

// Block click event (pass in coordinates and click event object) open (rowIndex, colIndex, e) {
   // Determine whether the current game is   if (!) {
     ()
     return
   }
   // Determine whether the current coordinate is marked. If it is marked, it cannot be opened.   if ((rowIndex, colIndex) === ) {
     ('This area has been marked, please select another area to click')
     return
   }
   
    = 'opened'
   if (([rowIndex, colIndex])) {
     // Step on the mine     ([rowIndex, colIndex])
   } else {
     // The first and second situations     ([rowIndex, colIndex])
   }
 },
 //Judge whether there is a mine coordinate array through the incoming coordinates hasTouchMine ([xPosition, yPosition]) {
   return ([xPosition, yPosition], )
 },
 mineTouched (position) {
   (position, )
   // Game failure prompt    = false
   ()
 },
 safeTouched (position) {
   (position)
 },
 // Use the incoming coordinates to determine whether there is a corresponding prompt for setting lightning setTips (position) {
   const total = (position)
   this.$set(, `${position[0]}-${position[1]}`, total || '')
 },
 // Set the incoming coordinates to the corresponding state svg icon setSvg (position, type) {
   this.$set(, `${position[0]}-${position[1]}`, type)
 },
 // Pass the coordinate array and mine coordinate array to determine whether there is lightning around it positionAroundMineTotal (position) {
   const aroundPositionList = (position[0], position[1])
   return (item =&gt; (item)).length
 },
 // Get the nine grid coordinates around the passed coordinates getAroundPosition (xPosition, yPosition) {
   const aroundPositionList = [
     [xPosition - 1, yPosition - 1],
     [xPosition - 1, yPosition],
     [xPosition - 1, yPosition + 1],
     [xPosition, yPosition - 1],
     [xPosition, yPosition + 1],
     [xPosition + 1, yPosition - 1],
     [xPosition + 1, yPosition],
     [xPosition + 1, yPosition + 1]
   ]
   return (position =&gt; isInRange(position[0]) &amp;&amp; isInRange(position[1]))
   // Determine whether the incoming number is in the corresponding range   function isInRange (num, range = [1, 10]) {
     return num &gt;= range[0] &amp;&amp; num &lt;= range[1]
   }
 }

Mark coordinates

The left button is the click block, and the right button is the mark coordinate (the second click is the cancellation mark). When the coordinate is a mark, it is impossible to click. When the coordinate array just happened to be the same as the mine array, the game ends and the player wins.

Code implementation

/*
 * hasWin See vue computed below
 */
sign (rowIndex, colIndex, e) {
// Determine the current status of the game  if (!) {
    ()
    return
  }
  if ((rowIndex, colIndex) === undefined ||
    (rowIndex, colIndex) === ) {
    // Current coordinates are marked or unmarked. Trigger: Add a mark    ([rowIndex, colIndex], )
  } else if ((rowIndex, colIndex) === ) {
    // Current coordinates are marked Triggered: Unmark    ([rowIndex, colIndex], )
  }
  (, )
  // Check whether the game is over  ()
},
// Game TipsgameEndConfirm () {
  const message =  ? 'Congratulations on passing the level, will you continue?  ' : 'The game failed, should I start over?'
  (message, {
    callback: () =&gt; {
      ()
    },
    cancelCallback: () =&gt; {}
  }, 'confirm')
},
// Game status detector (judging whether the current game is over)gameInspector () {
  if () {
    ()
  }
},
// Return the string of the corresponding format (areaSign's key value) by passing in the coordinatesgetAreaSignAttrWithPosition (xPosition, yPosition) {
  return `${xPosition}-${yPosition}`
},
// Return the value value of areaSign by passing in the coordinates (get the status of the coordinates)getAreaSignValueWithPosition (xPosition, yPosition) {
  return [(xPosition, yPosition)]
}
// Tagged listtagList () {
  return ()
    .filter(item =&gt; [item] === 'tag')
    .map(attrStr =&gt; ('-').map(str =&gt; parseInt(str)))
},
// Determine whether all mines have been markedhasSignAllMine () {
  return  ===  &amp;&amp;
    (tagPosition =&gt; (tagPosition, ))
},
// Whether the game is successfulhasWin () {
  return 
}

The game ends

The game needs to be reset when the game fails or wins

Code implementation

resetGame () {
   = true
   = {}
   = []
  ()
  // Initialize the game  ()
},
// Change the element of class = "opened" back to "block" stateresetOpenedClass () {
  ('.opened').forEach(node =&gt; {
     = 'block'
  })
}

Summarize

The implementation of mine-sweeping is not complicated. First of all, you need to have ideas about the mechanism of the mine-sweeping game and you can clarify some logic. When implementing it, consider some edge states. You can pay more attention to the encapsulation of the code, which is very important for the refinement of the code, so it is easy to get started when it continues to develop or needs to be modified.

The above is the detailed content of the Vue2+JS mine-sweeping mini-game. For more information about Vue mine-sweeping games, please pay attention to my other related articles!