亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C# > 正文

C#帶你玩掃雷(附源碼)

2019-10-29 21:08:33
字體:
來源:轉載
供稿:網友

掃雷游戲,大家都應該玩過吧!其實規則也很簡單,可是我們想自己實現一個掃雷,我們應該怎么做呢?

C#,掃雷

Step1: 知曉游戲原理

掃雷就是要把所有非地雷的格子揭開即勝利;踩到地雷格子就算失敗。游戲主區域由很多個方格組成。使用鼠標左鍵隨機點擊一個方格,方格即被打開并顯示出方格中的數字;方格中數字則表示其周圍的8個方格隱藏了幾顆雷;如果點開的格子為空白格,即其周圍有0顆雷,則其周圍格子自動打開;如果其周圍還有空白格,則會引發連鎖反應;在你認為有雷的格子上,點擊右鍵即可標記雷;如果一個已打開格子周圍所有的雷已經正確標出,則可以在此格上同時點擊鼠標左右鍵以打開其周圍剩余的無雷格。

1代表1的上下左右及斜角合計有一顆雷,依次輪推,2則有2顆,3則有3顆..

在確實是炸彈的方格上點了旗子,就安全了,不是炸彈的被點了旗子,后面會被炸死的..問號就先不確定這里有沒有炸彈,不會存在點錯了被炸死的狀況..

Step2: 由step1可知,游戲由格子組成,翻譯成代碼語言就叫做數組,也就是游戲地圖就是一個二維數組。格子對象,格子的值即當前雷的數量,那么此時我們暫定雷的數字標識為-1。除此之外,格子對象還有是否被顯示,顯示當前雷數量等屬性,那么我們大概可以定義這樣一個類:

 public class CellBlockRole  {    /// <summary>    /// 位于游戲地圖中的坐標點X    /// </summary>    public int X { get; set; }    /// <summary>    /// 位于游戲地圖中的坐標點Y    /// </summary>    public int Y { get; set; }    /// <summary>    /// 是否展示最后格子所代表的結果    /// </summary>    public bool IsShowResult { get; set; } = false;    /// <summary>    /// 是否計算數字結果    /// </summary>    public bool IsComputeResult { get; set; } = false;    /// <summary>    /// 是否已經展示過計算結果了    /// </summary>    public bool IsHasShowComputed { get; set; } = false;    /// <summary>    /// 當前的格子的角色數字, -1:地雷,其他當前雷的數量    /// </summary>    public int Number { set; get; } = 0;    /// <summary>    /// 是否被Flag標識    /// </summary>    public bool IsFlag { get; set; } = false;    /// <summary>    /// 是否是雷    /// </summary>    public bool IsBoom => Number == -1;  }

繪制游戲UI畫面,見代碼:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Drawing;using System.Data;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows.Forms;using SweeperLibrary.Properties;using Timer = System.Threading.Timer;namespace SweeperLibrary{  public delegate void OnGameOverDelegate();  public delegate void OnShowANumberDelegate();  public delegate void OnPublishGameTimeDelegate(string timeDescription);  public partial class GameView : UserControl  {    /// <summary>    /// 游戲結束事件    /// </summary>    public event OnGameOverDelegate OnGameOverEvent;    /// <summary>    /// 當一個格子被點擊時,顯示當前數字的事件    /// </summary>    public event OnShowANumberDelegate OnShowANumberEvent;    /// <summary>    /// 發布當前游戲的時間    /// </summary>    public event OnPublishGameTimeDelegate OnPublishGameTimeEvent;    /// <summary>    /// 游戲繪制地圖的每個格子的大小    /// </summary>    public static readonly int CellSize = 40;    /// <summary>    /// 游戲規模N*N    /// </summary>    public static readonly int GameCellCount = 10;    /// <summary>    /// 移動方向坐標點改變的數組    /// </summary>    public static readonly int[][] MoveDirectionPoints = {      new[]{-1, -1},      new[] {0, -1},      new[] {1, -1},      new[] {1, 0},      new[] {1, 1},      new[] {0, 1},      new[] {-1, 1},      new[] {-1, 0}    };    /// <summary>    /// 隨機數雷生成對象    /// </summary>    private static readonly Random random = new Random(Guid.NewGuid().GetHashCode());    /// <summary>    /// 游戲地圖標識數組    /// </summary>    private CellBlockRole[][] gameMap = new CellBlockRole[GameCellCount][];    /// <summary>    /// 雷的數量,默認為10    /// </summary>    public int BoomCount { get; set; } = 10;    /// <summary>    /// 游戲開始時間    /// </summary>    private DateTime gameStartTime;    /// <summary>    /// 計時定時器    /// </summary>    private System.Windows.Forms.Timer gameTimer = new System.Windows.Forms.Timer();    public GameView()    {      InitializeComponent();      SetStyle(ControlStyles.OptimizedDoubleBuffer, true);      SetStyle(ControlStyles.AllPaintingInWmPaint, true);      InitGame(); //默認游戲已經開始      SetGameTimer(); //設置游戲定時器    }    private void GameView_Paint(object sender, PaintEventArgs e)    {      Width = GameCellCount + 1 + GameCellCount * CellSize;      Height = GameCellCount + 1 + GameCellCount * CellSize;      //繪制游戲界面      Graphics graphics = e.Graphics;      graphics.Clear(Color.WhiteSmoke);      if (gameMap != null && gameMap.Length > 0 && gameMap[0] != null && gameMap[0].Length > 0)      {        for (int y = 0; y < GameCellCount; y++)        {          for (int x = 0; x < GameCellCount; x++)          {            int dx = x + 1 + x * CellSize,              dy = y + 1 + y * CellSize;            CellBlockRole cellBlockRole = gameMap[y][x];            graphics.FillRectangle(new SolidBrush(cellBlockRole.IsShowResult ? Color.LightSlateGray : Color.WhiteSmoke),              dx, dy, CellSize, CellSize);            graphics.DrawRectangle(new Pen(Color.LightGray), dx, dy, CellSize, CellSize);            if (cellBlockRole.IsShowResult && cellBlockRole.Number != 0)            {              switch (cellBlockRole.Number)              {                case -1: //雷                  graphics.DrawImage(Image.FromHbitmap(Resources.boom.GetHbitmap()), new RectangleF(dx, dy, CellSize, CellSize));                  break;                default: //數字                  string drawText = cellBlockRole.Number.ToString();                  Font textFont = new Font(FontFamily.GenericSansSerif, 12, FontStyle.Bold);                  SizeF textSize = graphics.MeasureString(drawText, textFont);                  graphics.DrawString(drawText, textFont, new SolidBrush(Color.White),                    dx + (CellSize - textSize.Width) / 2, dy + (CellSize - textSize.Height) / 2);                  break;              }            }          }        }      }    }    private void GameView_MouseDown(object sender, MouseEventArgs e)    {      int px = (e.X - 1) / (CellSize + 1),        py = (e.Y - 1) / (CellSize + 1);      switch (e.Button)      {        case MouseButtons.Left: //鼠標左鍵          if (!gameMap[py][px].IsShowResult)          {            if (gameMap[py][px].IsBoom)            {              new Thread(() =>              {                ShowAllCellBlockRoleNumber();                if (this.InvokeRequired)                {                  MethodInvoker del = Invalidate;                  this.Invoke(del);                } else                {                  Invalidate();                }              }).Start();              gameTimer.Stop();              OnGameOverEvent?.Invoke();            } else            {              new Thread(() =>              {                ShowNeiborhoodCellRolesByPosi(px, py);                if (this.InvokeRequired)                {                  MethodInvoker del = Invalidate;                  this.Invoke(del);                } else                {                  Invalidate();                }              }).Start();              OnShowANumberEvent?.Invoke();            }          }          break;        case MouseButtons.Right: //鼠標右鍵          break;      }    }    /// <summary>    /// 初始化游戲    /// </summary>    private void InitGame()    {      new Thread(() =>      {        InitGameMap();        GenerateBooms();        if (this.InvokeRequired)        {          MethodInvoker del = Invalidate;          this.Invoke(del);        } else        {          Invalidate();        }      }).Start();    }    /// <summary>    /// 設置游戲定時器    /// </summary>    private void SetGameTimer()    {      gameTimer.Interval = 1000;      gameTimer.Enabled = true;      gameTimer.Tick += (sender, args) =>      {        long dMillisecond = DateTime.Now.Millisecond - gameStartTime.Millisecond;        long hour = dMillisecond / 60 / 60 / 1000;        long minute = (dMillisecond - hour * (60 * 60 * 1000)) / (60 * 1000);        long second = ((dMillisecond - hour * (60 * 60 * 1000)) % (60 * 1000)) / 1000;        OnPublishGameTimeEvent?.Invoke((hour > 0 ? (hour > 9 ? hour.ToString() : "0" + hour) + ":" : "")                        + (minute > 9 ? minute.ToString() : "0" + minute) + ":" + (second > 9 ? second.ToString() : "0" + second));      };    }    /// <summary>    /// 初始化游戲地圖    /// </summary>    private void InitGameMap()    {      for (int i = 0; i < GameCellCount; i++)      {        gameMap[i] = new CellBlockRole[GameCellCount];        for (int j = 0; j < GameCellCount; j++)        {          gameMap[i][j] = new CellBlockRole          {            X = j,            Y = i          };        }      }      gameStartTime = DateTime.Now;      gameTimer.Start();    }    /// <summary>    /// 重置游戲地圖    /// </summary>    public void ResetGameMap()    {      new Thread(() =>      {        for (int i = 0; i < GameCellCount; i++)        {          for (int j = 0; j < GameCellCount; j++)          {            gameMap[i][j].X = j;            gameMap[i][j].Y = i;            gameMap[i][j].Number = 0;            gameMap[i][j].IsShowResult = false;            gameMap[i][j].IsComputeResult = false;            gameMap[i][j].IsHasShowComputed = false;          }        }        GenerateBooms(); //生成一些雷        if (this.InvokeRequired)        {          MethodInvoker del = Invalidate;          this.Invoke(del);        } else        {          Invalidate();        }      }).Start();      gameStartTime = DateTime.Now;      gameTimer.Start();    }    /// <summary>    /// 隨機生成一些地雷    /// </summary>    public void GenerateBooms()    {      for (int i = 0; i < BoomCount; i++)      {        int boomNumberIndex = random.Next(0, GameCellCount * GameCellCount - 1); //生成隨機數的范圍        int boomX = boomNumberIndex % GameCellCount,          boomY = boomNumberIndex / GameCellCount;        if (gameMap[boomY][boomX].Number == 0)          gameMap[boomY][boomX].Number = -1; //-1表示雷        else // 已經存在雷了,所以要重新處理          i--;      }      MakeAllNumberComputeInCellRole(0, 0); //默認從坐標(0,0)開始    }    /// <summary>    /// 顯示所有的格子的信息    /// </summary>    private void ShowAllCellBlockRoleNumber()    {      for (int i = 0; i < GameCellCount; i++)      {        for (int j = 0; j < GameCellCount; j++)        {          gameMap[i][j].IsShowResult = true;        }      }    }    /// <summary>    /// 顯示某點周邊所有格子的數字    /// </summary>    /// <param name="posiX">X軸坐標</param>    /// <param name="posiY">Y軸坐標</param>    private void ShowNeiborhoodCellRolesByPosi(int posiX, int posiY)    {      gameMap[posiY][posiX].IsShowResult = true;      gameMap[posiY][posiX].IsHasShowComputed = true;      int boomCount = GetBoomCountInNeiborhood(posiX, posiY);      if (boomCount == 0) //如果周圍沒有雷,則翻開所有8個方向的相關數字      {        for (int i = 0; i < MoveDirectionPoints.Length; i++)        {          int[] itemPosi = MoveDirectionPoints[i];          int rx = posiX + itemPosi[0],            ry = posiY + itemPosi[1];          bool isNotOutIndexRange = rx >= 0 && rx < GameCellCount && ry >= 0 && ry < GameCellCount;          if (isNotOutIndexRange) //防止坐標溢出          {            gameMap[ry][rx].IsShowResult = true;            if (!gameMap[ry][rx].IsHasShowComputed && gameMap[ry][rx].Number == 0)              ShowNeiborhoodCellRolesByPosi(rx, ry);          }        }      }    }    /// <summary>    /// 獲取某點附近的雷數量    /// </summary>    /// <param name="posiX">X軸坐標點</param>    /// <param name="posiY">Y軸坐標點</param>    /// <returns></returns>    private int GetBoomCountInNeiborhood(int posiX, int posiY)    {      int boomCount = 0;      for (int i = 0; i < MoveDirectionPoints.Length; i++)      {        int[] itemPosi = MoveDirectionPoints[i];        int rx = posiX + itemPosi[0],          ry = posiY + itemPosi[1];        bool isNotOutIndexRange = rx >= 0 && rx < GameCellCount && ry >= 0 && ry < GameCellCount;        if (isNotOutIndexRange && gameMap[ry][rx].IsBoom) //防止坐標溢出        {          boomCount++;        }      }      return boomCount;    }    /// <summary>    /// 計算每個格子的數字標識    /// </summary>    /// <param name="posiX">X軸坐標</param>    /// <param name="posiY">Y軸坐標</param>    private void MakeAllNumberComputeInCellRole(int posiX, int posiY)    {      int boomCount = GetBoomCountInNeiborhood(posiX, posiY);      if (boomCount != 0) //如果周圍沒有雷,則計算周圍的8個方向的格子      {        gameMap[posiY][posiX].Number = boomCount;      } else      {        if (!gameMap[posiY][posiX].IsBoom)          gameMap[posiY][posiX].Number = 0;      }      gameMap[posiY][posiX].IsComputeResult = true;      for (int i = 0; i < MoveDirectionPoints.Length; i++)      {        int[] itemPosi = MoveDirectionPoints[i];        int rx = posiX + itemPosi[0],          ry = posiY + itemPosi[1];        bool isNotOutIndexRange = rx >= 0 && rx < GameCellCount && ry >= 0 && ry < GameCellCount;        if (isNotOutIndexRange && !gameMap[ry][rx].IsComputeResult && !gameMap[ry][rx].IsBoom) //防止坐標溢出        {          MakeAllNumberComputeInCellRole(rx, ry);        }      }    }  }}

主要代碼已經實現,現已知現有代碼的定時器由問題,暫時不支持Flag(旗子標識)。當然代碼中還有其他不足的地方,游戲持續優化中。。。

源代碼地址:MineSweeper-CShape.rar

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日韩免费在线观看视频| 亚洲天堂久久av| 久久精品成人一区二区三区| 欧美激情区在线播放| 中文字幕在线看视频国产欧美在线看完整| 中文字幕亚洲专区| 亚洲精品一区在线观看香蕉| 日日摸夜夜添一区| 欧美成人激情图片网| 欧美视频精品一区| 国产精品久久久久久一区二区| 热久久这里只有| 国产亚洲欧美aaaa| 热久久这里只有| 亚洲丁香婷深爱综合| 精品久久久久久久久久国产| 精品国产乱码久久久久久虫虫漫画| 欧美性生交xxxxx久久久| 红桃视频成人在线观看| 欧美激情网友自拍| 亚洲а∨天堂久久精品喷水| 久青草国产97香蕉在线视频| 激情成人在线视频| 日韩精品久久久久久久玫瑰园| 亚洲国产精彩中文乱码av在线播放| 国产亚洲美女精品久久久| 日韩欧美在线免费| 久久精品国产一区二区三区| 久久人人爽人人| 日韩av免费观影| 欧洲美女7788成人免费视频| 51色欧美片视频在线观看| 国产免费亚洲高清| 日韩在线视频一区| 中文字幕成人精品久久不卡| 国产精品久久久久久久久久尿| 国产精品一二三在线| 97在线日本国产| 一本色道久久综合亚洲精品小说| 国产一区二区动漫| 亚洲人成电影网站色www| 亚洲欧美国产日韩中文字幕| 日韩在线观看免费| 一区二区日韩精品| 91精品久久久久久久久久| 欧美精品激情在线观看| 日av在线播放中文不卡| 日韩欧美视频一区二区三区| 亚洲理论电影网| 亚洲精品自拍视频| 国产中文字幕日韩| 亚洲欧美日韩一区二区在线| 国产亚洲欧洲高清| 91网站在线免费观看| 第一福利永久视频精品| 中文字幕欧美日韩| 亚洲欧洲一区二区三区在线观看| 欧美日韩国产精品| 亚洲国产精品va在线| 亚洲国产精品大全| 97热精品视频官网| 自拍偷拍亚洲区| 日韩精品在线免费播放| 国内揄拍国内精品少妇国语| 亚洲欧美另类在线观看| 久久999免费视频| 亚洲影院色在线观看免费| 亚洲天堂网在线观看| 日韩黄色av网站| 国产精品日韩专区| 57pao国产精品一区| 久久久国产精品x99av| 伊是香蕉大人久久| 欧美亚洲一区在线| 国产日韩欧美自拍| 日韩av不卡电影| 精品久久久久久久大神国产| 国产精品成人品| 久久久精品亚洲| 日韩精品小视频| 国产日韩在线免费| 成人精品久久av网站| 都市激情亚洲色图| 97视频在线观看播放| 亚洲国产成人91精品| 国产精品久久久久久av下载红粉| 日韩免费视频在线观看| 亚洲欧美国产精品久久久久久久| 欧美乱妇40p| 成人羞羞国产免费| 精品爽片免费看久久| 久久伊人91精品综合网站| 亚洲成年网站在线观看| 不卡av在线播放| 欧美午夜激情视频| 国产精品成人一区二区| 中文字幕亚洲字幕| 久久久av网站| 一区二区亚洲欧洲国产日韩| 欧美洲成人男女午夜视频| 欧美大片va欧美在线播放| 亚洲自拍av在线| 欧美国产视频一区二区| 亚洲伊人成综合成人网| 亚洲一级一级97网| 久久久久久久久久久人体| 日韩中文字幕在线播放| 久久偷看各类女兵18女厕嘘嘘| 深夜成人在线观看| 国产精品99久久久久久久久| 久久激情五月丁香伊人| 性欧美视频videos6一9| 国产日韩换脸av一区在线观看| 欧美成人自拍视频| 91精品美女在线| 夜夜躁日日躁狠狠久久88av| 亚洲国产日韩欧美在线图片| 欧美日在线观看| 亚洲欧美国产精品va在线观看| 7777精品久久久久久| 精品magnet| 日韩成人网免费视频| 日韩精品高清在线观看| 狠狠躁18三区二区一区| 国产狼人综合免费视频| 久久精品中文字幕一区| 成人性生交大片免费看小说| 亚洲经典中文字幕| 97热精品视频官网| 中文字幕无线精品亚洲乱码一区| 亚洲欧美国产制服动漫| 亚洲一二在线观看| 国产精品高潮在线| 日韩中文字幕网站| 国产精品午夜国产小视频| 久久人人爽国产| 欧美电影免费播放| 欧美肥老太性生活视频| 伊人久久久久久久久久久久久| 国产小视频国产精品| 亚洲人成伊人成综合网久久久| 亚洲色无码播放| 久久福利视频导航| 2019国产精品自在线拍国产不卡| 日韩欧美在线视频免费观看| 欧美激情国内偷拍| 日韩成人xxxx| 国产91精品青草社区| 亚洲性69xxxbbb| 国产福利视频一区| 国产精品成人va在线观看| 精品无码久久久久久国产| 午夜精品一区二区三区在线视频| 精品久久久久久久久久国产| 色琪琪综合男人的天堂aⅴ视频| 亚洲天堂免费视频| 亚洲美女av在线播放| 国产一区二区三区免费视频| 国产精品日韩一区| 最好看的2019的中文字幕视频| 亚洲二区中文字幕| 大胆欧美人体视频| 国产精品∨欧美精品v日韩精品| 中文字幕久热精品在线视频|