欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

 更新時(shí)間:2017年10月11日 14:08:00   作者:Cosecant  
這篇文章主要介紹了C#帶你玩掃雷(附源碼),詳細(xì)的介紹實(shí)現(xiàn)掃雷的方法,具體一定的參考價(jià)值,有興趣的可以了解一下

掃雷游戲,大家都應(yīng)該玩過(guò)吧!其實(shí)規(guī)則也很簡(jiǎn)單,可是我們想自己實(shí)現(xiàn)一個(gè)掃雷,我們應(yīng)該怎么做呢?


Step1: 知曉游戲原理

掃雷就是要把所有非地雷的格子揭開(kāi)即勝利;踩到地雷格子就算失敗。游戲主區(qū)域由很多個(gè)方格組成。使用鼠標(biāo)左鍵隨機(jī)點(diǎn)擊一個(gè)方格,方格即被打開(kāi)并顯示出方格中的數(shù)字;方格中數(shù)字則表示其周?chē)?個(gè)方格隱藏了幾顆雷;如果點(diǎn)開(kāi)的格子為空白格,即其周?chē)?顆雷,則其周?chē)褡幼詣?dòng)打開(kāi);如果其周?chē)€有空白格,則會(huì)引發(fā)連鎖反應(yīng);在你認(rèn)為有雷的格子上,點(diǎn)擊右鍵即可標(biāo)記雷;如果一個(gè)已打開(kāi)格子周?chē)械睦滓呀?jīng)正確標(biāo)出,則可以在此格上同時(shí)點(diǎn)擊鼠標(biāo)左右鍵以打開(kāi)其周?chē)S嗟臒o(wú)雷格。

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

在確實(shí)是炸彈的方格上點(diǎn)了旗子,就安全了,不是炸彈的被點(diǎn)了旗子,后面會(huì)被炸死的..問(wèn)號(hào)就先不確定這里有沒(méi)有炸彈,不會(huì)存在點(diǎn)錯(cuò)了被炸死的狀況..

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

 public class CellBlockRole
  {
    /// <summary>
    /// 位于游戲地圖中的坐標(biāo)點(diǎn)X
    /// </summary>
    public int X { get; set; }

    /// <summary>
    /// 位于游戲地圖中的坐標(biāo)點(diǎn)Y
    /// </summary>
    public int Y { get; set; }

    /// <summary>
    /// 是否展示最后格子所代表的結(jié)果
    /// </summary>
    public bool IsShowResult { get; set; } = false;

    /// <summary>
    /// 是否計(jì)算數(shù)字結(jié)果
    /// </summary>
    public bool IsComputeResult { get; set; } = false;

    /// <summary>
    /// 是否已經(jīng)展示過(guò)計(jì)算結(jié)果了
    /// </summary>
    public bool IsHasShowComputed { get; set; } = false;

    /// <summary>
    /// 當(dāng)前的格子的角色數(shù)字, -1:地雷,其他當(dāng)前雷的數(shù)量
    /// </summary>
    public int Number { set; get; } = 0;

    /// <summary>
    /// 是否被Flag標(biāo)識(shí)
    /// </summary>
    public bool IsFlag { get; set; } = false;

    /// <summary>
    /// 是否是雷
    /// </summary>
    public bool IsBoom => Number == -1;

  }

