【Unity】MiniGame編輯器小游戲(三)馬賽克【Mosaic】

更新日期:2025年6月17日。
項目源碼:后續章節發布

索引

  • 馬賽克【Mosaic】
    • 一、游戲最終效果
    • 二、玩法簡介
    • 三、正式開始
      • 1.定義游戲窗口類
      • 2.規劃游戲窗口、視口區域
      • 3.地圖方塊陣列
        • ①.定義方塊結構體
        • ②.生成方塊陣列
        • ③.計算九宮格黑色方塊數量
        • ④.排除任意九宮格內不存在任何一個顯示文字方塊的情況
        • ⑤.設置馬賽克題目
      • 4.繪制方塊陣列
      • 5.標記方塊
      • 6.檢測游戲是否通關
      • 7.繪制游戲操作說明
      • 8.游戲技巧
        • ①.數字0所在九宮格全為白色
        • ②.數字9所在九宮格全為黑色
        • ③.靠邊6所在九宮格全為黑色
        • ④.精準排除法
        • ⑤.模糊排除法
      • 9.暫停游戲、退出游戲

馬賽克【Mosaic】

本篇的目標是開發一個馬賽克【Mosaic】小游戲。

一、游戲最終效果

Unity編輯器小游戲:馬賽克

二、玩法簡介

馬賽克是掃雷游戲的變種,是一款推理游戲,其玩法簡單卻富有挑戰性。

游戲界面由方塊陣列組成,玩家需要推理每個方塊的正確顏色,并標記為該顏色(分為黑色白色),所以游戲通關后的界面看起來像馬賽克一樣,因而得名。

有些方塊上會顯示一個數字,代表了該方塊所在的9宮格中黑色方塊的數量(包含該方塊自身),玩家需要通過這些信息來推理逐步找出所有黑色方塊。

三、正式開始

1.定義游戲窗口類

首先,定義馬賽克的游戲窗口類MiniGame_Mosaic,其繼承至MiniGameWindow【小游戲窗口基類】

    /// <summary>/// 馬賽克/// </summary>public class MiniGame_Mosaic : MiniGameWindow{}

2.規劃游戲窗口、視口區域

通過覆寫虛屬性實現規劃游戲視口區域大小:

        /// <summary>/// 游戲名稱/// </summary>public override string Name => "馬賽克 [Mosaic]";/// <summary>/// 游戲窗體大小/// </summary>public override Vector2 WindowSize => new Vector2(700, 530);/// <summary>/// 游戲視口區域/// </summary>public override Rect ViewportRect => new Rect(5, 25, 500, 500);

注意:游戲窗體大小必須 > 游戲視口區域。

然后通過代碼打開此游戲窗口:

        [MenuItem("MiniGame/馬賽克 [Mosaic]", priority = 3)]private static void Open_MiniGame_Mosaic(){MiniGameWindow.OpenWindow<MiniGame_Mosaic>();}

便可以看到游戲的窗口、視口區域如下(左側深色凹陷區域為視口區域):

在這里插入圖片描述

3.地圖方塊陣列

馬賽克游戲的背景也是由一系列方塊組成的,所以我們先來繪制如下這樣的地圖方塊陣列:

在這里插入圖片描述

①.定義方塊結構體

首先,定義方塊結構體Block,其代表方塊陣列中的一個方塊:

        /// <summary>/// 方塊/// </summary>public struct Block{/// <summary>/// 方塊位置/// </summary>public Rect Position;/// <summary>/// 是否為黑色/// </summary>public bool IsBlack;/// <summary>/// 是否為白色/// </summary>public bool IsWhite;/// <summary>/// 周圍九宮格內黑色方塊數量/// </summary>public int BlackCount;/// <summary>/// 是否顯示數量文字/// </summary>public bool IsShowCount;}
②.生成方塊陣列

我們設計如下四種難度等級的關卡:

名稱地圖大小
初級5*5
中級10*10
高級15*15
大師級20*20
        private readonly string[] LEVELS = new string[] { "初級(5*5)", "中級(10*10)", "高級(15*15)", "大師級(20*20)" };

所以游戲視口的寬度、高度是根據大師級難度(方塊尺寸25 * 方塊寬高20 = 500)的大小來設置的:

        private const int BLOCKSIZE = 25;

