C#扫雷游戏-3(界面部分)

界面方面实际没有什么了,只要美观、人性化就行。因为所有的逻辑都在Game类中,只要将Game作为成员变量放入窗体类中就行了。这里就将个技巧,扫雷有3个级别,根据不同的级别设置游戏的砖块和行数、列数以及地雷数,并且我们要求选中项要打勾,而其他项没勾,用傻方法也能实现。那么如果10个级别或者100个级别,那冗余的代码就更多了。
所以,先遍历级别菜单,将选中项打勾,其余都去除勾,然后根据菜单项的Tag值设置对应的级别。

Code:
  1. usingSystem;
  2. usingSystem.Collections.Generic;
  3. usingSystem.ComponentModel;
  4. usingSystem.Data;
  5. usingSystem.Drawing;
  6. usingSystem.Text;
  7. usingSystem.Windows.Forms;
  8. namespaceMineSweeper{
  9. publicpartialclassMainForm:Form{
  10. Gamegame=newGame();
  11. publicMainForm(){
  12. InitializeComponent();
  13. }
  14. privatevoidtsmiStart_Click(objectsender,EventArgse){
  15. }
  16. privatevoidMainForm_Load(objectsender,EventArgse){
  17. game.Init(pnlBoard,1);
  18. }
  19. privatevoidChangeLevel(objectsender,EventArgse){
  20. for(inti=1;i<=3;i++){
  21. ToolStripItem[]items=msMenu.Items.Find("tsmiLevel"+i,true);
  22. if(items!=null&&items.Length>0){
  23. ((ToolStripMenuItem)items[0]).Checked=false;
  24. }
  25. }
  26. ToolStripMenuItemmItem=(ToolStripMenuItem)sender;
  27. mItem.Checked=true;
  28. game.Init(pnlBoard,Convert.ToInt32(mItem.Tag));
  29. }
  30. }
  31. }

点击下载扫雷源代码

展开阅读全文

C#编写扫雷游戏

11-02