繪制游戲UI畫(huà)面,見(jiàn)代碼:

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>
    /// 游戲結(jié)束事件
    /// </summary>
    public event OnGameOverDelegate OnGameOverEvent;

    /// <summary>
    /// 當(dāng)一個(gè)格子被點(diǎn)擊時(shí),顯示當(dāng)前數(shù)字的事件
    /// </summary>
    public event OnShowANumberDelegate OnShowANumberEvent;

    /// <summary>
    /// 發(fā)布當(dāng)前游戲的時(shí)間
    /// </summary>
    public event OnPublishGameTimeDelegate OnPublishGameTimeEvent;

    /// <summary>
    /// 游戲繪制地圖的每個(gè)格子的大小
    /// </summary>
    public static readonly int CellSize = 40;

    /// <summary>
    /// 游戲規(guī)模N*N
    /// </summary>
    public static readonly int GameCellCount = 10;

    /// <summary>
    /// 移動(dòng)方向坐標(biāo)點(diǎn)改變的數(shù)組
    /// </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>
    /// 隨機(jī)數(shù)雷生成對(duì)象
    /// </summary>
    private static readonly Random random = new Random(Guid.NewGuid().GetHashCode());
    /// <summary>
    /// 游戲地圖標(biāo)識(shí)數(shù)組
    /// </summary>
    private CellBlockRole[][] gameMap = new CellBlockRole[GameCellCount][];

    /// <summary>
    /// 雷的數(shù)量,默認(rèn)為10
    /// </summary>
    public int BoomCount { get; set; } = 10;

    /// <summary>
    /// 游戲開(kāi)始時(shí)間
    /// </summary>
    private DateTime gameStartTime;

    /// <summary>
    /// 計(jì)時(shí)定時(shí)器
    /// </summary>
    private System.Windows.Forms.Timer gameTimer = new System.Windows.Forms.Timer();

    public GameView()
    {
      InitializeComponent();
      SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
      SetStyle(ControlStyles.AllPaintingInWmPaint, true);
      InitGame(); //默認(rèn)游戲已經(jīng)開(kāi)始
      SetGameTimer(); //設(shè)置游戲定時(shí)器
    }

    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: //數(shù)字
                  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: //鼠標(biāo)左鍵
          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: //鼠標(biāo)右鍵
          break;
      }
    }

    /// <summary>
    /// 初始化游戲
    /// </summary>
    private void InitGame()
    {
      new Thread(() =>
      {
        InitGameMap();
        GenerateBooms();
        if (this.InvokeRequired)
        {
          MethodInvoker del = Invalidate;
          this.Invoke(del);
        } else
        {
          Invalidate();
        }
      }).Start();
    }

    /// <summary>
    /// 設(shè)置游戲定時(shí)器
    /// </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>
    /// 隨機(jī)生成一些地雷
    /// </summary>
    public void GenerateBooms()
    {
      for (int i = 0; i < BoomCount; i++)
      {
        int boomNumberIndex = random.Next(0, GameCellCount * GameCellCount - 1); //生成隨機(jī)數(shù)的范圍
        int boomX = boomNumberIndex % GameCellCount,
          boomY = boomNumberIndex / GameCellCount;
        if (gameMap[boomY][boomX].Number == 0)
          gameMap[boomY][boomX].Number = -1; //-1表示雷
        else // 已經(jīng)存在雷了,所以要重新處理
          i--;
      }
      MakeAllNumberComputeInCellRole(0, 0); //默認(rèn)從坐標(biāo)(0,0)開(kāi)始
    }

    /// <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>
    /// 顯示某點(diǎn)周邊所有格子的數(shù)字
    /// </summary>
    /// <param name="posiX">X軸坐標(biāo)</param>
    /// <param name="posiY">Y軸坐標(biāo)</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) //如果周?chē)鷽](méi)有雷,則翻開(kāi)所有8個(gè)方向的相關(guān)數(shù)字
      {
        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) //防止坐標(biāo)溢出
          {
            gameMap[ry][rx].IsShowResult = true;
            if (!gameMap[ry][rx].IsHasShowComputed && gameMap[ry][rx].Number == 0)
              ShowNeiborhoodCellRolesByPosi(rx, ry);
          }
        }
      }
    }

    /// <summary>
    /// 獲取某點(diǎn)附近的雷數(shù)量
    /// </summary>
    /// <param name="posiX">X軸坐標(biāo)點(diǎn)</param>
    /// <param name="posiY">Y軸坐標(biāo)點(diǎn)</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) //防止坐標(biāo)溢出
        {
          boomCount++;
        }
      }
      return boomCount;
    }

    /// <summary>
    /// 計(jì)算每個(gè)格子的數(shù)字標(biāo)識(shí)
    /// </summary>
    /// <param name="posiX">X軸坐標(biāo)</param>
    /// <param name="posiY">Y軸坐標(biāo)</param>
    private void MakeAllNumberComputeInCellRole(int posiX, int posiY)
    {
      int boomCount = GetBoomCountInNeiborhood(posiX, posiY);
      if (boomCount != 0) //如果周?chē)鷽](méi)有雷,則計(jì)算周?chē)?個(gè)方向的格子
      {
        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) //防止坐標(biāo)溢出
        {
          MakeAllNumberComputeInCellRole(rx, ry);
        }
      }
    }

  }

}