根據選擇的不同難度,來生成對應的地圖方塊陣列:

        private Block[,] _mosaic;/// <summary>/// 開始游戲/// </summary>private void StartGame(){if (_level == 0){WIDTH = 5;HEIGHT = 5;}else if (_level == 1){WIDTH = 10;HEIGHT = 10;}else if (_level == 2){WIDTH = 15;HEIGHT = 15;}else if (_level == 3){WIDTH = 20;HEIGHT = 20;}GenerateMosaic();}/// <summary>/// 生成馬賽克矩陣/// </summary>private void GenerateMosaic(){//生成馬賽克矩陣_mosaic = new Block[WIDTH, HEIGHT];for (int row = 0; row < WIDTH; row++){for (int col = 0; col < HEIGHT; col++){_mosaic[row, col].Position = new Rect(row * BLOCKSIZE, col * BLOCKSIZE, BLOCKSIZE, BLOCKSIZE);_mosaic[row, col].IsBlack = Utility.IsTriggerProbability(60);_mosaic[row, col].IsWhite = false;_mosaic[row, col].IsShowCount = Utility.IsTriggerProbability((_level == 0 || _level == 1) ? 70 : 60);}}}

在生成方塊陣列的方法中,每一個方塊有60%概率為黑色:

_mosaic[row, col].IsBlack = Utility.IsTriggerProbability(60);

初級中級時,每一個方塊有70%概率顯示九宮格內黑色方塊數量,高級大師級60%,相應提升了難度:

_mosaic[row, col].IsShowCount = Utility.IsTriggerProbability((_level == 0 || _level == 1) ? 70 : 60);
③.計算九宮格黑色方塊數量

在生成方塊陣列完成后,下一步就需要計算每一個方塊所屬九宮格中的黑色方塊數量:

        /// <summary>/// 生成馬賽克矩陣/// </summary>private void GenerateMosaic(){//......//計算所有方塊所在九宮格的黑色方塊數量for (int row = 0; row < WIDTH; row++){for (int col = 0; col < HEIGHT; col++){_mosaic[row, col].BlackCount = CalculateBlackCount(row, col);}}}/// <summary>/// 計算方塊所在九宮格的黑色方塊數量/// </summary>private int CalculateBlackCount(int x, int y){int count = 0;for (int i = -1; i <= 1; i++){for (int j = -1; j <= 1; j++){int newX = x + i;int newY = y + j;if (newX >= 0 && newX < WIDTH && newY >= 0 && newY < HEIGHT && _mosaic[newX, newY].IsBlack){count++;}}}return count;}
④.排除任意九宮格內不存在任何一個顯示文字方塊的情況

我們必須確保,任意九宮格中,至少有一個方塊會顯示黑色方塊數量,否則會顯著提升解題難度,甚至不可解:

        /// <summary>/// 生成馬賽克矩陣/// </summary>private void GenerateMosaic(){//......//排除單一九宮格內不存在任何一個顯示文字方塊的情況for (int row = 0; row < WIDTH; row++){for (int col = 0; col < HEIGHT; col++){int count = CalculateShowCount(row, col);if (count <= 0){_mosaic[row, col].IsShowCount = true;}}}}/// <summary>/// 計算方塊所在九宮格的顯示文字的數量/// </summary>private int CalculateShowCount(int x, int y){int count = 0;for (int i = -1; i <= 1; i++){for (int j = -1; j <= 1; j++){int newX = x + i;int newY = y + j;if (newX >= 0 && newX < WIDTH && newY >= 0 && newY < HEIGHT && _mosaic[newX, newY].IsShowCount){count++;}}}return count;}
⑤.設置馬賽克題目

馬賽克游戲也可以看作是一道邏輯解密題,由于之前我們隨機生成了一些黑色方塊,現在部分方塊上已經標注了其所在九宮格中黑色方塊的數量,現在只需要將所有黑色方塊去掉,使玩家通過邏輯推理來尋找黑色方塊即可:

        /// <summary>/// 生成馬賽克矩陣/// </summary>private void GenerateMosaic(){//......//設置馬賽克題目for (int row = 0; row < WIDTH; row++){for (int col = 0; col < HEIGHT; col++){_mosaic[row, col].IsBlack = false;}}}

4.繪制方塊陣列

然后在OnGameViewportGUI方法中繪制方塊陣列:

		//未標記的方塊風格private GUIStyle _noBlockGS;//已標記的方塊風格private GUIStyle _blockGS;protected override void OnGameViewportGUI(){base.OnGameViewportGUI();DrawPanel();}/// <summary>/// 繪制畫布/// </summary>private void DrawPanel(){for (int h = 0; h < HEIGHT; h++){for (int w = 0; w < WIDTH; w++){DrawBlock(w, h);}}}/// <summary>/// 繪制方塊/// </summary>private void DrawBlock(int x, int y){string count = _mosaic[x, y].IsShowCount ? _mosaic[x, y].BlackCount.ToString() : "";if (_mosaic[x, y].IsBlack){GUI.backgroundColor = Color.black;GUI.Box(_mosaic[x, y].Position, count, _blockGS);GUI.backgroundColor = Color.white;}else if (_mosaic[x, y].IsWhite){GUI.Box(_mosaic[x, y].Position, count, _blockGS);}else{GUI.Box(_mosaic[x, y].Position, count, _noBlockGS);}}

