c#扫雷游戏
时间:2011-06-10 来源:windfree
一、C#实现扫雷
1、在form中
BombClass bombClass = new BombClass(); /*布雷按钮事件*/ private void initBombBtn_Click(object sender, EventArgs e) { bombClass.InitBombData(); bombClass.winHandle = bombPanel.Handle; bombPanel.Width = bombClass.Width; bombPanel.Height = bombClass.Height; bombClass.BombDraw(); //使用方法一画雷盘 //bombClass.DispBomb(); //使用方法二画雷盘 } /*雷盘的鼠标点击事件:方法一 */ private void bombPanel_MouseClick(object sender, MouseEventArgs e) { //获取鼠标点击时的位置 int row = e.Y / (bombClass.CellSize + 1); int column = e.X / (bombClass.CellSize + 1); //如果已经点击过了 if (bombClass.BombDataFlag[row, column] == 1) return; //可以显示标志 bombClass.BombDataFlag[row, column] = 1; //如果踩到的方格是数字 if (bombClass.BombData[row, column] > 0) { ; } else if (bombClass.BombData[row, column] == BombClass.BombInt) { bombClass.ShowAllBomb(); MessageBox.Show("踩到地雷了!"); return; } else if (bombClass.BombData[row, column] == 0) { //bombClass.NullDepthFindFirst(row, column);//深度优先搜索 bombClass.NullWidthFindFirst(row, column); //广度优先搜索 } if (bombClass.CheckFinishFirst()) { MessageBox.Show("成功!"); bombClass.ShowAllBomb(); } else bombClass.BombDraw(); }
/*扫雷panel重绘事件*/ private void bombPanel_Paint(object sender, PaintEventArgs e) { if (bombClass.BombStartFlag) { if (bombClass.winHandle == null) bombClass.winHandle = bombPanel.Handle; bombClass.BombDraw(); } }
2、扫雷类
public class BombClass { #region 参数 /*扫雷是否开始标志*/ public bool BombStartFlag = false; /*坐标点数据结构*/ public struct point { public int row; public int column; }; /*雷数*/ public int BombCount; /*雷数组*/ public int[,] BombData; /*是否点击的标志*/ public int[,] BombDataFlag; /*棋子大小*/ public int CellSize = 30; /*表示地雷的数字*/ public const int BombInt = -2; public System.IntPtr winHandle; public int Width; public int Height; #endregion /*初始化雷数组(点击布雷按钮之后才用)*/ public void InitBombData() { BombStartFlag = true; BombCount = 10; BombData = new int[BombCount, BombCount]; BombDataFlag = new int[BombCount, BombCount]; //是否点击了的标志数组 List<point> bombs = RadomBomb(BombCount); SetBomb(bombs); Width = (CellSize + 1) * BombCount + 1; Height = (CellSize + 1) * BombCount + 1; } /*随机数生成雷的位置*/ protected List<point> RadomBomb(int BombCount) { List<point> bombs = new List<point>(); for (int i = 0; i < BombCount; i++) { Random rad = new Random(); int row = rad.Next(0, BombCount - 1); //行号 int column = rad.Next(0, BombCount - 1); //列号 bool checkFlag = false; for (int j = 0; j < bombs.Count; j++) { if (row == ((point)bombs[j]).row && column == ((point)bombs[j]).column) { checkFlag = true;//找到一个相同位置的点 break; } } if (checkFlag) { i--; //退一位 continue; } else { point newPoint = new point() { row = row, column = column }; bombs.Add(newPoint); } } return bombs; } /*布雷(以雷为中心访问四周)*/ protected void SetBomb(List<point> bombs) { for (int i = 0; i < bombs.Count; i++) { point onePoint = bombs[i]; //用-2表示地雷 -1表示已经遍历过的空 BombData[onePoint.row, onePoint.column] = BombInt; int[] locationRound = GetRoundLocation(onePoint.row, onePoint.column); for (int j = 0; j < 8; j++) { if (locationRound[j * 2] == -1) break; else if (BombData[locationRound[j * 2], locationRound[j * 2 + 1]] != BombInt) BombData[locationRound[j * 2], locationRound[j * 2 + 1]]++; } } } /*获取四周合法的坐标并返回*/ public int[] GetRoundLocation(int row, int column) { //不合法的用-1代替 int[] locationRound = new int[16]; for (int j = 0; j < 16; j++) { locationRound[j] = -1; } int i = 0; //左上 if (row - 1 >= 0 && column - 1 >= 0) { locationRound[i++] = row - 1; locationRound[i++] = column - 1; } //上 if (row - 1 >= 0) { locationRound[i++] = row - 1; locationRound[i++] = column; } //右上 if (row - 1 >= 0 && column + 1 < BombCount) { locationRound[i++] = row - 1; locationRound[i++] = column + 1; } //左 if (column - 1 >= 0) { locationRound[i++] = row; locationRound[i++] = column - 1; } //右 if (column + 1 < BombCount) { locationRound[i++] = row; locationRound[i++] = column + 1; } //左下 if (row + 1 < BombCount && column - 1 >= 0) { locationRound[i++] = row + 1; locationRound[i++] = column - 1; } //下 if (row + 1 < BombCount) { locationRound[i++] = row + 1; locationRound[i++] = column; } //右下 if (row + 1 < BombCount && column + 1 < BombCount) { locationRound[i++] = row + 1; locationRound[i++] = column + 1; } return locationRound; } /*使用画图方法:画雷盘一 */ public void BombDraw() { Image myImage = new Bitmap(Width, Height); Graphics g = Graphics.FromImage(myImage); //画线(正方形的) for (int i = 0; i <= BombCount; i++) { g.DrawLine(new Pen(Color.Black), (CellSize + 1) * i, 0, (CellSize + 1) * i, Height); g.DrawLine(new Pen(Color.Black), 0, (CellSize + 1) * i, Width, (CellSize + 1) * i); } //画方格及数字 for (int i = 0; i < BombCount; i++) { for (int j = 0; j < BombCount; j++) { SolidBrush brush = new SolidBrush(Color.Gold); //默认金色背景画刷 FontFamily fontFamily = new FontFamily("Arial"); Font font = new Font(fontFamily, 16, FontStyle.Regular, GraphicsUnit.Pixel); string strTemp = ""; //默认需要写的字 //如果已经点击过了,需要处理显示行为 if (BombDataFlag[i, j] == 1) { //如果点击到的是大于0的数字 if (BombData[i, j] > 0) { brush = new SolidBrush(Color.White); strTemp = BombData[i, j].ToString(); } //如果点击到的是空 else if (BombData[i, j] == 0 || BombData[i, j] == -1) { brush = new SolidBrush(Color.White); } //如果点击到的是地雷 else if (BombData[i, j] == -2) { strTemp = "*"; } } g.FillRectangle(brush, (CellSize + 1) * j + 1 , (CellSize + 1) * i + 1, CellSize, CellSize); g.DrawString(strTemp, font, new SolidBrush(Color.Black), (CellSize + 1) * j + 8, (CellSize + 1) * i + 8); } } Graphics gg = Graphics.FromHwnd(winHandle); //Graphics gg = bombPanel.CreateGraphics(); gg.DrawImage(myImage, 0, 0); } /*踩到空时处理方法(深度优先搜索):方法一*/ public void NullDepthFindFirst(int row, int column) { //遍历到空,置为-1 BombData[row, column] = -1; //获取周围8个坐标位置(有时候四周并不具有8个位置,用-1表示不合法的位置) int[] eightLocation = GetRoundLocation(row, column); for (int i = 0; i < 8; i++) { //如果要访问的坐标位置不存在 if (eightLocation[i * 2] == -1) break; else { BombDataFlag[eightLocation[i * 2], eightLocation[i * 2 + 1]] = 1; if (BombData[eightLocation[i * 2], eightLocation[i * 2 + 1]] == 0) { //递归调用 NullDepthFindFirst(eightLocation[i * 2], eightLocation[i * 2 + 1]); } } } } /*踩到空时处理方法(深度优先搜索):方法一*/ public void NullWidthFindFirst(int row, int column) { BombData[row, column] = -1; BombDataFlag[row,column] = 1; //可以显示标志 //存放为空的方格坐标的队列 int[] waitCheck = new int[BombCount * BombCount * 2]; for (int k = 0; k < waitCheck.Length; k++) { waitCheck[k] = -1; } waitCheck[0] = row; waitCheck[1] = column; int frontCount = 0; //队头 int backCount = frontCount + 2; //队尾 //队头不等于队尾 while (frontCount != backCount) { //置为已经访问过 BombData[waitCheck[frontCount], waitCheck[frontCount + 1]] = -1; //得到周围8个方位的坐标 int[] eightLocation = GetRoundLocation(waitCheck[frontCount], waitCheck[frontCount + 1]); //遍历8个方位的坐标,选择可以加入候选队列的坐标 for (int i = 0; i < 8; i++) { if (eightLocation[i * 2] == -1) break; else { BombDataFlag[eightLocation[i * 2], eightLocation[i * 2 + 1]] = 1; //可以显示标志 if (BombData[eightLocation[i * 2], eightLocation[i * 2 + 1]] == 0) { BombData[eightLocation[i * 2], eightLocation[i * 2 + 1]] = -1; //加入候选队列 waitCheck[backCount++] = eightLocation[i * 2]; waitCheck[backCount++] = eightLocation[i * 2 + 1]; } } } frontCount += 2; //队列指针移动 } } /*检查扫雷是否完成:方法一*/ public bool CheckFinishFirst() { int leftCount = 0; //剩余雷数 for (int i = 0; i < BombCount; i++) { bool flag = false; for (int j = 0; j < BombCount; j++) { if (BombDataFlag[i, j] == 0) { //未点击且是雷 if (BombData[i, j] == BombInt) leftCount++; //为点击且不是雷,直接退出所有循环 else { flag = true; break; } } } if (flag) break; } if (leftCount == BombCount) { return true; } else return false; } /*踩到雷时显示所有:方法一*/ public void ShowAllBomb() { for (int i = 0; i < BombCount; i++) { for (int j = 0; j < BombCount; j++) { BombDataFlag[i, j] = 1; } } BombDraw(); } }
相关阅读 更多 +