主要代碼已經(jīng)實(shí)現(xiàn),現(xiàn)已知現(xiàn)有代碼的定時(shí)器由問(wèn)題,暫時(shí)不支持Flag(旗子標(biāo)識(shí))。當(dāng)然代碼中還有其他不足的地方,游戲持續(xù)優(yōu)化中。。。

源代碼地址:MineSweeper-CShape_jb51.rar

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • C#的回調(diào)機(jī)制淺析

    C#的回調(diào)機(jī)制淺析

    這篇文章主要介紹了C#的回調(diào)機(jī)制,較為通俗的分析了回調(diào)機(jī)制的本質(zhì)與使用時(shí)的注意事項(xiàng),對(duì)于C#的學(xué)習(xí)有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-11-11
  • Unity3d射箭小游戲?qū)崿F(xiàn)示例

    Unity3d射箭小游戲?qū)崿F(xiàn)示例

    這篇文章主要為大家介紹了Unity3d射箭小游戲?qū)崿F(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • C#計(jì)算器編寫(xiě)代碼

    C#計(jì)算器編寫(xiě)代碼

    這篇文章主要為大家分享了C#計(jì)算器編寫(xiě)代碼,供大家參考,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-07-07
  • c#之用戶定義的數(shù)據(jù)類(lèi)型轉(zhuǎn)換介紹

    c#之用戶定義的數(shù)據(jù)類(lèi)型轉(zhuǎn)換介紹

    c#允許定義自己的數(shù)據(jù)類(lèi)型,這意味著需要某些工具支持在自己的數(shù)據(jù)類(lèi)型間進(jìn)行數(shù)據(jù)轉(zhuǎn)換。方法是把數(shù)據(jù)類(lèi)型轉(zhuǎn)換定義為相關(guān)類(lèi)的一個(gè)成員運(yùn)算符,數(shù)據(jù)類(lèi)型轉(zhuǎn)換必須聲明是隱式或者顯式,以說(shuō)明怎么使用它
    2014-01-01
  • C#操作INI配置文件示例詳解

    C#操作INI配置文件示例詳解

    這篇文章主要為大家詳細(xì)介紹了C#操作INI配置文件示例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • C# 中的??操作符淺談

    C# 中的??操作符淺談

    (??) 用于如果類(lèi)不為空值時(shí)返回它自身,如果為空值則返回之后的操作
    2013-04-04
  • C#多線程死鎖介紹與案例代碼

    C#多線程死鎖介紹與案例代碼

    這篇文章介紹了C#多線程的死鎖,并使用案例代碼實(shí)現(xiàn)解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì)。對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-04-04
  • C#通過(guò)PInvoke調(diào)用c++函數(shù)的備忘錄的實(shí)例詳解

    C#通過(guò)PInvoke調(diào)用c++函數(shù)的備忘錄的實(shí)例詳解

    這篇文章主要介紹了C#通過(guò)PInvoke調(diào)用c++函數(shù)的備忘錄的實(shí)例以及相關(guān)知識(shí)點(diǎn)內(nèi)容,有興趣的朋友們學(xué)習(xí)下。
    2019-08-08
  • WinForm中BackgroundWorker控件用法簡(jiǎn)單實(shí)例

    WinForm中BackgroundWorker控件用法簡(jiǎn)單實(shí)例

    這篇文章主要介紹了WinForm中BackgroundWorker控件用法,以一個(gè)簡(jiǎn)單實(shí)例形式分析了BackgroundWorker控件的定義、設(shè)置及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-08-08
  • Unity Shader實(shí)現(xiàn)模糊效果

    Unity Shader實(shí)現(xiàn)模糊效果

    這篇文章主要為大家詳細(xì)介紹了Unity Shader實(shí)現(xiàn)模糊效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-08-08

最新評(píng)論