此時就能繪制出游戲的地圖方塊陣列了,比如初級(5*5)的:

在這里插入圖片描述

注意:這里有一個選擇關卡難度的過程省略了,該過程很簡單便不浪費篇幅贅述了,后續在源碼中即可一目了然。

兩種狀態的方塊繪制出來大致是這樣的:

在這里插入圖片描述

5.標記方塊

OnGamePlayingEvent方法中完成標記方塊的邏輯:

        protected override void OnGamePlayingEvent(Event e, Vector2 mousePosition){base.OnGamePlayingEvent(e, mousePosition);if (e.type == EventType.MouseDown){if (e.button == 0){for (int h = 0; h < HEIGHT; h++){for (int w = 0; w < WIDTH; w++){if (_mosaic[w, h].Position.Contains(mousePosition)){//鼠標左鍵標記為黑色(再次點擊則取消標記黑色)_mosaic[w, h].IsWhite = false;_mosaic[w, h].IsBlack = !_mosaic[w, h].IsBlack;Repaint();return;}}}}else if (e.button == 1){for (int h = 0; h < HEIGHT; h++){for (int w = 0; w < WIDTH; w++){if (_mosaic[w, h].Position.Contains(mousePosition)){//鼠標右鍵標記為白色(再次點擊則取消標記白色)_mosaic[w, h].IsBlack = false;_mosaic[w, h].IsWhite = !_mosaic[w, h].IsWhite;Repaint();return;}}}}}}

6.檢測游戲是否通關

檢測游戲是否通關的邏輯為:每一個顯示了黑色方塊數量的方塊,其所在九宮格內必須真實標記相應數量的黑色方塊,其余標記為白色。

跟掃雷不同的是:每個方塊的黑、白屬性并不固定,只要最終滿足每個九宮格的黑色方塊數量即可。

        /// <summary>/// 檢測馬賽克題目是否完成(游戲是否通關)/// </summary>private bool CheckMosaicQuestion(){for (int row = 0; row < WIDTH; row++){for (int col = 0; col < HEIGHT; col++){//如果此方塊顯示了黑色方塊數量,則檢測其所在九宮格中是否存在相應數量的方塊if (_mosaic[row, col].IsShowCount){int count = CalculateBlackCount(row, col);//任意九宮格中黑色方塊數量不對,則游戲未通關if (count != _mosaic[row, col].BlackCount){return false;}}}}return true;}

7.繪制游戲操作說明

最后,操作說明等其他UI統一繪制在OnOtherGUI方法中:

        protected override void OnOtherGUI(){base.OnOtherGUI();Rect rect = new Rect(ViewportRect.x + ViewportRect.width + 5, ViewportRect.y + ViewportRect.height - 25, 80, 20);GUI.backgroundColor = Color.green;//玩家可主動點擊Done按鈕,檢測游戲是否通關if (GUI.Button(rect, "Done")){if (CheckMosaicQuestion()){IsGameSuccessed = true;}else{ShowNotification(new GUIContent("You are failed, please try again."));}}rect.x += 85;GUI.backgroundColor = Color.yellow;//也可重新開始(如果當前題目無解,隨機生成會有無解的情況)if (GUI.Button(rect, "Restart")){OnRestart();}GUI.backgroundColor = Color.white;rect.Set(ViewportRect.x + ViewportRect.width + 5, ViewportRect.y + ViewportRect.height - 75, 80, 20);GUI.Button(rect, "Mouse Left");rect.x += 85;rect.width = 100;GUI.Label(rect, "Marked as black");rect.Set(ViewportRect.x + ViewportRect.width + 5, ViewportRect.y + ViewportRect.height - 50, 80, 20);GUI.Button(rect, "Mouse Right");rect.x += 85;rect.width = 100;GUI.Label(rect, "Marked as white");}

這里繪制出來的效果如下:

在這里插入圖片描述

8.游戲技巧

介紹一些游戲技巧(并不是全部)。

①.數字0所在九宮格全為白色

數字0代表所在九宮格中一個黑色方塊也沒有:

在這里插入圖片描述

②.數字9所在九宮格全為黑色

同理,數字9代表所在九宮格中全為黑色方塊:

在這里插入圖片描述

③.靠邊6所在九宮格全為黑色

靠邊數字6代表所在九宮格中有6個黑色方塊,但其九宮格只有6個方塊,所以全為黑色:

在這里插入圖片描述

④.精準排除法

如下圖方塊數字4,已知其下方2個方塊為白色,排除后其九宮格只剩4個方塊,所以4個全為黑色:

在這里插入圖片描述

⑤.模糊排除法

如下圖方塊數字5,已知其下方2個方塊為黑色,則上方4個方塊中只能有3個黑色方塊。

轉向數字8,表明其所在九宮格中只有1個白色方塊,則其上方左側方塊均為黑色(那1個白色方塊在與數字5的交界區域中)。

在這里插入圖片描述

至此,一個簡單的馬賽克小游戲就完成了,簡單但卻耐玩,試玩效果如下:馬賽克【Mosaic】。

9.暫停游戲、退出游戲

同俄羅斯方塊。

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

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

相關文章

基于深度學習的智能圖像質量評估系統:技術與實踐

前言 在數字圖像處理和計算機視覺領域&#xff0c;圖像質量評估&#xff08;Image Quality Assessment, IQA&#xff09;是一個重要的研究方向。圖像質量評估的目標是通過算法自動評估圖像的質量&#xff0c;包括清晰度、對比度、噪聲水平等。傳統的圖像質量評估方法主要依賴于…

【Golang面試題】Go語言實現請求頻率限制

Go語言實現請求頻率限制&#xff1a;從計數器到令牌桶的完整指南 在實際開發中&#xff0c;接口被惡意刷請求是常見問題。本文將深入探討Go語言中四種主流的請求限流方案&#xff0c;從簡單到復雜逐步深入&#xff0c;助你構建高可用服務。 一、基礎方案&#xff1a;計數器法…

11Labs 增長負責人分享:企業級市場將從消費級或開發者切入丨Voice Agent 學習筆記

本文摘自 Founder Park AI 產品如何做增長&#xff0c;ElevenLabs的案例很值得學習。 專注于 AI 語音生成的獨角獸企業 ElevenLabs 可以說一直在高速增長。在今年 1 月完成 1.8 億美元 C 輪融資后&#xff0c;ElevenLabs 的估值突破 30 億&#xff0c;直指 33 億美元。2024 年…

Linux 命令:grep

概述 在Linux系統里&#xff0c;grep是一款十分實用的命令行工具&#xff0c;它主要用于在文件或者輸入流中搜索符合特定模式的文本。下面為你詳細介紹它的用法。資料已經分類整理好&#xff1a;https://pan.quark.cn/s/26d73f7dd8a7 基本語法 grep [選項] 搜索模式 [文件..…

Java八股文——MySQL「架構篇」

MySQL主從復制了解嗎 面試官您好&#xff0c;我了解MySQL的主從復制。它是構建高可用、高可擴展數據庫架構的核心基石。 1. 主從復制的核心原理與流程 整個主從復制的過程&#xff0c;就是一場圍繞 binlog&#xff08;二進制日志&#xff09; 的“接力賽”。這個過程主要可以…

ubuntu下python版本升級導致pyqt不能正常運行解決

最終解決方案 ubuntu下多python版本pyqt兼容性問題解決 python3.9 -m pip install --upgrade --force-reinstall --prefer-binary pyqt5)嘗試解決方案一(失敗) 系統默認python版本可以&#xff0c;其他版本不行 sudo apt install pyqt5-dev-tools嘗試解決方案二(失敗) 一直…

AIGC工具平臺-VideoRetalking音頻對口型數字人

唇形合成技術正逐漸成為AIGC內容生產領域的重要工具&#xff0c;能夠實現音視頻數據的高度融合。基于VideoRetalking模塊的可視化界面降低了技術門檻&#xff0c;使非技術背景的用戶也能便捷體驗唇形驅動數字人合成的流程。 本文重點解析該模塊的使用方式及開發流程&#xff0…

前端項目如何部署為https

如何為項目部署設置HTTPS 設置HTTPS是保護網站數據傳輸安全的重要步驟。以下是設置HTTPS的主要方法&#xff1a; 1. 獲取SSL/TLS證書 免費證書選項 Let’s Encrypt&#xff1a;最流行的免費證書頒發機構Cloudflare&#xff1a;提供免費SSL和CDN服務ZeroSSL&#xff1a;另一…

nginx 配置 系統升級頁面

默認80端口配置如下&#xff1a; server {listen 80; # 指定端口號server_name 192.168.2.96; # 替換為實際域名或IP# 全局重定向到升級頁面&#xff08;排除自身防循環&#xff09;if ($request_uri !~* "/upgrade.html") {return 307 /upgrade.html; # 臨時重定…

計算機基礎(一)——設計模式

一、設計模式 設計模式&#xff08;Design Patterns&#xff09;是軟件開發中反復出現問題的解決方案的通用描述。 它是經過總結、提煉的高效代碼結構和設計方案&#xff0c;幫助開發者寫出更靈活、可維護和可擴展的代碼。 優點注意點規范代碼結構&#xff0c;提高開發效率設…

Mac電腦 磁盤檢測和監控工具 DriveDx

DriveDx Mac 一款不監視驅動器的內置S.M.A.R.T.狀態的先進驅動器運行狀況診斷和監測工具。 還分析了所有驅動器健康密切相關的指標&#xff0c; SSD或硬盤驅動器故障&#xff08;像SSD磨損 /耐久性&#xff0c;壞扇區重新分配&#xff0c;離線壞道&#xff0c;未定扇形區&…

頻繁操作Json嵌套數據PostgreSQL配合JSON操作工具類+sql

文章目錄 1.工具類2.依賴3.sql 本文檔只是為了留檔方便以后工作運維&#xff0c;或者給同事分享文檔內容比較簡陋命令也不是特別全&#xff0c;不適合小白觀看&#xff0c;如有不懂可以私信&#xff0c;上班期間都是在得 背景&#xff1a;因為頻繁操作json嵌套數據 PostgreSQL得…

京東云 centos vim有操作混亂的問題

centos云服務器 安裝micro編輯器可以解決 yum install micro

限流系列之二:TDMQ CKafka 版限流方案詳解及最佳實踐

導語 在當今大數據和實時通信的時代&#xff0c;消息隊列在分布式系統中扮演著至關重要的角色。CKafka 作為一種高性能、高可靠的消息中間件&#xff0c;被廣泛應用于各種業務場景中。然而&#xff0c;隨著業務的增長和數據流量的增加&#xff0c;CKafka 在生產者和消費者以極…

消息隊列的基本概念

文章目錄 為什么需要消息隊列&#xff1f;&#x1f914;&#x1f3af; 核心價值&#x1f4cb; 使用場景 &#x1f3d7;? 架構層面的基本概念整體架構圖&#x1f4e6; 核心組件詳解1. Broker&#xff08;消息代理&#xff09;2. Topic&#xff08;主題&#xff09;3. Partition…

Shell腳本中和||語法解析

https://www.cnblogs.com/liuyuelinfighting/p/16377705.html 在 Shell 腳本中&#xff0c;&& 和 || 是邏輯操作符&#xff0c;用于根據前一個命令的退出狀態&#xff08;成功或失敗&#xff09;決定是否執行后續命令。這種語法稱為 命令鏈&#xff08;Command Chainin…

MySQL中的常見運算符

精選專欄鏈接 &#x1f517; MySQL技術筆記專欄Redis技術筆記專欄大模型搭建專欄Python學習筆記專欄深度學習算法專欄 歡迎訂閱&#xff0c;點贊&#xff0b;關注&#xff0c;每日精進1%&#xff0c;共攀技術高峰 更多內容持續更新中&#xff01;希望能給大家帶來幫助~ &…

高級IO技術詳解:阻塞/非阻塞IO、多路復用與內存映射

高級IO技術詳解&#xff1a;阻塞/非阻塞IO、多路復用與內存映射 關鍵詞&#xff1a;阻塞IO 非阻塞IO select/poll/epoll mmap 一、阻塞IO vs 非阻塞IO 類型行為特點設置方式阻塞IO- 讀空管道阻塞- 寫滿管道阻塞默認模式非阻塞IO- 讀空文件返回 -1&#xff0c;errnoEAGAIN- 寫滿…

【無標題】拓撲對偶框架的嚴格性補完與哲學突破

拓撲對偶框架的嚴格性補完與哲學突破&#xff1a; 一、數學嚴格性補完&#xff1a;同調類守恒的解決方案 1.1 負系數問題的幾何化修正 **問題本質**&#xff1a;當 $a_i$ 含負數時&#xff0c;曲率分配 $\kappa\frac{2\pi a_i}{A_{\text{max}}}$ 導致偽黎曼流形 **解決方案…

從0開始學習R語言--Day25--A/B測試 vs 多臂老虎機

通常在比較兩個不同的方案對數據的影響時&#xff0c;我們會各拿50%的數據去進行對照試驗&#xff0c;這樣觀測到的結果會最大程度地保留統計學上的特點。但實際上&#xff0c;并不是所有對比不同方案都要這樣做&#xff0c;一來&#xff0c;我們需要等到兩組實驗都完全結束后&…