本文将介绍js实现经典扫雷游戏的详细情况,特别是关于js实现经典扫雷游戏的方法的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于C#实现扫雷游戏、C+
本文将介绍js实现经典扫雷游戏的详细情况,特别是关于js实现经典扫雷游戏的方法的相关信息。我们将通过案例分析、数据研究等多种方式,帮助您更全面地了解这个主题,同时也将涉及一些关于C#实现扫雷游戏、C++实现扫雷游戏示例讲解、C++实现简易版扫雷游戏、C++控制台实现扫雷游戏的知识。
本文目录一览:js实现经典扫雷游戏(js实现经典扫雷游戏的方法)
本文实例为大家分享了js实现经典扫雷游戏的具体代码,供大家参考,具体内容如下
项目结构
实现效果
思路流程
1、写出基本的布局
2、利用js生成扫雷的table表格
3、利用随机数来做地雷在表格中的索引
4、初始化table表格
5、根据地雷的坐标生成地雷周围的数字
6、点击事件分成鼠标左键点击和右键点击
7、左键点击情况下又分为点到的是地雷和非地雷两种情况
8、点到的是地雷情况下,则将全部地雷显示,其他样式不变,并且不能再进行任意表格内的点击事件(左键右键都不行)
9、点到的是非地雷情况下又分为点击的数字是0和非0两种情况
10、如果是非0,则只需要显示其数字
11、如果是0,利用递归思想,遍历周围的表格,若为0则继续递归显示0,直到遇到非0停止
12、接上面的6,若进行右键点击,则显示小红旗,并且剩余地雷数-1
13、当剩余雷数为0时,判断小红旗底下是否全为地雷,若全是地雷则成功扫雷,否则扫雷失败
14、为按钮添加功能,分别为9乘以9->10个雷、16乘以16->40个地雷、28乘以28、99个地雷,以及重新开始按钮
html源码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="./css/style.css" rel="external nofollow" > </head> <body> <div>剩余雷数:<span></span></div> <div> </div> <div> <button>初级</button> <button>中级</button> <button>高级</button> <button>重新开始</button> </div> <script src="./js/main.js"></script> </body> </html>
css样式表
* { padding: 0; margin: 0; } .header { margin: 10px auto auto auto; text-align: center; } .header button { padding: 5px 15px; background-color: #02a4ad; color: #fff; text-align: center; border: none; border-radius: 8px; outline: none; cursor: pointer; } .header button.active { background-color: #00abff; } .footer { margin: 100px auto auto auto; text-align: center; } table { margin: 10px auto auto auto; border-spacing: 1px; background: #929196; } td { padding: 0; width: 20px; height: 20px; border: 2px solid; background: #ccc; border-color: #fff #a1a1a1 #a1a1a1 #fff; text-align: center; line-height: 20px; font-weight: 700; } .mine { background: #d9d9d9 url(../images/mine01.jpg) no-repeat center; background-size: cover; } .flag { background: #fff url(../images/flag.jpeg) no-repeat center; background-size: cover; } .redMine { background: #fff url(../images/mine02.jpg) no-repeat center; background-size: cover; } td.zero{ border-color: #d9d9d9; background: #d9d9d9; } td.one{ border-color: #d9d9d9; background: #d9d9d9; color: #0332fe; } td.two{ border-color: #d9d9d9; background: #d9d9d9; color: #019f02; } td.three{ border-color: #d9d9d9; background: #d9d9d9; color: #ff2600; } td.four{ border-color: #d9d9d9; background: #d9d9d9; color: #93208f; } td.five{ border-color: #d9d9d9; background: #d9d9d9; color: #ff7f29; } td.six{ border-color: #d9d9d9; background: #d9d9d9; color: #ff3fff; } td.seven{ border-color: #d9d9d9; background: #d9d9d9; color: #3fffbf; } td.eight{ border-color: #d9d9d9; background: #d9d9d9; color: #22ee0f; }
js源码
function Mine(tr, td, mineNum) { this.tr = tr; // 行 this.td = td; // 列 this.mineNum = mineNum; // 雷的数量 this.squares = []; // 方格的对象数组 this.tds = []; // 方格的DOM this.surplusMine = mineNum; // 剩余的雷数 this.mainBox = document.querySelector(''.gameBox''); // 获取游戏box元素 //this.createDom(); } /*生成随机数*/ Mine.prototype.randomNum = function () { var positionArray = new Array(this.tr * this.td); for (var i = 0; i < positionArray.length; i++) { // 利用索引来确定雷的位置 positionArray[i] = i } // 数组乱序 positionArray.sort(function () { return 0.5 - Math.random() }); return positionArray.splice(0, this.mineNum); // 取乱序的mineNum个数字当做雷的位置 } // 初始化 Mine.prototype.init = function () { var positionMine = this.randomNum(); // 获得雷的位置 var n = 0; for (var i = 0; i < this.tr; i++) { this.squares[i] = []; for (var j = 0; j < this.td; j++) { if (positionMine.indexOf(n++) != -1) { // 利用indexOf将雷放入方格数组中 this.squares[i][j] = { type: ''mine'', x: j, y: i }; } else { this.squares[i][j] = { type: ''number'', x: j, y: i, value: 0 }; } } } this.mainBox.oncontextmenu = function () { return false; } this.updateNum(); this.createDom(); //console.log(this.squares); // 处理剩余的雷数 this.mineNumDom = document.querySelector(''.mineNum''); this.surplusMine = this.mineNum; this.mineNumDom.innerHTML = this.surplusMine; // 处理游戏提示 //document.querySelector(''''); }; /*生成大表格*/ Mine.prototype.createDom = function () { var This = this; // 作用是指向实例对象 var table = document.createElement(''table''); // 创建table for (var i = 0; i < this.tr; i++) { var domTr = document.createElement(''tr''); // 创建行tr this.tds[i] = []; // 存储[[],[],[]...[]] 行 for (var j = 0; j < this.td; j++) { var domTd = document.createElement(''td''); // 创建列td domTd.pos = [i, j]; domTd.onmousedown = function () { This.play(event, this); }; this.tds[i][j] = domTd; // 存储列 [ [,],[,], [,] .....] domTr.appendChild(domTd); // 在行中添加列 } table.appendChild(domTr) // 在table中添加方格 } // 清空之前的状态 this.mainBox.innerHTML = ''''; this.mainBox.appendChild(table); // 形成大方格 tr*td } // 找格子 Mine.prototype.getAround = function (positionArray) { var x = positionArray.x; var y = positionArray.y; var result = []; // 二维,找到的各子返回 /* 这里的坐标信息如下 x-1,y-1 x,y-1 x+1,y-1 x-1,y x,y x+1,y x-1,y+1 x,y+1 x+1,y+1 */ for (var i = x - 1; i <= x + 1; i++) { for (var j = y - 1; j <= y + 1; j++) { if ( i < 0 || // 超出表格左边 j < 0 || // 超出上边 i > this.td - 1 || // 超出表格右边 j > this.tr - 1 || // 超出表格下边 (i == x && j == y || // 点击点本身 this.squares[j][i].type == ''mine'') // 如果是雷也没必要修改数值 ) { continue; } result.push([j, i]); // 将周围格子信息添加到result数组 如第j行,第i列有数字 } } return result; // 返回格子信息数组 } // 更新数字 Mine.prototype.updateNum = function () { for (var i = 0; i < this.tr; i++) { for (var j = 0; j < this.td; j++) { // 只需要更新雷周围的数字 if (this.squares[i][j].type == ''number'') { continue; } var num = this.getAround(this.squares[i][j]); for (var k = 0; k < num.length; k++) { // 如果数字周围有雷就加1 this.squares[num[k][0]][num[k][1]].value += 1; } } } } Mine.prototype.play = function (ev, obj) { var This = this; // 获取实例对象 // 点击的是左键 which=1是左键,2是中间的滚轮,3是右键 if (ev.which == 1 && obj.className != ''flag'') { var curSquare = this.squares[obj.pos[0]][obj.pos[1]]; // 各个数字对应的样式 var cl = [''zero'', ''one'', ''two'', ''three'', ''four'', ''five'', ''six'', ''seven'', ''eight'']; // 点击的是数字 if (curSquare.type == ''number'') { obj.innerHTML = curSquare.value; obj.className = cl[curSquare.value]; // 点到数字可以分成两种,0和非0 // 1.点到了数字0 if (curSquare.value == 0) { obj.innerHTML = ''''; // 将0的数字样式不显示0 function getAllZero(positionArray) { // 获取周围的格子信息 var around = This.getAround(positionArray); // 利用递归思想,使周围格子0不显示,直至不是0停止 for (var i = 0; i < around.length; i++) { // around[i]=[0,0] var x = around[i][0]; var y = around[i][1]; This.tds[x][y].className = cl[This.squares[x][y].value]; // 若依然为0 if (This.squares[x][y].value == 0) { // 递归 if (!This.tds[x][y].check) { This.tds[x][y].check = true; getAllZero(This.squares[x][y]); } } else { // 不为0则继续显示数字 This.tds[x][y].innerHTML = This.squares[x][y].value; } } } getAllZero(curSquare); } } else { // 点击的是雷,直接判断游戏结束 this.gameOver(obj); } } // which=3,鼠标点击的是右键 if (ev.which == 3) { if (obj.className && obj.className != ''flag'') { return; } obj.className = obj.className == ''flag'' ? '''' : ''flag''; // 处理剩余的雷数 // if (this.squares[obj.pos[0]][obj.pos[1]].type == ''mine'') { // this.allRight = true; // } else { // this.allRight = false; // } if (obj.className == ''flag'') { this.mineNumDom.innerHTML = --this.surplusMine; } else { this.mineNumDom.innerHTML = ++this.surplusMine; } if (this.surplusMine == 0) { for (var i = 0; i < this.tr; i++) { for (var j = 0; j < this.td; j++) { if (this.tds[i][j].className == ''flag'') { if (this.squares[i][j].type != ''mine'') { this.gameOver(); return; } } } } alert("恭喜你成功扫雷!"); this.init(); } } }; // 游戏结束方法gameover Mine.prototype.gameOver = function (clickTd) { // 1.显示所有的雷 // 2.取消所有格子的点击事件 // 3.给点中的雷标上红 for (var i = 0; i < this.tr; i++) { for (var j = 0; j < this.td; j++) { if (this.squares[i][j].type == ''mine'') { this.tds[i][j].className = ''mine''; } this.tds[i][j].onmousedown = null; } } if (clickTd) { clickTd.className = ''redMine''; } }; // 按钮的功能 var btns = document.querySelectorAll(''.header button''); var mine = null; var btnKey = 0; // 等级的索引 // 初级,中级,高级的难度设置 var headerArr = [ [9, 9, 10], [16, 16, 40], [28, 28, 99] ]; for (let i = 0; i < btns.length - 1; i++) { btns[i].onclick = function () { // 清除之前点击的样式 btns[btnKey].className = ''''; this.className = ''active''; mine = new Mine(...headerArr[i]); mine.init(); // 更新状态 btnKey = i; } } // 页面一开始就是初级扫雷 btns[0].onclick(); btns[3].onclick = function () { mine.init(); }
源码
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- 分享自己用JS做的扫雷小游戏
- 使用纯javascript实现经典扫雷游戏
- HTML+JavaScript实现扫雷小游戏
- javascript 扫雷游戏
- JavaScript版经典游戏之扫雷游戏完整示例【附demo源码下载】
- JavaScript制作windows经典扫雷小游戏
- js+canvas实现简单扫雷小游戏
- 通过javascript实现扫雷游戏代码实例
- 一步步教你使用JavaScript打造一个扫雷游戏
C#实现扫雷游戏
本文实例为大家分享了C#实现扫雷游戏的具体代码,供大家参考,具体内容如下
一、实验目的:
1、掌握c#窗体和控件的常用属性和功能
2、完成扫雷游戏的基本功能
二、实验要求:
1、游戏基本功能必须实现。鼠标左键点非雷点,否则游戏结束;鼠标右键一次标记雷点,邮件两次标记上问号,右键三次取消标记。
2、可以对游戏选择难度,分为初级、中级和高级,按笑脸按钮重新开始游戏
3、符合游戏逻辑。每个点周围的雷的个数必须正确
4、点开雷点,显示游戏结束,并且显示各个点的情况
5、点开所有非雷点或者标记完所有雷点时,能够显示游戏胜利
6、不接受键盘操作,只接受鼠标操作
三、实验内容:
1、构建菜单栏,添加开始栏、帮助栏,开始栏用于游戏难度的选择,帮助栏用于游戏规则的介绍
2、创建雷区,使用buttonarray模拟雷区,start按钮用于重新开始游戏
3、鼠标左键时,分三种情况:
(1)鼠标点击雷点时,直接显示游戏结束
(2)鼠标点击空白点时,周围没雷,则显示周围点的情况,周围有雷,只显示此点的雷数
(3)鼠标左键点了一个大于0的数字,显示周围雷点的情况,若周围雷点标错,直接显示游戏结束
4、鼠标右键时,第一次标记为雷点,第二次标记为疑问,第三次取消标记。
5、显示周围点的情况时,因为周围点的雷点数也可能为0,还需要显示此点周围的情况,需用递归,完成此项功能。
6、点击笑脸按钮时,如果不是第一次开始,就删除原有按钮,否则直接初始化长度、宽度和雷数,重新构建button按钮
7、点击菜单栏的难度选择按钮时,如果不是第一次开始,就删除原有按钮,否则直接初始化长度、宽度和雷数,重新构建button按钮
四、实验源代码:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class Form1 : Form { public Form1() { InitializeComponent(); Size s = new Size(250,300); this.MaximumSize = this.MinimumSize = s; this.Size = s; } Button start = new Button(); Button[,] buttonarray; int[,] MileState; int Miles = 10; int widths = 9, heights = 9; int remain;//剩余雷数 int notMiles;//剩余非雷数 int isfirst = 1;//是否是第一次 int[,] sign;//表示各点是否输出 private void Form1_Load(object sender, EventArgs e) { MenuStrip ms = new MenuStrip(); ToolStripMenuItem tsmione = new ToolStripMenuItem("开始"); ToolStripMenuItem tsmi1 = new ToolStripMenuItem("初级"); ToolStripMenuItem tsmi2 = new ToolStripMenuItem("中级"); ToolStripMenuItem tsmi3 = new ToolStripMenuItem("高级"); ToolStripMenuItem tsmi4 = new ToolStripMenuItem("退出"); tsmione.DropDownItems.Add(tsmi1); tsmione.DropDownItems.Add(tsmi2); tsmione.DropDownItems.Add(tsmi3); tsmione.DropDownItems.Add(tsmi4); ms.Items.Add(tsmione); tsmi1.Click += new EventHandler(tsmi1_Click); tsmi2.Click += new EventHandler(tsmi2_Click); tsmi3.Click += new EventHandler(tsmi3_Click); tsmi4.Click += new EventHandler(tsmi4_Click); ToolStripMenuItem tsmitwo = new ToolStripMenuItem("帮助"); ToolStripMenuItem tsmi5 = new ToolStripMenuItem("游戏规则"); tsmi5.Click += new EventHandler(tsmi5_Click); tsmitwo.DropDownItems.Add(tsmi5); ms.Items.Add(tsmitwo); this.Controls.Add(ms); //笑脸按钮 start.Text = ""; start.Location = new Point(75, 25); start.Click += new EventHandler(start_Click); this.Controls.Add(start); } private void tsmi1_Click(object sender, EventArgs e) { Size s = new Size(250, 300); this.MaximumSize = this.MinimumSize = s; this.Size = s; if (isfirst == 1) { widths = 9; heights = 9; Miles = 10; Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); isfirst = 0; return; } delete(); widths = 9; heights = 9; Miles = 10; Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); } private void tsmi2_Click(object sender, EventArgs e) { Size s = new Size(400, 450); this.MaximumSize = this.MinimumSize = s; this.Size = s; if (isfirst == 1) { widths = 16; heights = 16; Miles = 40; Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); isfirst = 0; return; } delete(); widths = 16; heights = 16; Miles = 40; Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); } private void tsmi3_Click(object sender, EventArgs e) { Size s = new Size(650, 450); this.MaximumSize = this.MinimumSize = s; this.Size = s; if (isfirst == 1) { widths = 30; heights = 16; Miles = 99; Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); isfirst = 0; return; } delete(); widths = 30; heights = 16; Miles = 99; Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); } //删除控件 public void delete() { int i, j; for (i = 0; i < heights; i++) for (j = 0; j < widths; j++) this.Controls.Remove(buttonarray[i, j]); } private void tsmi4_Click(object sender, EventArgs e) { Close(); } private void tsmi5_Click(object sender, EventArgs e) { string str = "鼠标左键点开非雷点继续游戏,点开雷点游戏结束\r\n"; str += "鼠标右键一次标记雷点,右键两次标记问号,右键三次取消标记"; MessageBox.Show(str); } //设计扫雷界面,布雷 private void Initialize_button(object sender, EventArgs e) { //初始化游戏界面 //创建扫雷按钮,设计游戏界面 buttonarray = new Button[heights, widths]; MileState = new int[heights, widths]; notMiles = widths * heights - Miles; remain = Miles; int i, j; for (i = 0; i < heights; i++) { for (j = 0; j < widths; j++) { buttonarray[i, j] = new System.Windows.Forms.Button(); buttonarray[i, j].Location = new System.Drawing.Point(20 + 20 * j, 60 + 20 * i); buttonarray[i, j].Size = new System.Drawing.Size(20, 20); buttonarray[i, j].UseVisualStyleBackColor = true; buttonarray[i, j].Text = ""; buttonarray[i, j].MouseDown += new MouseEventHandler(but_MouseDown); this.Controls.Add(buttonarray[i, j]); } } int count = 0; //雷区初始化,鼠标右键次数初始化 for (i = 0; i < heights; i++) for (j = 0; j < widths; j++) MileState[i, j] = 0; //设置雷的位置 while (count < Miles) { Random r = new Random(); i = r.Next(heights); j = r.Next(widths); if (MileState[i, j] != -1) { MileState[i, j] = -1; count++; //雷点周围非雷的点各加1 if (i - 1 >= 0 && j - 1 >= 0 && MileState[i - 1, j - 1] != -1) MileState[i - 1, j - 1] += 1; if (i - 1 >= 0 && MileState[i - 1, j] != -1) MileState[i - 1, j] += 1; if (i - 1 >= 0 && j + 1 < widths && MileState[i - 1, j + 1] != -1) MileState[i - 1, j + 1] += 1; if (j - 1 >= 0 && MileState[i, j - 1] != -1) MileState[i, j - 1] += 1; if (j + 1 < widths && MileState[i, j + 1] != -1) MileState[i, j + 1] += 1; if (i + 1 < heights && j - 1 >= 0 && MileState[i + 1, j - 1] != -1) MileState[i + 1, j - 1] += 1; if (i + 1 < heights && MileState[i + 1, j] != -1) MileState[i + 1, j] += 1; if (i + 1 < heights && j + 1 < widths && MileState[i + 1, j + 1] != -1) MileState[i + 1, j + 1] += 1; } } } //点击笑脸按钮 private void start_Click(object sender, EventArgs e) { if (isfirst == 1) { Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); isfirst = 0; return; } delete(); remain = Miles; notMiles = widths * heights - Miles; start.Text = ""; Initialize_button(sender, e); start.Location = new Point((buttonarray[0, 0].Location.X + buttonarray[0, widths - 1].Location.X + 20 - start.Size.Width) / 2, 25); } //按下鼠标键时 private void but_MouseDown(object sender, MouseEventArgs e) { //获取按钮坐标 int x = (this.PointToClient(MousePosition).Y - 60) / 20; int y = (this.PointToClient(MousePosition).X - 20) / 20; sign = new int[heights, widths]; //递归时表示是否访问 for (int i = 0; i < heights; i++) for (int j = 0; j < widths; j++) sign[i, j] = 0; //鼠标左键点了一个大于0的数字 if (e.Button == MouseButtons.Left && buttonarray[x, y].Text != "" && buttonarray[x, y].Text != "×" && buttonarray[x, y].Text != "?" && buttonarray[x, y].Text != "-1") { int num = 0; bool issigned = false; //周围标记的地雷个数 if (x - 1 >= 0 && y - 1 >= 0) { if (buttonarray[x - 1, y - 1].Text == "×") num++; else if (buttonarray[x - 1, y - 1].Text == "-1") issigned = true; } if (x - 1 >= 0) { if (buttonarray[x - 1, y].Text == "×") num++; else if (buttonarray[x - 1, y].Text == "-1") issigned = true; } if (x - 1 >= 0 && y + 1 < widths) { if (buttonarray[x - 1, y + 1].Text == "×") num++; else if (buttonarray[x - 1, y + 1].Text == "-1") issigned = true; } if (y - 1 >= 0) { if (buttonarray[x, y - 1].Text == "×") num++; else if (buttonarray[x, y - 1].Text == "-1") issigned = true; } if (y + 1 < widths) { if (buttonarray[x, y + 1].Text == "×") num++; else if (buttonarray[x, y + 1].Text == "-1") issigned = true; } if (x + 1 < heights && y - 1 >= 0) { if (buttonarray[x + 1, y - 1].Text == "×") num++; else if (buttonarray[x + 1, y - 1].Text == "-1") issigned = true; } if (x + 1 < heights) { if (buttonarray[x + 1, y].Text == "×") num++; else if (buttonarray[x + 1, y].Text == "-1") issigned = true; } if (x + 1 < heights && y + 1 < widths) { if (buttonarray[x + 1, y + 1].Text == "×") num++; else if (buttonarray[x + 1, y + 1].Text == "-1") issigned = true; } if (buttonarray[x, y].Text == Convert.ToString(num)) { if (issigned == false) { print(x, y, sign); notMiles++; } else MessageBox.Show("哎呀,点错了,重新开始吧"); } } //鼠标左键,周围没雷 if (e.Button == MouseButtons.Left && MileState[x, y] == 0) { if (sign[x, y] == 0) print(x, y, sign); if (notMiles == 0) MessageBox.Show("恭喜你,扫雷成功,回去领赏吧", "成功"); } //鼠标左键,周围有雷 if (e.Button == MouseButtons.Left && MileState[x, y] > 0) { if (sign[x, y] == 0 && --notMiles == 0) MessageBox.Show("恭喜你,扫雷成功,回去领赏吧", "成功"); sign[x, y] = 1; buttonarray[x, y].FlatStyle = FlatStyle.Popup; buttonarray[x, y].Text = Convert.ToString(MileState[x, y]); } //鼠标左键,错误 if (e.Button == MouseButtons.Left && MileState[x, y] == -1) { for (x = 0; x < heights; x++) for (y = 0; y < widths; y++) { if (MileState[x, y] != 0) buttonarray[x, y].Text = Convert.ToString(MileState[x, y]); else buttonarray[x, y].FlatStyle = FlatStyle.Popup; } start.Text = ""; MessageBox.Show("哎呀,点错了,重新开始吧!"); } //鼠标右键 if (e.Button == MouseButtons.Right) { //第一次鼠标右键 if (buttonarray[x, y].Text == "" && sign[x, y] == 0) { //用X表示雷 buttonarray[x, y].Text = "×"; sign[x, y] = 1; if (MileState[x, y] == -1) { if (--remain == 0) MessageBox.Show("恭喜你,扫雷成功,回去领赏吧", "成功"); } } //第二次鼠标右键 else if (buttonarray[x, y].Text == "×") { buttonarray[x, y].Text = "?"; remain++; } //第三次鼠标右键 else if (buttonarray[x, y].Text == "?") { buttonarray[x, y].Text = ""; sign[x, y] = 0; } } } //显示周围雷区的情况,递归 private void print(int x, int y, int[,] sign) { buttonarray[x, y].FlatStyle = FlatStyle.Popup; sign[x, y] = 1; notMiles--; if (x - 1 >= 0 && y - 1 >= 0 && sign[x - 1, y - 1] == 0) if (MileState[x - 1, y - 1] > 0) { buttonarray[x - 1, y - 1].Text = Convert.ToString(MileState[x - 1, y - 1]); buttonarray[x - 1, y - 1].FlatStyle = FlatStyle.Popup; sign[x - 1, y - 1] = 1; } else if (MileState[x - 1, y - 1] == 0) print(x - 1, y - 1, sign); if (x - 1 >= 0 && sign[x - 1, y] == 0) if (MileState[x - 1, y] > 0) { buttonarray[x - 1, y].Text = Convert.ToString(MileState[x - 1, y]); buttonarray[x - 1, y].FlatStyle = FlatStyle.Popup; sign[x - 1, y] = 1; } else if (MileState[x - 1, y] == 0) print(x - 1, y, sign); if (x - 1 >= 0 && y + 1 < widths && sign[x - 1, y + 1] == 0) if (MileState[x - 1, y + 1] > 0) { buttonarray[x - 1, y + 1].Text = Convert.ToString(MileState[x - 1, y + 1]); buttonarray[x - 1, y + 1].FlatStyle = FlatStyle.Popup; sign[x - 1, y + 1] = 1; } else if (MileState[x - 1, y + 1] == 0) print(x - 1, y + 1, sign); if (y - 1 >= 0 && sign[x, y - 1] == 0) if (MileState[x, y - 1] > 0) { buttonarray[x, y - 1].Text = Convert.ToString(MileState[x, y - 1]); buttonarray[x, y - 1].FlatStyle = FlatStyle.Popup; sign[x, y - 1] = 1; } else if (MileState[x, y - 1] == 0) print(x, y - 1, sign); if (y + 1 < widths && sign[x, y + 1] == 0) if (MileState[x, y + 1] > 0) { buttonarray[x, y + 1].Text = Convert.ToString(MileState[x, y + 1]); buttonarray[x, y + 1].FlatStyle = FlatStyle.Popup; sign[x, y + 1] = 1; } else if (MileState[x, y + 1] == 0) print(x, y + 1, sign); if (x + 1 < heights && y - 1 >= 0 && sign[x + 1, y - 1] == 0) if (MileState[x + 1, y - 1] > 0) { buttonarray[x + 1, y - 1].Text = Convert.ToString(MileState[x + 1, y - 1]); buttonarray[x + 1, y - 1].FlatStyle = FlatStyle.Popup; sign[x + 1, y - 1] = 1; } else if (MileState[x + 1, y - 1] == 0) print(x + 1, y - 1, sign); if (x + 1 < heights && sign[x + 1, y] == 0) if (MileState[x + 1, y] > 0) { buttonarray[x + 1, y].Text = Convert.ToString(MileState[x + 1, y]); buttonarray[x + 1, y].FlatStyle = FlatStyle.Popup; sign[x + 1, y] = 1; } else if (MileState[x + 1, y] == 0) print(x + 1, y, sign); if (x + 1 < heights && y + 1 < widths && sign[x + 1, y + 1] == 0) if (MileState[x + 1, y + 1] > 0) { buttonarray[x + 1, y + 1].Text = Convert.ToString(MileState[x + 1, y + 1]); buttonarray[x + 1, y + 1].FlatStyle = FlatStyle.Popup; sign[x + 1, y + 1] = 1; } else if (MileState[x + 1, y + 1] == 0) print(x + 1, y + 1, sign); } } }
五、实验结果:
1、用”×”标记雷点,用”?”标记疑问点,空白点表示周围无雷点或者该点还未点开,根据颜色区别二者。
2、游戏胜利和游戏结束显示messagebox。
3、第一次开始点击笑脸按钮,重新开始点击哭脸按钮。
4、点击开始菜单栏的子菜单栏选择游戏难度,初级、中级、高级的雷点分别为10、40、99个
(初级)
(中级)
(高级)
点击雷点,显示游戏错误,游戏结束
六、总结
通过本次实验,对c#控件和窗体有了更深入的了解,懂得如何根据各个控件的特点实现扫雷对应的功能,希望在以后能更加熟练地使用各个控件。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- C#仿Windows XP自带的扫雷游戏
- c# 实现自动扫雷
- 利用C#编写扫雷游戏(附源码)
- C#带你玩扫雷(附源码)
- 详解从零开始---用C#制作扫雷游戏
C++实现扫雷游戏示例讲解
这篇文章主要介绍了C++实现扫雷游戏示例讲解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
C/C++实现扫雷小游戏
源代码:
github:https://github.com/KamSss/C-Practice/tree/master/minesweeper扫雷小游戏/minesweeper扫雷
总体构造:
a.简易的游戏菜单逻辑
b.初始化棋盘
c.布置雷的位置
d.排雷、棋盘打印、判断输赢(难点)
a.简易的游戏菜单逻辑
简单的通过一个输入0和1实现判断是玩游戏还是退出游戏的逻辑
输入1则进入游戏
输入0则break退出游戏,且退出do…while循环,程序结束。
void test(){ int input = 0; do{ menu(); cout --"; cin >> input; switch (input) { case 1: game(); break; case 0: cout
b.初始化棋盘
一、越界情况的考虑
为了减少边界情况可能出现越界访问的情况,把棋盘扩大一圈,但是在显示的时候只显示没扩大之前的棋盘。
二、棋盘打印的考虑
如果只使用一个二维数组,同时要记录雷的位置和每一个位置附近的雷数以及点击和未点击的位置显示显然不合适。所以: 初始化两个棋盘,一个专门用来存放雷的位置,一个专门用于打印当前棋盘给玩家看。//初始化格子 InitBoard(mine, ROWS, COLS, '0'); InitBoard(show, ROWS, COLS, '*'); void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { memset(&board[0][0], set, rows*cols*sizeof(board[0][0])); }初始化完,得到一个全0的雷盘,和一个全*的显示盘。c.布置雷的位置这里用随机数布置雷的位置,会不会对同一个点多次放雷呢?这里的解决办法是,如果当前随机到的位置已经有雷就再随机一个位置防雷。void Setmine(char board[ROWS][COLS], int row, int col) { srand((unsigned int)time(NULL)); int count = EASY_COUNT; while (count) { int x = rand() % row + 1; int y = rand() % col + 1; if (board[x][y] == '0') { board[x][y] = '1'; count--; } } }d.排雷、棋盘打印、判断输赢(难点)d排雷的逻辑判断:C++实现简易版扫雷游戏
一、菜单栏
1.先用printf函数制作一个简易版的菜单,并附上选项提示,玩游戏或者退出游戏
2.为了使玩家能选择玩或者不玩游戏,则采用do while循环比较合适,同时,借助switch case语句来进行选择
3.玩游戏的那个选项,只需调用game()函数即可
二、创建棋盘数组
为了便于修改棋盘大小,所以采用宏定义的方式定义其行与列
由于有三个信息:放置雷的的信息,周围雷的信息,以及没有雷的信息,所以采用两个棋盘比较合适
又因为每排查一次雷,都得打印该排查坐标周围八个坐标有几个雷的信息,所以为了防止数组越界,从而采用比该棋盘大一圈的棋盘,但是最外面一圈不放置雷
三、初始化棋盘
因为显示棋盘和放置雷的棋盘都需要初始化,为了使两个棋盘调用同一个初始化函数,所以采取多传一个参数的方法
四、打印棋盘
为了排查雷时,能够使棋盘间分割,从而更加清晰,所以最上面和最下面都各打印一个分割行
为了便于游戏玩家找到想要排查的坐标,所以将其行与列的提示打印
打印棋盘时,最外边一圈不需要打印,所以数组下标从1开始即可
五、布置雷
因为想让雷的个数便于更改,所以采用宏定义的方式更好
由于布置雷的个数不止一个,所以必然得采用循环的方式来进行
同时,为了使布置的雷具有随机性,那么就需要采用随机函数和时间戳来进行,time和rand函数,另外使用rand函数的同时,需要调用srand函数
随机数具有不确定性,所以需要将其%上棋盘(不包括最外层)的行与列,再+1,才能限制其范围为布置雷的范围或排查雷的范围
六、排查雷
排查的坐标是有范围限制的,所以输入错误时,需要给予提示
排雷涉及多次排查,所以得采用循环
如果排查雷时踩到雷,则这局游戏也就结束了,就该跳出循环,并给予提示,同时打印棋盘,让玩家输的明白点儿
如果此次排查雷成功,那就需打印此坐标周围八个坐标有雷的个数
由于雷的个数采用整数,而''1'' - ''0'' = 1,所以每个坐标的数都要-‘0’,如下图
然后,把此数返回给show棋盘数组,同时打印show棋盘数组
同时,show棋盘数组是浮点型,所以需该整数+‘0’再赋值给show棋盘数组
当排查的坐标只有有雷的坐标没有打印时,就表示玩家赢了,即定义一个变量,每排查一个雷就+1,当其等于棋盘(不包括最外层)的坐标个数-雷的个数时,玩家就赢了
七、全部代码
//测试文件 #include"game.h" void menu() { printf("**************************\n"); printf("**** 1.play ********\n"); printf("**** 0.exit ********\n"); printf("**************************\n"); } //玩游戏 void game() { //创建棋盘 //放置雷的棋盘 char mine[ROWS][COLS]; //显示排查后的棋盘 char show[ROWS][COLS]; //初始化棋盘 InitBoard(mine, ROWS, COLS, ''0''); InitBoard(show, ROWS, COLS, ''*''); //打印棋盘 //DisplayBoard(mine, ROW, COL); DisplayBoard(show, ROW, COL); //布置雷 SetMineBoard(mine, ROW, COL); //排查雷 FindBoard(mine, show, ROW, COL); } int main() { int input = 0; srand((unsigned int)time(NULL)); do { menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 1: game();//玩游戏 break; case 0: printf("退出游戏\n"); break; default: printf("选择错误,请重新选择\n"); break; } } while (input); return 0; } //声明文件 #pragma once #include<stdio.h> #include<stdlib.h> #include<time.h> //用宏定义来定义棋盘行与列,便于修改其大小 #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 //放置雷的个数 #define EASY_COUNT 10 //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set); //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col); //布置雷 void SetMineBoard(char board[ROWS][COLS], int row, int col); //排查雷 void FindBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col); //定义文件 #include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols, char set) { int i = 0; for (i = 0; i < rows; i++) { int j = 0; for (j = 0; j < cols; j++) { board[i][j] = set; } } } //打印棋盘 void DisplayBoard(char board[ROWS][COLS], int row, int col) { int i = 0; printf("--------------------------------\n"); //行提示 for (i = 0; i <= row; i++) { printf("%d ", i); } printf("\n"); for (i = 1; i <= row; i++) { int j = 0; //列提示 printf("%d ",i); for (j = 1; j <= col; j++) { printf("%c ", board[i][j]); } printf("\n"); } printf("--------------------------------\n"); } //布置雷 void SetMineBoard(char board[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int count = 0;//已经布置雷的个数 while (count < EASY_COUNT) { x = rand() % row + 1; y = rand() % col + 1; if (board[x][y] == ''0'') { board[x][y] = ''1''; count++; } } } int GetMineBoard(char board[ROWS][COLS], int x, int y) { return (board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + board[x + 1][y] + board[x + 1][y + 1] - 8 * ''0''); } //排查雷 void FindBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) { int x = 0; int y = 0; int win = 0;//已经排查雷的个数 while (win < row * col - EASY_COUNT) { printf("请输入要排查的坐标:"); scanf("%d %d", &x, &y); if (x >= 1 && x <= col && y >= 1 && y <= col) { if (mine[x][y] == ''1'') { printf("很遗憾,你被炸死了\n"); DisplayBoard(mine, ROW, COL); break; } else { show[x][y] = GetMineBoard(mine, x, y) + ''0''; DisplayBoard(show, ROW, COL); win++; } } else { printf("坐标非法,请重新输入\n"); } } if (win == row * col - EASY_COUNT) { printf("恭喜您,排雷成功!\n"); DisplayBoard(mine, ROW, COL); } }
总结
到此这篇关于C++实现简易版扫雷游戏的文章就介绍到这了,更多相关C++扫雷内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!
- C++ 情怀游戏扫雷的实现流程详解
- C++实现趣味扫雷游戏
- 380行C++代码实现扫雷小游戏
- C++代码实现扫雷游戏
- C++实现简单扫雷小游戏
- C++实现扫雷游戏示例讲解
- C++实现扫雷程序开发
C++控制台实现扫雷游戏
本文实例为大家分享了C++控制台实现扫雷游戏的具体代码,供大家参考,具体内容如下
花了一下午写出来的控制台扫雷,主要通过修改和打印数组来实现。
主要的问题点:
1.在显示地图的过程中,既要显示数字,又要显示雷和符号,所以的用string类型的二维向量,vector<vector<string.>>;中间要利用ASCII码将int型的数字转化为字符串。
2.生成地图的时候,雷是随机的,我这里采用的做法是取余生成雷,举个例子,如果雷数是格子数的十分之一,那我遍历整个二维数组,在rand()%8 == 0时放置一颗雷,当放置10颗之后停止,这样可能会导致我的雷都偏前面一点,哈哈。
3.对于没有雷的格子,需要做一个遍历,统计周边的雷数,为了方便,实际地图要大一圈,实际的边长+2,边不作为地图,只为统计雷数时方便存在。
4.当点开一颗雷之后,如果数字是0,那么四周为0的数字也要被点亮,因此在这里使用递归实现dfs。
5.在每次进行一个格子操作之后,使用一个count计数,所有格子操作完后,游戏结束统计游戏结果,在此之前,踩到雷也会导致游戏结束。
附上游戏截图和代码
主函数
#include<vector> #include<algorithm> #include<functional> #include<iostream> #include<windows.h> #include"gameManager.h" #include"map.h" using namespace std; int main() { GameManager* game = new GameManager(); while (true) { int diff = game->difficultNumber();//玩家的难度选择参数 Map* m = new Map(diff); m->initMap(); while (true) { m->showMap(); int swicth; cout << "1.踩雷" << endl; cout << "2.插旗子" << endl; cout << "3.取消插旗子" << endl; cin >> swicth; if (swicth == 1) { //踩雷;如果踩到雷了返回1,没踩到返回0 if (game->stepOnMine(m)) break; } else if (swicth == 2) { //插旗子 game->flagMine(m); } else if (swicth == 3) { //取消插旗子 game->cancelFalgMine(m); } else { cout << "您的输入有误!" << endl; } //判断格子是否被开完,开完了则取胜 if (m->gameOver()) { cout << "恭喜你获得胜利!" << endl; m->showMap(); break; } } int over = 0; cout << "1.回到主菜单" << endl; cout << "other.退出游戏" << endl; cin >> over; if (over == 1) { system("cls"); continue; } else break; } system("pause"); return 0; }
map类
头文件
```cpp #pragma once #include<ctime> #include <vector> #include<string> #include <iostream> using namespace std; class Map { public: Map(int);//根据难度构造地图 void initMap();//根据难度初始化地图 string aroudMineNum (const vector<vector<string>>&, const int&, const int&) const;//判断某个坐标桌边的雷数 void showMap();//打印showMapArray数组 int dateUpMap(const int&, const int&);//如果返回值为1,继续,返回值为0表示结束,如果返回值为-1表示非法输入 int flag(const int&, const int&);//插旗子修改显示数组 int cancelFlag(const int&, const int&);//取消旗子时修改显示数组 bool gameOver(); private: int mapCount;//格子用完的计数 int difficult;//难度 vector<vector<string>> map;//隐藏的雷表 vector<vector<string>> showMapArray;//公开的显示数组 };
源文件
#include"map.h" Map::Map(int difficult) : difficult(difficult), mapCount(difficult* difficult) { } //初始化地图数组 void Map::initMap() { //根据难度设置二维数组的大小以及雷的数量 int mineNumber = difficult * difficult * 10;//雷的数量 int size = 10 * difficult;//此处尺寸加2,四边都为零,这样方便统计没有雷的格子上的数据 srand(time(0)); //使用随机数设置雷的数量 for (int i = 0; i < size + 2; ++i) { vector<string> temp; for (int j = 0; j < size + 2; ++j) { if (rand() % 8 == 0 && mineNumber != 0 && i != 0 && j != 0 && i != size - 1 && j != size - 1) { temp.push_back("*"); --mineNumber; } else { temp.push_back("0"); } } map.push_back(temp); } //此外还需要根据雷的位置和数量在其他位置上提示! for (int i = 1; i < size - 1; ++i) { for (int j = 1; j < size - 1; ++j) { if (map[i][j] != "*") { map[i][j] = aroudMineNum(map, i, j); } } } //初始化显示显示数组,注意!此数组要显示行列数,所以比上述数组多一行一列 for (int i = 0; i < size + 1; ++i) { vector<string> temp; for (int j = 0; j < size + 1; ++j) { if (i == 0) { string t; if (j < 10) { t.push_back(48); t.push_back(j + 48); } else if (j < 20) { t.push_back(49); t.push_back(j + 38); } else if (j < 30) { t.push_back(50); t.push_back(j + 28); } else { t.push_back(''3''); t.push_back(''0''); } temp.push_back(t); } else if (j == 0) { string t; if (i < 10) { t.push_back(48); t.push_back(i + 48); } else if (i < 20) { t.push_back(49); t.push_back(i + 38); } else if (i < 30) { t.push_back(50); t.push_back(i + 28); } else { t.push_back(''3''); t.push_back(''0''); } temp.push_back(t); } else temp.push_back(" #"); } showMapArray.push_back(temp); } } //判断自身格子上的数字为多少 string Map::aroudMineNum(const vector<vector<string>>& map, const int& i, const int& j) const { int count = 0; string ans; for (int x = i - 1; x <= i + 1; ++x) { for (int y = j - 1; y <= j + 1; ++y) { if (map[x][y] == "*") { ++count; } } } ans.push_back(48); ans.push_back(count + 48); return ans; } //按照地图数组显示画面 void Map::showMap() { int sideLength = showMapArray.size(); for (int i = 0; i < sideLength; ++i) { for (int j = 0; j < sideLength; ++j) { cout << showMapArray[i][j] << " "; } cout << endl; } } int Map::dateUpMap(const int& x, const int& y) { //判断xy的值只能在0-30之间difficult*10 if (x < 1 || x >= (difficult * 10) || y < 0 || y >= (difficult * 10)) return -1; //判断坐标是否已经被翻开,若被翻开,则输入非法,返回-1 if (showMapArray[x][y] != " #") return -1; //如果该点有雷,则把该点的雷翻出来,显示游戏失败 if (map[x][y] == "*") { showMapArray[x][y] = " *"; return 0; } //如果该点的数字大于0,则只把单一数字翻出来 else if (map[x][y] != "00") { string temp; temp.append(map[x][y]); showMapArray[x][y] = temp; --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利! } //如果该点的数字为0,则把附近为0的点全部翻出来,直到翻出数字为止 else { if (showMapArray[x][y] != " Q") { --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利! showMapArray[x][y] = "00"; } if (showMapArray[x][y] == " Q" && map[x][y] == "*") { showMapArray[x][y] = " *"; return -1; } for (int i = x - 1; i <= x + 1; ++i) { for (int j = y - 1; j <= y + 1; ++j) { if (!(i == x && j == y) && i > 0 && i < (difficult * 10) && j > 0 && j < (difficult * 10)) { dateUpMap(i, j); } } } return 1; } } int Map::flag(const int& x, const int& y) { if (showMapArray[x][y] != " #") return -1; else { --mapCount;//格子数减少统计,当格子数为0时判断游戏胜利! showMapArray[x][y] = " Q"; } return 0; } int Map::cancelFlag(const int& x, const int& y) { if (showMapArray[x][y] != " Q") return -1; else { ++mapCount;//格子数增加统计,当格子数为0时判断游戏胜利! showMapArray[x][y] = " #"; } return 0; } bool Map::gameOver() { if (mapCount == 0) return true; return false; }
gameManager类
头文件
#pragma once #include<iostream> #include<windows.h> #include"map.h" using namespace std; class GameManager { public: void showMenu();//显示主菜单 int difficultNumber();//选择难度 int stepOnMine(Map * m);//踩雷 int flagMine(Map* m);//插旗子 int cancelFalgMine(Map * m);//取消旗子 };
源文件
#include"gameManager.h" #include"map.h" void GameManager::showMenu() { cout << "***************主菜单***************" << endl; cout << "************1.简单模式**************" << endl; cout << "************2.中等模式**************" << endl; cout << "************3.困难模式**************" << endl; cout << "**********请输入你的选择************" << endl; } int GameManager::difficultNumber() { int diff = 0; while (diff != 1 && diff != 2 && diff != 3) { this->showMenu(); cin >> diff; } return diff; } int GameManager::stepOnMine(Map* m) { int x, y; cout << "请输入你想排雷的坐标:" << endl; cout << "x:" << endl; cin >> x; cout << "y:" << endl; cin >> y; int result = m->dateUpMap(x, y); system("cls"); if (result == -1) { cout << "您的输入有误,请重新输入!" << endl; } else if (result == 0) { cout << "你踩到雷啦!" << endl; Sleep(300); cout << "游戏即将结束!" << endl; Sleep(300); cout << "5!" << endl; Sleep(300); cout << "4!" << endl; Sleep(300); cout << "3!" << endl; Sleep(300); cout << "2!" << endl; Sleep(300); cout << "1!" << endl; m->showMap(); system("pause"); return 1; } return 0; } int GameManager::flagMine(Map* m) { //插旗子 int x, y; cout << "请输入你想插旗子的坐标:" << endl; cout << "x:" << endl; cin >> x; cout << "y:" << endl; cin >> y; int result = m->flag(x, y); system("cls"); if (result == -1) { cout << "此处不能插旗子!" << endl; } else cout << "插旗子成功!" << endl; return 0; } int GameManager::cancelFalgMine(Map* m) { int x, y; cout << "请输入你想取消旗子的坐标:" << endl; cout << "x:" << endl; cin >> x; cout << "y:" << endl; cin >> y; int result = m->cancelFlag(x, y); system("cls"); if (result == -1) { cout << "此处没有旗子可以取消!" << endl; } else { cout << "取消旗子成功!" << endl; } return 0; }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
- C/C++ 中实现让控制台暂停的方法
- C++控制台实现简单人机对弈井字棋
- C++实现控制台版扫雷程序
- C++控制台版扫雷游戏
- C++实现扫雷小游戏(控制台)
- C/C++ 控制台等待指令解析
我们今天的关于js实现经典扫雷游戏和js实现经典扫雷游戏的方法的分享就到这里,谢谢您的阅读,如果想了解更多关于C#实现扫雷游戏、C++实现扫雷游戏示例讲解、C++实现简易版扫雷游戏、C++控制台实现扫雷游戏的相关信息,可以在本站进行搜索。
本文标签: