用Deepseek寫掃雷uniapp小游戲

掃雷作為Windows系統自帶的經典小游戲,承載了許多人的童年回憶。本文將詳細介紹如何使用Uniapp框架從零開始實現一個完整的掃雷游戲,包含核心算法、交互設計和狀態管理。無論你是Uniapp初學者還是有一定經驗的開發者,都能從本文中獲得啟發。

一、游戲設計思路

1.1 游戲規則回顧

掃雷游戲的基本規則非常簡單:

  • 游戲區域由方格組成,部分方格下藏有地雷

  • 玩家點擊方格可以揭開它

  • 如果揭開的是地雷,游戲結束

  • 如果揭開的是空白格子,會顯示周圍8格中的地雷數量

  • 玩家可以通過標記來標識可能的地雷位置

  • 當所有非地雷方格都被揭開時,玩家獲勝

1.2 技術實現要點

基于上述規則,我們需要實現以下核心功能:

  1. 游戲棋盤的數據結構

  2. 隨機布置地雷的算法

  3. 計算每個格子周圍地雷數量的方法

  4. 點擊和長按的交互處理

  5. 游戲狀態管理(進行中、勝利、失敗)

  6. 計時和剩余地雷數的顯示

二、Uniapp實現詳解

2.1 項目結構

我們創建一個單獨的頁面minesweeper/minesweeper.vue來實現游戲,主要包含三個部分:

  • 模板部分:游戲界面布局

  • 腳本部分:游戲邏輯實現

  • 樣式部分:游戲視覺效果

2.2 核心代碼解析

