亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

基于vue編寫一個月餅連連看游戲

 更新時間:2023年09月15日 11:40:50   作者:冰鎮(zhèn)白干  
中秋節(jié)快要到啦,我們一起用Vue創(chuàng)建一個簡單的連連看游戲,連連看大家一定都玩過吧,通過消除相同的圖案來清理棋盤,小編將一步步引導(dǎo)大家完成整個游戲的制作過程,讓我們開始吧,一起為中秋節(jié)增添一些互動和娛樂

"月圓花好夜,花好月圓人更圓。"

前言

中秋節(jié)快要到啦,我們一起用Vue創(chuàng)建一個簡單的連連看游戲。

連連看大家一定都玩過吧,通過消除相同的圖案來清理棋盤。上面就是我們今天要做的效果圖,看上去也挺像那么回事,不過實現(xiàn)起來也是非常簡單。

我將一步步引導(dǎo)大家完成整個游戲的制作過程,讓我們開始吧,一起為中秋節(jié)增添一些互動和娛樂!

設(shè)計思路

在構(gòu)建連連看游戲之前,首先需要考慮游戲的設(shè)計思路。

  • 游戲界面:我們將創(chuàng)建一個網(wǎng)格狀的游戲界面,每個格子上都有一個圖標(biāo)或者數(shù)字。
  • 游戲邏輯:玩家可以點擊兩個相同的格子來連接它們,但是連接的路徑上下左右不能有障礙物
  • 游戲結(jié)束:當(dāng)所有的格子都被連接后,游戲結(jié)束。

初始棋盤

<template>
  <div class="game-board">
    <!-- 棋盤網(wǎng)格 -->
    <div v-for="(row,rowIndex) in grid" :key="rowIndex" class="row">
      <div 
        v-for="(cell,colIndex) in row" 
        class="cell"
        :key="colIndex"
      >
        {{grid[rowIndex][colIndex]}}
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
const grid = ref<number[][]>([])
/**
 * 隨機生成grid
 */
const randomizeGrid = () => {
  const rows = 10
  const cols = 10
  for(let i = 0 ; i < rows ; i ++) {
    const row = []
    for(let j = 0 ; j < cols ; j ++) {
      row.push(Math.floor(Math.random() * 3 + 1))
    }
    grid.value.push(row)
  }
}
onMounted(() => {
  randomizeGrid()
})
</script>
<style scoped lang="less">
.game-board {
  background-color: palegoldenrod;
  background-size: contain;
  .row {
    display: flex;
    .cell {
      width: 60px;
      height: 60px;
      margin: 5px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      transition: all .3s;
    }
  }
}
</style>

這樣就生成了一個隨機棋盤,后續(xù)我們將數(shù)組換成對應(yīng)的圖片就可以達(dá)到效果。

但是上面的寫法是我前面寫的,后續(xù)發(fā)現(xiàn)一個問題,我們不能簡單的隨機1、2、3,我們要確保每種值都是成對存在的。為了實現(xiàn)這一點,可以采用以下步驟:

  • 初始化一個存儲可用格子坐標(biāo)的數(shù)組 availableCells
  • 遍歷棋盤格子,并將每個格子的坐標(biāo)添加到 availableCells。
  • 隨機選擇一個可用格子,為其分配一個隨機圖案值,然后從 availableCells 中移除該格子。
  • 再次隨機選擇一個可用格子,并為其分配相同的圖案值。
  • 重復(fù)步驟 3 和 4,直到生成了足夠的圖案對。
  • 將這些圖案值填充到游戲棋盤中。
/**
 * 隨機生成grid,確保每一個值都是成對存在的
 */
