創作內容

2 GP

[Unity遊戲作品]Unity初體驗--數獨小遊戲與它的程式寫法

作者:Keaton 凱特│2021-07-15 18:12:59│巴幣:4│人氣:565

  各位朋友大家好,這次要來分享在新公司的一些遊戲作品,數獨遊戲。是某朋友敲碗要小弟打這篇小弟才打的,本來有點懶得打XD
  上一次小弟做遊戲的時候已經是大四(2008年)的時候了(凱特衝浪去遊戲專案請按此),壓根沒有想到過了13年,現在還有機會碰遊戲相關的專案。因為現在換到遊戲公司工作,才得以碰到做遊戲這塊,而且其實遊戲產業也是小弟夢寐以求想做的工作,所以做得算是開心~只是薪水....(´_ゝ`)
  這次先來分享遊戲畫面跟遊戲流程。畫面影片如上,流程很簡單,先用亂數產生一個盤面,再從盤面挖洞將滿滿的格子當中挖掉一部分的數字,剩下的空格就是玩家要填空的部分了。小弟也做了自動填空跟目測檢查有無兩種以上解答的功能。
  因為這個專案當初公司只給了4天就要寫出來,小弟對Unity跟C#(Unity預設使用的程式語言)又不是很熟的狀態,所以寫得有點吃力,就算參考網路上的寫法,也寫不太出來,可說是差點就趕不出來的狀態,看著同事輕鬆解決這個專案,只能遠目(不過他幫了我很多忙,感恩同事,讚歎同事)。
  在主程式演算法方面,下面有參考的C#程式碼供大家參考,應該是沒什麼bug才對,頂多UI的部分寫得不是很好而已。這邊描述一下如何產生一個亂數產生的數獨盤面。

  1. 首先先寫GetRandomArray()使程式產生一個1~9的有序陣列,接著用亂數將這個有序列逐一交換數字順序好幾次
  2. 分別產生1~9的有序陣列並填入左上、中間、右下的九宮格內
  3. 執行SolveSudoku(),先將盤面上的數字存進sudoku陣列,接著找出盤面上數值為零(未填數字)的地方並存入陣列n[]
  4. 接著執行forcefillsdk(1),用遞迴法搜尋可能解答(若此格isValid判定答案正確則執行下一格forcefillsdk(i+1),如果碰壁則自動回上一個動作),只要在solution1[]還是空白的狀況下就用正向搜尋(如果isValid判定答案不對則加1),solution1[]有數值時就用逆向搜尋(如果isValid判定答案不對則減1)
  5. 等到solution1[]與solution2[]都有答案時(或是搜索次數超過30000次時),程式就會自動終止並秀出最終結果

  程式碼截圖如上、擷取如下,寫得也不是很好,僅供參考就好XD
using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class Sudoku : MonoBehaviour{public GameObject uiText;public GameObject InputFld;public GameObject BtnDigHole;Color BtnColor = new Color(149, 169, 245, 255);int solveStep = 0;int[,] sudoku = new int[9, 9];int[,] solution1 = new int[9, 9];int[,] solution2 = new int[9, 9];int[,] n = new int[81, 2];int nlen = 0;static int[,] sudokuSample = new int[9, 9]        {        {0,0,0,7,2,8,0,0,0},        {0,9,0,0,5,1,6,0,0},        {0,0,0,0,6,0,0,8,2},        {3,0,0,8,0,2,7,0,4},        {1,7,4,0,3,0,0,2,0},        {2,8,0,5,0,0,0,3,0},        {0,1,0,3,0,0,2,0,0},        {0,0,7,0,4,6,0,0,5},        {0,0,6,1,0,0,0,4,9}};public void SudokuSolution1(){for(int i=0;i<9 btn.getcomponent="" btn="GameObject.Find(str);" for="" gameobject="" i="" int="" j="" mage="" solution1="" str="Btn" string="" sudoku="">().color = BtnColor;}}uiText.GetComponent().text = "答案1盤面";Show();}public void SudokuSolution2(){for(int i=0;i<9 btn.getcomponent="" btn="GameObject.Find(str);" for="" gameobject="" i="" int="" j="" mage="" solution2="" str="Btn" string="" sudoku="">().color = BtnColor;}}uiText.GetComponent().text = "答案2盤面";Show();}public void SudokuSample(){BtnDigHole.SetActive(false);for(int i=0;i<9 0="" btn.getcomponent="" btn="GameObject.Find(str);" for="" gameobject="" i="" if="" int="" j="" mage="" str="Btn" string="" sudoku="" sudokusample="">().color = Color.gray;}else{string str="Btn"+(i+1)+"-"+(j+1);GameObject Btn = GameObject.Find(str);Btn.GetComponent().color = BtnColor;}}}uiText.GetComponent().text = "使用數獨樣本";Show();}public void InitSudoku(){BtnDigHole.SetActive(false);for (int i=0;i<9 0="" btn.getcomponent="" btn="GameObject.Find(str);" for="" gameobject="" i="" int="" j="" mage="" str="Btn" string="" sudoku="">().color = Color.gray;}}Show();solveStep = 0;uiText.GetComponent().text = "清空盤面";}    int[] GetRandomArray(){int[] result = new int[] {1,2,3,4,5,6,7,8,9};int loopNum = UnityEngine.Random.Range(10,100);for (int i = 0; i < loopNum; i++){int a = UnityEngine.Random.Range(0,9);int b = UnityEngine.Random.Range(0,9);            while(a == b)            {                b = UnityEngine.Random.Range(0,9);            }int temp = 0;temp = result[a];result[a] = result[b];result[b] = temp;}return result;}public void DiggingHole(){BtnDigHole.SetActive(false);int digHoleNum = 15;string digHoleText = InputFld.GetComponent().text;if ((digHoleText == "") || (int.Parse(digHoleText) > 50) || (int.Parse(digHoleText) <= 0)){InputFld.GetComponent().text = "15";digHoleNum = 15;uiText.GetComponent().text = "進行挖洞,共挖15個洞";}elsedigHoleNum = int.Parse(digHoleText);uiText.GetComponent().text = "進行挖洞,共挖"+digHoleNum.ToString()+"個洞";for (int i = 0; i < digHoleNum; i++){int a = UnityEngine.Random.Range(0,9);int b = UnityEngine.Random.Range(0,9);            while(sudoku[a,b] == 0)            {a = UnityEngine.Random.Range(0,9);b = UnityEngine.Random.Range(0,9);            }sudoku[a,b] = 0;string str="Btn"+(a+1)+"-"+(b+1);GameObject Btn = GameObject.Find(str);Btn.GetComponent().color = Color.gray;}Show();}    void SolveSudoku(){nlen = 0;n = new int[81, 2];solution1 = new int[9, 9];solution2 = new int[9, 9];//將盤面上的文字存入sudokufor (int i = 1; i <= 9; i++){for (int j = 1; j <= 9; j++){                string str="Btn"+i+"-"+j+"/Text";GameObject Btn = GameObject.Find(str);                sudoku[i-1,j-1] = int.Parse(Btn.GetComponent().text);Btn.GetComponentInParent().color = BtnColor;}}//搜尋數獨區塊為零的地方for (int i = 0; i < 9; i++){for (int j = 0; j < 9; j++){if(sudoku[i,j]==0){n[nlen, 0] = i;n[nlen, 1] = j;nlen++;}}}//用遞迴法搜尋可能解答forcefillsdk(1);}void forcefillsdk(int i){if(solveStep>=30000){uiText.GetComponent().text = "解題超過30000步,強制終止";return;}if((i > nlen) && (solution1[0,0] == 0)){Show();for(int a=0;a<9 a="" b="" ext="" for="" int="" solution1="" sudoku="" uitext.getcomponent="">().text = "完成解題,找到答案1";//所有空格填回0for (int k = 0; k < nlen; k++){sudoku[n[k, 0],n[k, 1]] = 0;}forcefillsdk(1);return;}if((i > nlen) && (solution1[0,0] != 0) && (solution2[0,0] == 0)){Show();for(int a=0;a<9 a="" b="" ext="" for="" int="" solution2="" sudoku="" uitext.getcomponent="">().text = "完成解題,找到答案1與答案2";return;}if(i > nlen){uiText.GetComponent().text = "完成解題,終止程序";return;}for (int k = 1; k <= 9; k++){if (solution1[0,0] == 0)sudoku[n[i-1, 0],n[i-1, 1]] += 1;//解答一用正向搜尋elsesudoku[n[i-1, 0],n[i-1, 1]] -= 1;//解答二用逆向搜尋if (sudoku[n[i-1, 0],n[i-1, 1]] > 9){sudoku[n[i-1, 0],n[i-1, 1]] = 1;}if (sudoku[n[i-1, 0],n[i-1, 1]] < 0){sudoku[n[i-1, 0],n[i-1, 1]] = 9;}if(isValid(n[i-1, 0], n[i-1, 1])){// print("第"+i+"("+n[i-1, 0]+","+n[i-1, 1]+")被填滿"+sudoku[n[i-1, 0],n[i-1, 1]]);solveStep++;forcefillsdk(i+1);}else{solveStep++;}}// print("第"+i+"("+n[i-1, 0]+","+n[i-1, 1]+")錯誤,數字歸零");sudoku[n[i-1, 0],n[i-1, 1]] = 0;}    //驗證函數bool isValid(int i, int j){int n = sudoku[i,j];int[] query = new int[9] {0,0,0,3,3,3,6,6,6};int t, u;//本身是否為零if (sudoku[i,j] == 0)return false;        //每一行每一列是否重複for (t=0;t<9 3="" 9="" btn="GameObject.Find(str);" checksdkcorrectness="" ext="" false="" for="" gameobject="" i-1="" i="" if="" int.parse="" int="" j-1="" j="" n="" public="" query="" return="" str="Btn" string="" sudoku="" t="" tn.getcomponent="" true="" u="" void="">().text);}}bool Correctness = true;for (int i = 0; i < 9; i++){for (int j = 0; j < 9; j++){                if(isValid(i,j) == false){Correctness = false;string str="Btn"+(i+1)+"-"+(j+1);GameObject Btn = GameObject.Find(str);Btn.GetComponent().color = Color.red;}else{string str="Btn"+(i+1)+"-"+(j+1);GameObject Btn = GameObject.Find(str);Btn.GetComponent().color = BtnColor;}}}if (Correctness){uiText.GetComponent().text = "數獨盤面正確無誤";BtnDigHole.SetActive(true);}elseuiText.GetComponent().text = "數獨盤面有以下紅色錯誤";}void Show(){for (int i = 1; i <= 9; i++){for (int j = 1; j <= 9; j++){                string str="Btn"+i+"-"+j+"/Text";GameObject Btn = GameObject.Find(str);                Btn.GetComponent().text = ""+sudoku[i-1,j-1];}}}    public void CreateGameFull()    {uiText.GetComponent().text = "開始產題...";solveStep = 0;InitSudoku();for (int i = 0; i < 3; i++){int[] temp = GetRandomArray();int p = 0;for (int j =0+(i*3);j<3 9="" autosolvesudoku="" btn="GameObject.Find(str);" ext="" for="" gameobject="" i-1="" i="" int.parse="" int="" j-1="" j="" k="" n="" p="" public="" show="" solvesudoku="" str="Btn" string="" sudoku="" temp="" tn.getcomponent="" void="">().text);}}solveStep = 0;SolveSudoku();solveStep = 0;}    void Start()    {BtnDigHole.SetActive(false);    }    void Update()    {    }}
  這次的數獨撰寫,讓我對小時候寫遊戲程式的熱誠慢慢又找回來了,希望未來會有更多的作品可以跟大家分享,也期待大家能夠多多支持國產遊戲作品,因為設計一款好遊戲真的不容易~ヽ(∀゚ )人(゚∀゚)人( ゚∀)人(∀゚ )人(゚∀゚)人( ゚∀)ノ
引用網址:https://home.gamer.com.tw/TrackBack.php?sn=5209039
All rights reserved. 版權所有,保留一切權利

相關創作

同標籤作品搜尋:數獨|unity

留言共 0 篇留言

我要留言提醒:您尚未登入,請先登入再留言

2喜歡★c5g4f4c4up2k 可決定是否刪除您的留言,請勿發表違反站規文字。

前一篇:[音樂作品]Fuse09... 後一篇:[音樂作品]Fuse10...

追蹤私訊切換新版閱覽

作品資料夾

vicpetsshu大家
分享自己拍的黑絲與肉絲腿腿照ww 喜歡可以看看小屋嘿嘿看更多我要大聲說48分前


face基於日前微軟官方表示 Internet Explorer 不再支援新的網路標準,可能無法使用新的應用程式來呈現網站內容,在瀏覽器支援度及網站安全性的雙重考量下,為了讓巴友們有更好的使用體驗,巴哈姆特即將於 2019年9月2日 停止支援 Internet Explorer 瀏覽器的頁面呈現和功能。
屆時建議您使用下述瀏覽器來瀏覽巴哈姆特:
。Google Chrome(推薦)
。Mozilla Firefox
。Microsoft Edge(Windows10以上的作業系統版本才可使用)

face我們了解您不想看到廣告的心情⋯ 若您願意支持巴哈姆特永續經營,請將 gamer.com.tw 加入廣告阻擋工具的白名單中,謝謝 !【教學】