我突发奇想,想用C#编写了一个扫雷游戏,在网上搜了半天,结果一无所获。rn在图书馆翻了半天的书,硬着头皮把一本很厚很厚的书看完了,总之,还是觉得收获挺大。rn为了能够学以致用,我开始通过C#来编写扫雷游戏。rn废话少说,我们先来了解一下扫雷游戏的一些功能:rn1.首先是界面设计:通过不同颜色大小的画刷画笔以及在窗体上绘制直线,将窗体分成两个区域。一个用来显示时间和雷数还有复位按钮,一个用来装载棋盘。rnrn哎!完成这个东西其实很不容易,需要一些图片资源,要分析它们的尺寸,等等,图片上所有的资源都来自这个:rn rn就是将它们的一部分截下来放在窗体的某一位置,呵呵,而你的工作就是以一种可视化有趣的方式不断的变换变量之间的次序。rn想要代码吗?我觉得其实用处不大,关键得看懂,我也知道,一般在短时间内是不易看懂的,因为我做这个也花了不少时间。rn本来想粘贴代码的,可是字数限制了只好算了rn不管是什么游戏,产生随机数,这个少不了!我们需要编写一个类,内容如下:rn[code=csharp]using System;rnusing System.Collections.Generic;rnusing System.Linq;rnusing System.Text;rnusing System.Threading.Tasks;rnrnnamespace 扫雷rnrn class GetRandomrn rn public static Random globalRandomGenerator= GenerateNewRandomGenerator();rn public static Random GenerateNewRandomGenerator()rn rn globalRandomGenerator= new Random((int)DateTime.Now.Ticks);rn return globalRandomGenerator;rn rn public static int GetRandomInt()//随机产生0至9的一个整数rn rn return globalRandomGenerator.Next(10);rn rn public static int GetRandomInt(int max)rn rn return globalRandomGenerator.Next(max);rn rn //产生一个随机浮点数组rn public static float[] GenerateRandomOrder(int n)rn rn float[] RandomOrder=new float[n];rn for (int i = 0; i < n; i++)rn rn RandomOrder[i] =GetRandom.GetRandomFloat(0.0f,1.0f);rn rn return RandomOrder;rn rn public static int GetRandomInt(int min, int max)rn rn return globalRandomGenerator.Next(max - min) + min;rn rn public static float GetRandomFloat(float min, float max)rn rn return (float)globalRandomGenerator.NextDouble() * (max - min) + min;rn rn //将一串随机数顺序打乱rn public static int[] ArrRandom(int[] Arr)rn rn int k = 0;rn int strtmp ;rn for (int i = 0; i < Arr.Length; i++)rn rn k = GetRandomInt(Arr.Length);rn if (k != i)rn rn strtmp = Arr[i];rn Arr[i] = Arr[k];rn Arr[k] = strtmp;rn rn rn return Arr;rn rn rn[/code]rnrnrnrn当然这只是完成了边框的绘制,为了使游戏更有趣,更具可玩性,我们不妨来让地雷的布局由用户自己定义,呵呵,这就好玩多了!rnrn允许用户自己定义地雷的布局,行列数,当然,一些简单的菜单控件的布置我就不说了,只需一拖。上图:rnrn自定义布雷:rnrn这个游戏的核心部分就是递归算法。还有许多辅助函数,由于内容太多,工作量比较大,我只好一股脑粘贴啦!rn#region 几个重要的自定义函数rn //放置雷的函数rn private void LayMines()rn //获得某个方格周围雷的个数的函数rn private int GetAroundNums(MineGrid mineGrid)rn /// rn /// 当由于某种操作(可能是左键点击了一个恰好周围没有一个雷的方格,也可能是鼠标左右键点rn /// 击了一个状态为数字的方格而触发了某个周围没有一个雷的方格被显示),一个周围没有一个rn /// 雷的方格被显示,此时必须显示这个方格周围方格的周围雷的个数,而这可能发生一系列的连rn /// 锁反应,导致一片方格被展开,这个过程的实现依靠递归函数Expand(MineGrid mineGrid)来实现:rn /// rn /// rn private void Expand(MineGrid mineGrid)rn rn ExpandNums++;rn int row = mineGrid.Row;rn int col = mineGrid.Col;rn int minRow = row == 0 ? 0 : row - 1;rn int maxRow = row == RowsNum - 1 ? row : row + 1;rn int minCol = col == 0 ? 0 : col - 1;rn int maxCol = col == ColsNum - 1 ? col : col + 1;rn int aroundNums = GetAroundNums(mineGrid);rn mineGrid.State = 15 - aroundNums;rn mineGrid.OldState = 15 - aroundNums;rn if (aroundNums == 0)rn rn for (int i = minRow; i <= maxRow; i++)rn rn for (int j = minCol; j <= maxCol; j++)rn rn if (!(i == row && j == col) &&mineGrids[i, j].State == (int)MineGridState.Normal&& (!mineGrids[i, j].IsMine))rn rn Expand(mineGrids[i, j]);rn rn rn rn rn rn /// rn /// 当游戏失败时,必须显示还有哪些为雷的方格没有被确认,void Dead()函数:rn /// rn private void Dead()rn //游戏胜利的判断函数:rn private bool Victory()rn #endregionrnrn现在就可以开玩啦!rnrn不好意思,把我的个人信息粘上来了。rn再来一张,我玩过的:rnrn哈哈!有意思吧!我居然用了942秒就通过了!rn偶!忘了说了,还需要加载音乐,不然就太无趣了!rn添加一个命名空间:rnusing System.Runtime.InteropServices;rnrn向定义全局变量一样放入以下语句(具体是什么原理,?我也不太清楚)rnrn[DllImport("winmm")]rn public static extern bool PlaySound(string szSound, int hMod, int i);rn为了使编程更简单,还需要编写一些播放声音的函数。当然如果你比较牛逼,可以不写,不过你要让你多年后还能看得懂。rnprivate void Play(string waveName)rn rn PlaySound(Application.StartupPath + "\\GameSounds\\" + waveName + ".wav", 0, 1);rn rnrn在可执行目录下放置几个音乐文件,命名规则遵循见名知意,当然其他变量和函数的命名都应该遵循这个潜规则(难道你老湿没告诉你吗?)。rnrnrn还有,我们一时兴奋,完成了一项伟大的扫雷任务,想要把它保存起来,该怎么办!和其他游戏一样,我们可以来个截图,留下精彩瞬间,也可以保存一下游戏记录,以便以后翻给学弟学妹门看,看,这是我创下了丰碑!当然你也有了装逼的资本,虐小狗还是挺容易的,呵呵!rnrn保存截图这项功能是我通过网络了解到的,其实对于编程这种数据量繁重的工作对人脑的载荷能力是很有挑战性的。一个很好的应对办法是通过网络不断的学习和发展自我。分享自己的智慧,也吸收别人的精华。我不可能手把手的帮助到你,只能交给你怎样学习的方法。 这些对你在今后的学习工作中都是有用的。rnprivate void 保存截图ToolStripMenuItem_Click(object sender, EventArgs e)rn rn Bitmap bit = new Bitmap(this.Width - 16, this.Height - 7);//实例化一个和窗体一样大的bitmaprn Graphics g = Graphics.FromImage(bit);rn g.CompositingQuality = CompositingQuality.HighQuality;//质量设为最高rn //g.CopyFromScreen(this.Left+8, this.Top, 0, 0, new Size(this.Width-12, this.Height-7));//保存整个窗体为图片rn g.CopyFromScreen(new Point(this.Left + 8, this.Top), new Point(0, 0), new Size(this.Width - 16, this.Height - 7));rn //g.CopyFromScreen(panel游戏区 .PointToScreen(Point.Empty), Point.Empty, panel游戏区.Size);//只保存某个控件(这里是panel游戏区)rn bit.Save(Application.StartupPath + "\\扫雷游戏"+DateTime.Now.Year.ToString() + DateTime.Now.Month.ToString() + DateTime.Now.Year.ToString()rn + DateTime.Now.Day.ToString() + DateTime.Now.Hour.ToString() + DateTime.Now.Minute.ToString()+rn DateTime.Now.Second.ToString()+DateTime.Now.Millisecond.ToString()+".png");//默认保存格式为PNG,保存成jpg格式质量不是很好rn rnrn图片保存的名字以“扫雷游戏+日期+时间”命名rn如:rnrn保存记录需要按照一定的格式,方便其他程序调用。rnrnprivate void 保存记录ToolStripMenuItem_Click(object sender, EventArgs e)rn rn GameTimer.Stop();rn FormGetName Fgname = new FormGetName();rn if (Fgname.ShowDialog()==DialogResult.OK)rn rn string LevelInfo = "";rn for (int i = 0; i < RowsNum; i++)rn rn for (int j = 0; j < ColsNum; j++)rn rnrn LevelInfo += (mineGrids[i, j].IsMine == true) ? "1" : "0";rn rn rn LevelInfo = LevelInfo + "," + RowsNum.ToString() + "," + ColsNum.ToString() + "," + RowsColsNums[3 * Difficulty + 2].ToString()rn + "," + SpendSeconds.ToString() + "," + System.Enum.GetName(typeof(GameState), gameState) + ","+DateTime.Now.ToLongDateString()rn + "," + DateTime.Now.ToLongTimeString() + ",";rn GameConfig.AddRecord(LevelInfo, Fgname.GetUserName);rn rn if (gameState==(int)GameState.Run)rn rn GameTimer.Start();rn rn rnrn这里加载了一个计时器,这些次要的东西我都忽略不讲了。rn当然,游戏保存了以后还需要浏览哈!需要再新建一个子窗体。rnrn它的程序如下:rn在主类中调用这个类rnprivate void 浏览记录ToolStripMenuItem_Click(object sender, EventArgs e)rn rn FormScanRecord FSR = new FormScanRecord();rn FSR.Show();rn rn窗体类中构造显示函数,读取保存的信息:rnusing System;rnusing System.Collections.Generic;rnusing System.ComponentModel;rnusing System.Data;rnusing System.Drawing;rnusing System.IO;rnusing System.Linq;rnusing System.Net.Mail;rnusing System.Text;rnusing System.Threading;rnusing System.Threading.Tasks;rnusing System.Windows.Forms;rnrnnamespace 扫雷rnrn public partial class FormScanRecord : Formrn rn string showInfo;rn public FormScanRecord()rn rn InitializeComponent();rn rnrn private void FormScanRecord_Load(object sender, EventArgs e)rn rn string[] RecordInfo=GameConfig.GetFileLines();rn rn if (RecordInfo!=null)rn rn if (RecordInfo[0]=="0")rn rn MessageBox.Show("还没有游戏记录");rn this.Close();rn rn elsern rn showInfo = "一共有" + RecordInfo[0] + "次记录,按时间先后顺序分别是:\r\n";rn for (int i = 1; i < int.Parse(RecordInfo[0])+1; i++)rn rn string[] strSplit = RecordInfo[i].Split(',');rn showInfo += "\r\n第" + i.ToString() + "位扫雷员:\r\n";rn showInfo += " 姓名:" + strSplit[8] + "\r\n";rn showInfo += " 扫雷行数:" + strSplit[1] + "\r\n";rn showInfo += " 扫雷列数:" + strSplit[2] + "\r\n";rn showInfo += " 雷数:" + strSplit[3] + "\r\n";rn showInfo += " 地雷分布密度:" + (int.Parse(strSplit[3]) / (float)((int.Parse(strSplit[1]) * int.Parse(strSplit[2])))).ToString() + "\r\n";rn showInfo += " 扫雷用时:" + (int.Parse(strSplit[4]) / 60).ToString() + "分" + (int.Parse(strSplit[4]) % 60).ToString() + "秒\r\n";rn showInfo += " 扫雷记录状态:" + strSplit[5] + "\r\n";rn showInfo += " 扫雷记录日期:" + strSplit[6] + "\r\n";rn showInfo += " 扫雷记录时间:" + strSplit[7] + "\r\n";rn rn this.RecordtextBox.Text = showInfo;rn rn rn rnrn private void close_Click(object sender, EventArgs e)rn rn this.Close();rn rn rnrn最后,也是你最迫不及待想要的东西,我还是把可执行文件发给你们吧。rn点击下面的链接:rn[url=http://pan.baidu.com/s/1c0uhFCO][/url]rn需要源代码的,可以向我发送QQ邮件,我会不定时查看rn1596058469@qq.comrnrn我也不知道为啥,不能上传图片了。rnrn 论坛

没有更多推荐了,返回首页