const randomizeGrid = () => {
  const rows = 10;
  const cols = 10;
  const numPairs = (rows * cols) / 2; // 總共需要的值對數(shù)  
  const igrid:number[][] = Array(rows).fill(0).map(() => Array(cols).fill(0))
  const availableCells = []; // 存儲可用格子的坐標(biāo)
  // 初始化可用格子的坐標(biāo)數(shù)組
  for (let i = 0; i < rows; i++) {
    for (let j = 0; j < cols; j++) {
      availableCells.push([i, j]);
    }
  }  
  // 隨機生成成對的圖案,并填充到grid中
  for (let pair = 1; pair <= numPairs; pair++) {
    // 隨機選擇一個可用格子
    const cellIndex = Math.floor(Math.random() * availableCells.length);
    const [row, col] = availableCells[cellIndex];
    // 隨機生成一個圖案
    const value = Math.floor(Math.random() * 4+ 1);
    igrid[row][col] = value;
    availableCells.splice(cellIndex, 1);
    // 隨機選擇一個可用格子,將相同圖案填充到第二個位置
    const secondCellIndex = Math.floor(Math.random() * availableCells.length);
    const [secondRow, secondCol] = availableCells[secondCellIndex];
    igrid[secondRow][secondCol] = value;
    // 從可用格子數(shù)組中移除已經(jīng)填充的格子
    availableCells.splice(secondCellIndex, 1);
  }
  grid.value = igrid
};

上面注釋已經(jīng)很清楚啦,如果大家有更好的方法歡迎在評論區(qū)交流 !

點擊動作

上一個步驟中,我們已經(jīng)獲取到了每個格子的值?,F(xiàn)在我們寫一下選中邏輯,由于每次點擊都需要和上一次結(jié)果進行對比,就需要將上一個點擊位置存起來

現(xiàn)在我們要實現(xiàn)一下功能

const lastSelectedCell = ref<number[]>([])
const selectCell = (rowIndex: number, colIndex: number) => {
  // 上次選中了
  if(lastSelectedCell.value?.length) {
    if(canConnect(lastSelectedCell.value,[rowIndex,colIndex])) {
      console.log('可以連接~~');
      grid.value[lastSelectedCell.value[0]][lastSelectedCell.value[1]] = 0
      grid.value[rowIndex][colIndex] = 0
    }
    lastSelectedCell.value = []
  } else {
    lastSelectedCell.value = [rowIndex,colIndex]
  }
}
/**
 * 格子是否被選中
 */
const isCellSelected = (rowIndex: number, colIndex: number): boolean => {
  return lastSelectedCell.value[0] === rowIndex && lastSelectedCell.value[1] === colIndex;
};

isCellSelected是我們選中要配對的那個方格,為了是對它添加動畫方便。

點擊時有兩種情況:

  • 正在選第一個,我們需要記錄次方格,為了下一次連接配對
  • 選了第一個了,此時點擊選中第二個,判斷是否配對成功 (配對成功的邏輯下一步介紹)

連接判定

連接判斷使用bfs來做

這里需要注意,判斷邏輯需要寫在for循環(huán)里面,因為需要配對的那個方格值一定不為0,也就是說目標(biāo)方格只要有值就到達(dá)不了

/**
 * 使用 BFS 檢查路徑是否通
 */
const directions = [
  [-1, 0], // 上
  [1, 0],  // 下
  [0, -1], // 左
  [0, 1],  // 右
];
const isPathConnected = (startCell: number[], endCell: number[]): boolean => {
  const visited = new Set<string>();
  const queue: number[][] = [startCell];
  while (queue.length) {
    const [row, col] = queue.shift()!;
    // 檢查四個方向的相鄰格子
    for (const [dx, dy] of directions) {
      const newRow = row + dx;
      const newCol = col + dy;
      const key = `${newRow}-${newCol}`;
      if(endCell[0] === newRow && endCell[1] === newCol) return true
      if (
        newRow >= 0 &&
        newRow < grid.value.length &&
        newCol >= 0 &&
        newCol < grid.value[0].length &&
        !visited.has(key) &&
        grid.value[newRow][newCol] === 0
      ) {
        queue.push([newRow, newCol]);
        visited.add(key);
      }
    }
  }
  return false; // 沒找到路徑
};

此時我們就可以點擊配對了,最簡單的版本也就完成了,貼一下完整代碼:

<template>
  <div class="game-board">
    <!-- 棋盤網(wǎng)格 -->
    <div v-for="(row,rowIndex) in grid" :key="rowIndex" class="row">
      <div 
        v-for="(cell,colIndex) in row" 
        class="cell"
        :class="{isSelected : isCellSelected(rowIndex,colIndex)}"
        :key="colIndex"
        @click="selectCell(rowIndex,colIndex)"
      >
        {{grid[rowIndex][colIndex]}}
      </div>
    </div>
  </div>
</template>
<script setup lang="ts">
import { onMounted, ref } from 'vue';
const grid = ref<number[][]>([])
const lastSelectedCell = ref<number[]>([])
const selectCell = (rowIndex: number, colIndex: number) => {
  // 上次選中了
  if(lastSelectedCell.value?.length) {
    if(canConnect(lastSelectedCell.value,[rowIndex,colIndex])) {
      console.log('可以連接~~');
      grid.value[lastSelectedCell.value[0]][lastSelectedCell.value[1]] = 0
      grid.value[rowIndex][colIndex] = 0
    }
    lastSelectedCell.value = []
  } else {
    lastSelectedCell.value = [rowIndex,colIndex]
  }
}
/**
 * 格子是否被選中
 */
 const isCellSelected = (rowIndex: number, colIndex: number): boolean => {
  return lastSelectedCell.value[0] === rowIndex && lastSelectedCell.value[1] === colIndex;
};
/**
 * 檢查兩個格子是否可以連接
 */
 const canConnect = (cell1: number[],cell2: number[]): boolean => {
  // 點擊同一個格子
  if(cell1[0] === cell2[0] && cell1[1] === cell2[1]) {
    return false
  }
  // 是否值相同
  if(grid.value[cell1[0]][cell1[1]] !== grid.value[cell2[0]][cell2[1]]) {
    return false
  }
  // 路徑是否通
  return isPathConnected(cell1,cell2)
}
/**
 * 使用 BFS 檢查路徑是否通
 */
 const directions = [
  [-1, 0], // 上
  [1, 0],  // 下
  [0, -1], // 左
  [0, 1],  // 右
];
const isPathConnected = (startCell: number[], endCell: number[]): boolean => {
  const visited = new Set<string>();
  const queue: number[][] = [startCell];
  while (queue.length) {
    const [row, col] = queue.shift()!;
    // 檢查四個方向的相鄰格子
    for (const [dx, dy] of directions) {
      const newRow = row + dx;
      const newCol = col + dy;
      const key = `${newRow}-${newCol}`;
      if(endCell[0] === newRow && endCell[1] === newCol) return true
      if (
        newRow >= 0 &&
        newRow < grid.value.length &&
        newCol >= 0 &&
        newCol < grid.value[0].length &&
        !visited.has(key) &&
        grid.value[newRow][newCol] === 0
      ) {
        queue.push([newRow, newCol]);
        visited.add(key);
      }
    }
  }
  return false; // 沒找到路徑
};
/**
 * 隨機生成grid
 */
const randomizeGrid = () => {
  const rows = 10
  const cols = 10
  for(let i = 0 ; i < rows ; i ++) {
    const row = []
    for(let j = 0 ; j < cols ; j ++) {
      row.push(Math.floor(Math.random() * 3 + 1))
    }
    grid.value.push(row)
  }
}
onMounted(() => {
  randomizeGrid()
})
</script>
<style scoped lang="less">
.game-board {
  // width: 80vw;
  // height: 80vh;
  background-color: palegoldenrod;
  background-size: contain;
  .row {
    display: flex;
    .cell {
      width: 60px;
      height: 60px;
      margin: 5px;
      display: flex;
      align-items: center;
      justify-content: center;
      cursor: pointer;
      transition: all .3s;
      background-color: aquamarine;
    }
  }
}
</style>

現(xiàn)在效果:

引入月餅圖片

現(xiàn)在簡單功能算是完成了,但是太簡單了。我們得做一個看起來高大上的練練看。