2.2.1 游戲數據初始化
data() {return {rows: 10,       // 行數cols: 10,       // 列數mines: 15,      // 地雷數board: [],      // 游戲棋盤數據remainingMines: 0, // 剩余地雷數time: 0,        // 游戲時間timer: null,    // 計時器gameOver: false, // 游戲是否結束gameOverMessage: '', // 結束消息firstClick: true // 是否是第一次點擊}
}
2.2.2 游戲初始化方法
startGame(rows, cols, mines) {this.rows = rows;this.cols = cols;this.mines = mines;this.remainingMines = mines;this.time = 0;this.gameOver = false;this.firstClick = true;// 初始化棋盤數據結構this.board = Array(rows).fill().map(() => Array(cols).fill().map(() => ({mine: false,          // 是否是地雷revealed: false,      // 是否已揭開flagged: false,       // 是否已標記neighborMines: 0,     // 周圍地雷數exploded: false       // 是否爆炸(踩中地雷)})));
}
2.2.3 地雷布置算法
placeMines(firstRow, firstCol) {let minesPlaced = 0;// 隨機布置地雷,但避開第一次點擊位置及周圍while (minesPlaced < this.mines) {const row = Math.floor(Math.random() * this.rows);const col = Math.floor(Math.random() * this.cols);if (!this.board[row][col].mine && Math.abs(row - firstRow) > 1 && Math.abs(col - firstCol) > 1) {this.board[row][col].mine = true;minesPlaced++;}}// 計算每個格子周圍的地雷數for (let row = 0; row < this.rows; row++) {for (let col = 0; col < this.cols; col++) {if (!this.board[row][col].mine) {let count = 0;// 檢查周圍8個格子for (let r = Math.max(0, row - 1); r <= Math.min(this.rows - 1, row + 1); r++) {for (let c = Math.max(0, col - 1); c <= Math.min(this.cols - 1, col + 1); c++) {if (this.board[r][c].mine) count++;}}this.board[row][col].neighborMines = count;}}}
}

?2.2.4 格子揭示邏輯

revealCell(row, col) {// 第一次點擊時布置地雷if (this.firstClick) {this.placeMines(row, col);this.startTimer();this.firstClick = false;}// 點擊到地雷if (this.board[row][col].mine) {this.board[row][col].exploded = true;this.gameOver = true;this.gameOverMessage = '游戲結束!你踩到地雷了!';this.revealAllMines();return;}// 遞歸揭示空白區域this.revealEmptyCells(row, col);// 檢查是否獲勝if (this.checkWin()) {this.gameOver = true;this.gameOverMessage = '恭喜你贏了!';}
}
2.2.5 遞歸揭示空白區域
revealEmptyCells(row, col) {// 邊界檢查if (row < 0 || row >= this.rows || col < 0 || col >= this.cols || this.board[row][col].revealed || this.board[row][col].flagged) {return;}this.board[row][col].revealed = true;// 如果是空白格子,遞歸揭示周圍的格子if (this.board[row][col].neighborMines === 0) {for (let r = Math.max(0, row - 1); r <= Math.min(this.rows - 1, row + 1); r++) {for (let c = Math.max(0, col - 1); c <= Math.min(this.cols - 1, col + 1); c++) {if (r !== row || c !== col) {this.revealEmptyCells(r, c);}}}}
}

2.3 界面實現

游戲界面主要分為三個部分:

  1. 游戲信息區:顯示標題、剩余地雷數和用時

  2. 游戲棋盤:由方格組成的掃雷區域

  3. 控制區:難度選擇按鈕和游戲結束提示

<view class="game-board"><view v-for="(row, rowIndex) in board" :key="rowIndex" class="row"><view v-for="(cell, colIndex) in row" :key="colIndex" class="cell":class="{'revealed': cell.revealed,'flagged': cell.flagged,'mine': cell.revealed && cell.mine,'exploded': cell.exploded}"@click="revealCell(rowIndex, colIndex)"@longpress="toggleFlag(rowIndex, colIndex)"><!-- 顯示格子內容 --><text v-if="cell.revealed && !cell.mine && cell.neighborMines > 0">{{ cell.neighborMines }}</text><text v-else-if="cell.flagged">🚩</text><text v-else-if="cell.revealed && cell.mine">💣</text></view></view>
</view>

三、關鍵技術與優化點

3.1 性能優化

  1. 延遲布置地雷:只在第一次點擊后才布置地雷,確保第一次點擊不會踩雷,提升用戶體驗

  2. 遞歸算法優化:在揭示空白區域時使用遞歸算法,但要注意邊界條件,避免無限遞歸

3.2 交互設計

  1. 長按標記:使用@longpress事件實現標記功能,符合移動端操作習慣

  2. 視覺反饋:為不同類型的格子(普通、已揭示、標記、地雷、爆炸)設置不同的樣式

3.3 狀態管理

  1. 游戲狀態:使用gameOvergameOverMessage管理游戲結束狀態

  2. 計時器:使用setInterval實現游戲計時功能,注意在組件銷毀時清除計時器

四、擴展思路

這個基礎實現還可以進一步擴展:

  1. 本地存儲:使用uni.setStorage保存最佳成績

  2. 音效增強:添加點擊、標記、爆炸等音效

  3. 動畫效果:為格子添加翻轉動畫,增強視覺效果

  4. 自定義難度:允許玩家自定義棋盤大小和地雷數量

  5. 多平臺適配:優化在不同平臺(H5、小程序、App)上的顯示效果

五、總結

通過本文的介紹,我們完整實現了一個基于Uniapp的掃雷游戲,涵蓋了從數據結構設計、核心算法實現到用戶交互處理的全部流程。這個項目不僅可以幫助理解Uniapp的開發模式,也是學習游戲邏輯開發的好例子。讀者可以根據自己的需求進一步擴展和完善這個游戲。

完整代碼

<template><view class="minesweeper-container"><view class="game-header"><text class="title">掃雷游戲</text><view class="game-info"><text>剩余: {{ remainingMines }}</text><text>時間: {{ time }}</text></view></view><view class="game-board"><view v-for="(row, rowIndex) in board" :key="rowIndex" class="row"><view v-for="(cell, colIndex) in row" :key="colIndex" class="cell":class="{'revealed': cell.revealed,'flagged': cell.flagged,'mine': cell.revealed && cell.mine,'exploded': cell.exploded}"@click="revealCell(rowIndex, colIndex)"@longpress="toggleFlag(rowIndex, colIndex)"><text v-if="cell.revealed && !cell.mine && cell.neighborMines > 0">{{ cell.neighborMines }}</text><text v-else-if="cell.flagged">🚩</text><text v-else-if="cell.revealed && cell.mine">💣</text></view></view></view><view class="game-controls"><button @click="startGame(10, 10, 15)">初級 (10×10, 15雷)</button><button @click="startGame(15, 15, 40)">中級 (15×15, 40雷)</button><button @click="startGame(20, 20, 99)">高級 (20×20, 99雷)</button></view><view v-if="gameOver" class="game-over"><text>{{ gameOverMessage }}</text><button @click="startGame(rows, cols, mines)">再玩一次</button></view></view>
</template><script>
export default {data() {return {rows: 10,cols: 10,mines: 15,board: [],remainingMines: 0,time: 0,timer: null,gameOver: false,gameOverMessage: '',firstClick: true}},created() {this.startGame(10, 10, 15);},methods: {startGame(rows, cols, mines) {this.rows = rows;this.cols = cols;this.mines = mines;this.remainingMines = mines;this.time = 0;this.gameOver = false;this.firstClick = true;clearInterval(this.timer);// 初始化棋盤this.board = Array(rows).fill().map(() => Array(cols).fill().map(() => ({mine: false,revealed: false,flagged: false,neighborMines: 0,exploded: false})));},placeMines(firstRow, firstCol) {let minesPlaced = 0;while (minesPlaced < this.mines) {const row = Math.floor(Math.random() * this.rows);const col = Math.floor(Math.random() * this.cols);// 確保第一次點擊的位置和周圍沒有地雷if (!this.board[row][col].mine && Math.abs(row - firstRow) > 1 && Math.abs(col - firstCol) > 1) {this.board[row][col].mine = true;minesPlaced++;}}// 計算每個格子周圍的地雷數for (let row = 0; row < this.rows; row++) {for (let col = 0; col < this.cols; col++) {if (!this.board[row][col].mine) {let count = 0;for (let r = Math.max(0, row - 1); r <= Math.min(this.rows - 1, row + 1); r++) {for (let c = Math.max(0, col - 1); c <= Math.min(this.cols - 1, col + 1); c++) {if (this.board[r][c].mine) count++;}}this.board[row][col].neighborMines = count;}}}},revealCell(row, col) {if (this.gameOver || this.board[row][col].revealed || this.board[row][col].flagged) {return;}// 第一次點擊時放置地雷并開始計時if (this.firstClick) {this.placeMines(row, col);this.startTimer();this.firstClick = false;}// 點擊到地雷if (this.board[row][col].mine) {this.board[row][col].exploded = true;this.gameOver = true;this.gameOverMessage = '游戲結束!你踩到地雷了!';this.revealAllMines();clearInterval(this.timer);return;}// 遞歸揭示空白區域this.revealEmptyCells(row, col);// 檢查是否獲勝if (this.checkWin()) {this.gameOver = true;this.gameOverMessage = '恭喜你贏了!';clearInterval(this.timer);}},revealEmptyCells(row, col) {if (row < 0 || row >= this.rows || col < 0 || col >= this.cols || this.board[row][col].revealed || this.board[row][col].flagged) {return;}this.board[row][col].revealed = true;if (this.board[row][col].neighborMines === 0) {// 如果是空白格子,遞歸揭示周圍的格子for (let r = Math.max(0, row - 1); r <= Math.min(this.rows - 1, row + 1); r++) {for (let c = Math.max(0, col - 1); c <= Math.min(this.cols - 1, col + 1); c++) {if (r !== row || c !== col) {this.revealEmptyCells(r, c);}}}}},toggleFlag(row, col) {if (this.gameOver || this.board[row][col].revealed) {return;}if (this.board[row][col].flagged) {this.board[row][col].flagged = false;this.remainingMines++;} else if (this.remainingMines > 0) {this.board[row][col].flagged = true;this.remainingMines--;}},startTimer() {clearInterval(this.timer);this.timer = setInterval(() => {this.time++;}, 1000);},revealAllMines() {for (let row = 0; row < this.rows; row++) {for (let col = 0; col < this.cols; col++) {if (this.board[row][col].mine) {this.board[row][col].revealed = true;}}}},checkWin() {for (let row = 0; row < this.rows; row++) {for (let col = 0; col < this.cols; col++) {if (!this.board[row][col].mine && !this.board[row][col].revealed) {return false;}}}return true;}},beforeDestroy() {clearInterval(this.timer);}
}
</script><style>
.minesweeper-container {padding: 20px;display: flex;flex-direction: column;align-items: center;
}.game-header {margin-bottom: 20px;text-align: center;
}.game-header .title {font-size: 24px;font-weight: bold;margin-bottom: 10px;
}.game-info {display: flex;justify-content: space-around;width: 100%;
}.game-board {border: 2px solid #333;margin-bottom: 20px;
}.row {display: flex;
}.cell {width: 30px;height: 30px;border: 1px solid #ccc;display: flex;justify-content: center;align-items: center;background-color: #ddd;font-weight: bold;
}.cell.revealed {background-color: #fff;
}.cell.flagged {background-color: #ffeb3b;
}.cell.mine {background-color: #f44336;
}.cell.exploded {background-color: #d32f2f;
}.game-controls {display: flex;flex-direction: column;gap: 10px;width: 100%;max-width: 300px;
}.game-over {margin-top: 20px;text-align: center;font-size: 18px;font-weight: bold;
}button {margin-top: 10px;padding: 10px;background-color: #4CAF50;color: white;border: none;border-radius: 5px;cursor: pointer;
}button:active {background-color: #3e8e41;
}
</style>

?

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/74020.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/74020.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/74020.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Dust3r、Mast3r、Fast3r

目錄 一.Dust3r 1.簡述 2.PointMap與ConfidenceMap 3.模型結構 4.損失函數 5.全局對齊 二.Mast3r 1.簡述 2.MASt3R matching 3.MASt3R sfm 匹配與標準點圖 BA優化 三.Fast3r 1.簡述 2.模型結構 3.損失函數 三維重建是計算機視覺中的一個高層任務&#xff0c;包…

學習不同電腦cpu分類及選購指南

學習不同電腦cpu分類及選購指南 關于電腦cpu 學習不同電腦cpu分類及選購指南一、CPU型號的核心組成與命名規則Intel命名規則:AMD命名規則:代數:具體型號:cpu后綴:Intel常見后綴及其含義:AMD后綴常見后綴及其含義:二、主流品牌CPU的分類與性能差異三、區分CPU型號的實用方…

【身份安全】零信任安全框架梳理(一)

目錄 零信任網絡安全防護理念一、定義零信任原則 二、零信任實現方式三、零信任的核心機制和思想1. 持續驗證&#xff08;Continuous Verification&#xff09;2. 多因素認證&#xff08;MFA&#xff09;與強身份驗證3. 細粒度權限控制&#xff08;最小權限原則&#xff09;4. …

【LeetCode Solutions】LeetCode 101 ~ 105 題解

CONTENTS LeetCode 101. 對稱二叉樹&#xff08;簡單&#xff09;LeetCode 102. 二叉樹的層序遍歷&#xff08;中等&#xff09;LeetCode 103. 二叉樹的鋸齒形層序遍歷&#xff08;中等&#xff09;LeetCode 104. 二叉樹的最大深度&#xff08;簡單&#xff09;LeetCode 105. 從…

革新汽車安全通信技術,美格智能全系車載通信模組支持NG-eCall

根據QYR&#xff08;恒州博智&#xff09;的統計及預測&#xff0c;2024年全球汽車無線緊急呼叫&#xff08;eCall&#xff09;設備市場銷售額達到了25.17億美元&#xff0c;預計2031年將達到44.97億美元&#xff0c;年復合增長率&#xff08;CAGR 2025-2031&#xff09;為8.8%…

Redis-04.Redis常用命令-字符串常用命令

一.字符串操作命令 set name jack 點擊左側name&#xff0c;顯示出值。 get name get abc&#xff1a;null setex key seconds value&#xff1a;設置過期時間&#xff0c;過期后該鍵值對將會被刪除。 然后再get&#xff0c;在過期時間內可以get到&#xff0c;過期get不到。…

一文總結常見項目排查

慢sql排查 怎么排查 通過如下命令&#xff0c;開啟慢 SQL 監控&#xff0c;執行成功之后&#xff0c;客戶端需要重新連接才能生效。 -- 開啟慢 SQL 監控 set global slow_query_log 1; 默認的慢 SQL 閥值是10秒&#xff0c;可以通過如下語句查詢慢 SQL 的閥值。 -- 查詢慢…

使用Python爬蟲獲取淘寶App商品詳情

在電商領域&#xff0c;獲取商品詳情數據對于市場分析、競品研究和用戶體驗優化至關重要。淘寶作為國內領先的電商平臺&#xff0c;提供了豐富的商品資源。雖然淘寶App的數據獲取相對復雜&#xff0c;但通過Python爬蟲技術&#xff0c;我們可以高效地獲取淘寶App商品的詳細信息…

Redis-06.Redis常用命令-列表操作命令

一.列表操作命令 LPUSH key value1 [value2]&#xff1a; LPUSH mylist a b c d: LRANGE key start stop&#xff1a; LRANGE mylist 0 -1&#xff1a; lrange mylist 0 2&#xff1a; d c b RPOP KEY&#xff1a;移除并返回最后一個元素 RPOP list a LLEN key…

客戶端給服務器發數據,服務器不顯示:開放端口操作

當你寫完UDP/TCP代碼進行測試時&#xff0c;發現沒出什么錯誤&#xff0c;但是不管你客戶端怎么發送消息&#xff0c;服務器就是不顯示&#xff0c;那么很有可能你云服務器沒開放端口。比如&#xff1a; 接下來教你開放端口&#xff1a; 一&#xff1a;進入你買云服務器的頁面…

IDApro直接 debug STM32 MCU

使用IDA pro 逆向分析muc 固件的時候&#xff0c; 難免要進行一些動態的debug&#xff0c;來進一步搞清楚一些內存的數據、算法等&#xff0c;這時候使用遠程debug 的方式直接在mcu上進行debug 最合適不過了。 不過有個前提條件就是一般來說有的mcu 會被運行中的代碼屏蔽 RDP、…

系統與網絡安全------Windows系統安全(1)

資料整理于網絡資料、書本資料、AI&#xff0c;僅供個人學習參考。 用戶賬號基礎 本地用戶賬號基礎 用戶賬號概述 用戶賬號用來記錄用戶的用戶名和口令、隸屬的組等信息 每個用戶賬號包含唯一的登錄名和對應的密碼 不同的用戶身份擁有不同的權限 操作系統根據SID識別不同…

測試用例管理工具

一、免費/開源工具 TestLink 適用場景&#xff1a;傳統手工測試團隊&#xff0c;需基礎用例管理與測試計劃跟蹤。 關鍵功能&#xff1a;用例分層管理、執行結果記錄、基礎報告生成。 局限&#xff1a;界面陳舊&#xff0c;自動化集成需插件支持。 Kiwi TCMS 適用場景&#xff1…

漏洞挖掘---順景ERP-GetFile任意文件讀取漏洞

一、順景ERP 順景 ERP 是廣東順景軟件科技有限公司研發的企業資源規劃系統。它以制造為核心&#xff0c;融合供應鏈、財務等管理&#xff0c;打破部門壁壘&#xff0c;實現全程無縫管理。該系統功能豐富&#xff0c;支持多語言、多平臺&#xff0c;具備柔性流程、條碼應用等特色…

關于bug總結記錄

1、vs中出現bug error C1083:無法打開文件 鏈接&#xff1a;vs中出現bug error C1083:無法打開文件_vs20151083錯誤解決方法-CSDN博客 2、 VS小技巧&#xff1a;系統卻提示&#xff1a;示msvcp120.dll丟失 鏈接&#xff1a;VS小技巧&#xff1a;系統卻提示&#xff1a;示msvc…

2023碼蹄杯真題

題目如下 代碼如下

如何在不同的分辨率均能顯示出清晰的字體?

問題 設計好的窗體&#xff0c;當屏幕的分辨率改變時&#xff0c;字體放大好變得模糊。 解決辦法 //高低版本&#xff0c;均可使用[DllImport("user32.dll")]private static extern bool SetProcessDPIAware(); //高版本windows,可選用以下 [DllImport("user…

北斗導航 | 基于因子圖優化的GNSS/INS組合導航完好性監測算法研究,附matlab代碼

以下是一篇基于因子圖優化(FGO)的GNSS/INS組合導航完好性監測算法的論文框架及核心內容,包含數學模型、完整Matlab代碼及仿真分析基于因子圖優化的GNSS/INS組合導航完好性監測算法研究 摘要 針對傳統卡爾曼濾波在組合導航完好性監測中對非線性與非高斯噪聲敏感的問題,本文…

wordpress的cookie理解

登錄 wordpress 登錄 wordpress 的時候 Cookie 顯示為 PHPSESSIDubilj5ad65810hqv88emitmvkc; isLogintrue; night0; wordpress_logged_in_27e3261db108cd80480af5f900ac865e1735846526%7C1744418831%7CrTugvME3l2ZITBoxf6JAsAn4woFdbIZvggvvKDRHQhc%7C3fa99b7f0728dffc47f75…

JavaScript 中的原型鏈與繼承

JavaScript 是一種基于原型的編程語言&#xff0c;這意味著它的對象繼承是通過原型鏈而非類的機制來實現的。原型鏈是 JavaScript 中對象與對象之間繼承屬性和方法的基礎。本文將深入探討 JavaScript 中的原型鏈和繼承機制&#xff0c;幫助你理解這一重要概念。 一、原型&…