您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么使用C#代碼實(shí)現(xiàn)經(jīng)典掃雷游戲”的相關(guān)知識(shí),小編通過(guò)實(shí)際案例向大家展示操作過(guò)程,操作方法簡(jiǎn)單快捷,實(shí)用性強(qiáng),希望這篇“怎么使用C#代碼實(shí)現(xiàn)經(jīng)典掃雷游戲”文章能幫助大家解決問(wèn)題。
布局效果如下,下面每個(gè)“網(wǎng)格”都是一個(gè)按鈕,點(diǎn)擊按鈕,就會(huì)有相應(yīng)的事件發(fā)生。
由于UniformGrid
中每個(gè)Grid的尺寸相等,所以作為雷區(qū)的容器。
<DockPanel> <DockPanel.Resources> <Style TargetType="TextBlock"> <Setter Property="Margin" Value="5"/> </Style> <Style TargetType="TextBox"> <Setter Property="Margin" Value="5"/> <Setter Property="InputMethod.IsInputMethodEnabled" Value="False"/> </Style> </DockPanel.Resources> <ToolBar DockPanel.Dock="Top"> <TextBlock Text="雷區(qū)尺寸"/> <TextBox Width="40" Text="20" x:Name="txtNumX"/> <TextBlock Text="×"/> <TextBox Width="40" Text="20" x:Name="txtNumY"/> <TextBlock Text="雷數(shù)"/> <TextBox Width="40" Text="20" x:Name="txtNumMine"/> <Button Content="????" Click="btnNewGame_Click"/> </ToolBar> <UniformGrid Name="ugMine"> </UniformGrid>
值得一提的是,由于隨機(jī)數(shù)可能在生成過(guò)程中產(chǎn)生重復(fù)的值,所以這里通過(guò)概率的方式來(lái)生成雷。
假設(shè)按鈕數(shù)為N,雷數(shù)為n,那么在][0,N]之間隨機(jī)生成一個(gè)數(shù)x,如果x<n,則判定當(dāng)前按鈕為雷。按鈕是否為雷的標(biāo)志作為布爾型存放在btn.tag中。
由于通過(guò)遍歷的方法生成雷,所以一旦剩余雷的個(gè)數(shù)和剩余按鈕的個(gè)數(shù)相等,就說(shuō)明剩余的按鈕全都是雷。這種情況發(fā)生,則不必進(jìn)行隨機(jī)數(shù)的判定。
private void newGame() { x = int.Parse(txtNumX.Text); y = int.Parse(txtNumY.Text); var nBtns = x * y; nMark = 0; nRes = int.Parse(txtNumMine.Text); if (nRes > nBtns) nRes = nBtns; pMine = new List<int>(); ugMine.Rows = y; ugMine.Columns = x; ugMine.Children.Clear(); Random rd = new Random(); int numSetMine = 0; //已經(jīng)布置的雷的個(gè)數(shù) for (int i = 0; i < nBtns; i++) { var btn = new Button(); ugMine.Children.Add(btn); btn.Click += Btn_Click; btn.MouseRightButtonDown += Btn_MouseRightButtonDown; btn.Content = ""; btn.Tag = false; if ((nRes - numSetMine) == (nBtns - i) || //如果剩余的雷數(shù)剛好等于剩余的按鈕數(shù),則剩下的按鈕都是雷 (numSetMine < nRes && rd.Next(0, nBtns) < nRes)) { btn.Tag = true; numSetMine += 1; pMine.Add(i); } } }
左鍵點(diǎn)擊,則類似于一個(gè)翻面的動(dòng)作;右鍵點(diǎn)擊,則相當(dāng)于是標(biāo)記,而且在標(biāo)記之后,不能再通過(guò)左鍵進(jìn)行翻面。
//左鍵單擊 private void Btn_Click(object sender, RoutedEventArgs e) { var btn = sender as Button; int index = ugMine.Children.IndexOf(btn); flipButton(index); if(nMark == pMine.Count || nRes == pMine.Count) MessageBox.Show("您贏了!"); } //右鍵單擊 private void Btn_MouseRightButtonDown(object sender, MouseButtonEventArgs e) { var btn = sender as Button; var flag = btn.Content.ToString() != "????"; if (flag) btn.Click -= Btn_Click; //如果已經(jīng)標(biāo)記,則卸載左鍵的功能 else btn.Click += Btn_Click; //如果取消標(biāo)記,則重新掛載左鍵的功能 btn.Content = flag ? "????" : ""; btn.Foreground = flag ? Brushes.Red : Brushes.Gray; nMark += flag ? 1 : -1; }
右鍵單擊效果如下
在翻面的時(shí)候,如果當(dāng)前按鈕為雷,則雷炸了,游戲結(jié)束。
如果當(dāng)前按鈕不是雷,那么判斷該按鈕周圍是否有雷。如果有雷,則當(dāng)前按鈕顯示周圍雷的個(gè)數(shù);如果沒(méi)雷,則將周圍的雷全部翻面——需要調(diào)用自身。
private void flipButton(int index) { var btn = ugMine.Children[index] as Button; if (!btn.IsEnabled) return; if ((bool)btn.Tag) { foreach (var i in pMine) { var mine = ugMine.Children[i] as Button; mine.Content = "????"; mine.Foreground = Brushes.Red; } MessageBox.Show("您輸了"); return; } nRes -= 1; btn.IsEnabled = false; int numMines = 0; var nears = setNear(index); foreach (var i in nears) { var near = ugMine.Children[i] as Button; if ((bool)near.Tag) numMines += 1; } if (numMines != 0) btn.Content = numMines; else foreach (var i in nears) flipButton(i); }
其中setNear
是用于獲取當(dāng)前按周圍按鈕的序號(hào),這里分別需要考慮四個(gè)角、四個(gè)邊以及中間區(qū)域。
private int[] setNear(int index) { if (index == 0) return new int[3] { 1, x, x + 1 }; if (index == x * y - 1) return new int[3] { index - 1, index - x, index - x - 1 }; if (index == x - 1) return new int[3] { x - 2, 2 * x - 1, 2 * x - 2 }; if (index == x * y - x) return new int[3] { index + 1, index - x, index - x + 1 }; if (index % x == 0) return new int[5] { index - x, index - x + 1, index + 1, index + x, index + x + 1 }; if (index % x == (x - 1)) return new int[5] { index - x - 1, index - x, index - 1, index + x - 1, index + x }; if (index < x) return new int[5] { index - 1, index + 1, index + x - 1, index + x, index + x + 1 }; if (index > x * (y - 1)) return new int[5] { index - x - 1, index - x, index - x + 1, index - 1, index + 1 }; return new int[8] { index - 1, index + 1, index - x, index-x-1, index-x+1,index + x,index+x-1,index+x+1 }; }
效果如下
關(guān)于“怎么使用C#代碼實(shí)現(xiàn)經(jīng)典掃雷游戲”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí),可以關(guān)注億速云行業(yè)資訊頻道,小編每天都會(huì)為大家更新不同的知識(shí)點(diǎn)。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。