此時,直接請班里妹子畫幾個好看的月餅圖片:

真的太好看了,項目直接升個檔次。

拿ps切出來:

然后就可以根據(jù)當(dāng)前格子渲染出對應(yīng)的小月餅啦!

動態(tài)加載圖片需要用到vite自己的方法

加了點擊的動畫,選中的圖片放大并且添加了光圈。大家自己看一看具體實現(xiàn)吧,也是很簡單。

小結(jié)

最后貼一下項目地址

項目地址:https://github.com/Bbbtt04/mooncake-match

主要有兩個難點:

  • bfs判斷連接
  • 隨機生成成對的值
  • 最難的一點:找一個會手繪的妹子

大家也可以試一試自己實現(xiàn)一下,做出來成就感滿滿!

以上就是基于vue編寫一個月餅連連看游戲的詳細(xì)內(nèi)容,更多關(guān)于vue月餅連連看的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • vue init失敗簡單解決方法(終極版)

    vue init失敗簡單解決方法(終極版)

    這篇文章主要介紹了vue init失敗的簡單解決方法-終極版,需要的朋友可以參考下
    2017-12-12
  • vue中的Key值重復(fù)問題

    vue中的Key值重復(fù)問題

    這篇文章主要介紹了vue中的Key值重復(fù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-04-04
  • 詳解vue-cli中使用rem,vue自適應(yīng)

    詳解vue-cli中使用rem,vue自適應(yīng)

    這篇文章主要介紹了vue-cli使用rem,vue自適應(yīng),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • 解決axios:"timeout of 5000ms exceeded"超時的問題

    解決axios:"timeout of 5000ms exceeded"

    這篇文章主要介紹了解決axios:"timeout of 5000ms exceeded"超時的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • IOS上微信小程序密碼框光標(biāo)離開提示存儲密碼的完美解決方案

    IOS上微信小程序密碼框光標(biāo)離開提示存儲密碼的完美解決方案

    ios密碼框輸入密碼光標(biāo)離開之后會提示存儲密碼的彈窗,關(guān)于這樣的問題怎么解決呢,下面給大家分享IOS上微信小程序密碼框光標(biāo)離開提示存儲密碼的完美解決方案,感興趣的朋友一起看看吧
    2024-07-07
  • 查看當(dāng)前vue項目所需Node.js版本的方法

    查看當(dāng)前vue項目所需Node.js版本的方法

    這篇文章主要大家介紹了查看當(dāng)前vue項目所需Node.js版本的方法,文章通過代碼示例給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作有一定的幫助,需要的朋友可以參考下
    2023-11-11
  • react router零基礎(chǔ)使用教程

    react router零基礎(chǔ)使用教程

    React-Router 路由庫,是官方維護的路由庫,事實上也是唯一可選的路由庫。它通過管理 URL,實現(xiàn)組件的切換和狀態(tài)的變化,開發(fā)復(fù)雜的應(yīng)用幾乎肯定會用到
    2022-09-09
  • 如何通過Vue自定義指令實現(xiàn)前端埋點詳析

    如何通過Vue自定義指令實現(xiàn)前端埋點詳析

    埋點分析是網(wǎng)站分析的一種常用的數(shù)據(jù)采集方法,下面這篇文章主要給大家介紹了關(guān)于如何通過Vue自定義指令實現(xiàn)前端埋點的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • Vue中輸入框僅支持?jǐn)?shù)字輸入的四種方法

    Vue中輸入框僅支持?jǐn)?shù)字輸入的四種方法

    項目中需要用到大量的數(shù)字輸入框限制,為了可以以后能又更多的拓展性,下面這篇文章主要給大家介紹了關(guān)于Vue中輸入框僅支持?jǐn)?shù)字輸入的四種方法,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-08-08
  • vue實現(xiàn)購物車功能(親測可用)

    vue實現(xiàn)購物車功能(親測可用)

    這篇文章主要為大家詳細(xì)介紹了vue實現(xiàn)購物車功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04

最新評論