1. 效果展示
(只展示一部分哈)
帮助规则
2. 游戏设计
2.1. 界面设计
首先,见到华丽的界面先不要慌,哈哈哈哈,背景知识个图片而已,无伤大雅。
当然游戏帮助也是背景图片,不过字也是图片的一部分
之后就是给他加一个菜单栏了,简单加一个开始游戏与退出就好
之后是创建16个PictureBox用于显示16个小图片
再有就是三个lable,用于显示游戏过程中的信息
2.2. 逻辑设计
写逻辑之前我们要先建立游戏要用到的各种变量
// 一维数组,与窗体上的每个图片框对应,存放每个图片框对应的图片索引 int[] pictureIds; int firstIndex; // 记录点击的第一个图片框 int secondIndex; // 记录点击的匹配的图片框 int firstPictureId; // 已经点中的第一个图片框中显示的图片索引 int secondPictureId; // 已经点中的匹配的图片框中显示的图片索引 int count; // 计数,记录点击了几个图片 int gameState; // 游戏状态:0-进行中,1-新游戏,-1-未开始 int gameTime; // 游戏时间 int matchNum; // 配成对的数量 int record; // 最高记录
2.2.1. 游戏初始化
首先我们要先对一维数组进行重新实例化,再把游戏状态改为未开始(值为-1),最高记录设置为0就OK啦。
功能代码如下:
this.pictureIds = new int[16]; // 创建一维数组 gameState = -1; // 游戏状态为未开始 record = 0; // 没有最高记录
2.2.2. 开始游戏
首先是设置各个变量的初始状态,这里不一一叙述,再将每张图片随机放到两个box里就行啦
// 随机指定每个图片框显示的动物图片 for (int i = 1; i <= 8; i++) { // 每张图片都放在两个图片框中 PutIntoBox(i); PutIntoBox(i); }
PutIntoBox是自定义随机图片位置函数
// 将指定索引的图片随机放在一个图片框中,记录在一维数组中 private void PutIntoBox(int pictureIndex) { Random r = new Random(); int boxId = r.Next(16); // 随机找到一个图片框 if (this.pictureIds[boxId] != -1) // 已经有图片了 { // 找到一个还没有图片的图片框 while (this.pictureIds[boxId] != -1) { boxId = r.Next(16); // 随机找到一个图片框 } } this.pictureIds[boxId] = pictureIndex; // 指定这个图片框对应的图片 }
之后别忘了开启计时器
// 启动计时器 tmrShow.Start();
2.2.3. 玩游戏
图片框单击事件
首先,如果游戏不在进行中,则不能点击图片框
// if (gameState != 0) { return; }
如果在游戏中,就可以判断点击的是第一张图片还是第二张了:
- 点击的是第一张图片:保存当前图片的相关参数
- 点击的是第二张图片:保存第二张图片的相关参数,并且调用判断函数进行判断是否匹配。
if (count == 1) // 点击的是第一张图片 { this.firstIndex = newIndex; this.firstPictureId = newPictureId; ((PictureBox)sender).Image = ilPictures.Images[newPictureId]; tmrShow.Start(); } else if (count == 2) // 点击了两张图片 { this.secondIndex = newIndex; this.secondPictureId = newPictureId; ((PictureBox)sender).Image = ilPictures.Images[newPictureId]; tmrShow.Stop(); // 将控制3秒钟显示的定时器停止 tmrMatch.Start(); // 启动延时0.5s计时器,并判断是否匹配 }
2.2.3.1. 判断
判断需要判断两个:
- 是否配对成功进行图片消除
- 检查是否要停止游戏
而且顺序不能调换,要先判断是否能消除,因为当最后两个图片消除完的时候就是游戏结束的时候。
// 是否配对成功进行图片消除 if (this.firstIndex != this.secondIndex && this.firstPictureId == this.secondPictureId) { // 将图片框置为不可见 SetInvisible(this.firstIndex); SetInvisible(this.secondIndex); this.matchNum++; } ResetState(); // 重新开始配对 HidePictures(); // 检查是否要停止游戏 if (this.matchNum == 8) { tmrGame.Stop(); string message = string.Format("配对完成,用时{0}秒,继续努力哦!",this.gameTime); MessageBox.Show(message, "游戏结束", MessageBoxButtons.OK, MessageBoxIcon.Information); if (this.gameTime < this.record || this.record ==0) { lblRecord.Text = this.gameTime.ToString() + "秒"; } this.gameState = -1; // 游戏变为未开始状态 }
2.2.4. 退出
DialogResult result = MessageBox.Show("确实要退出吗?","提示",MessageBoxButtons.YesNo,MessageBoxIcon.Warning); if (result == DialogResult.Yes) { Application.Exit(); }
3. 代码实现
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; namespace MatchBox { public partial class BoxesForm : Form { // 一维数组,与窗体上的每个图片框对应,存放每个图片框对应的图片索引 int[] pictureIds; int firstIndex; // 记录点击的第一个图片框 int secondIndex; // 记录点击的匹配的图片框 int firstPictureId; // 已经点中的第一个图片框中显示的图片索引 int secondPictureId; // 已经点中的匹配的图片框中显示的图片索引 int count; // 计数,记录点击了几个图片 int gameState; // 游戏状态:0-进行中,1-新游戏,-1-未开始 int gameTime; // 游戏时间 int matchNum; // 配成对的数量 int record; // 最高记录 public BoxesForm() { InitializeComponent(); } // 窗体加载时,每个picturebox关联到一个动物图片 private void BoxesForm_Load(object sender, EventArgs e) { this.pictureIds = new int[16]; // 创建一维数组 gameState = -1; // 游戏状态为未开始 record = 0; // 没有最高记录 } // 开始游戏 private void StartGame() { gameState = 1; // 标志为新游戏 this.gameTime = 0; // 游戏时间 this.matchNum = 0; // 配对的数量 // 设置各个变量的初始状态 ResetState(); // 将计时器都停止 tmrGame.Stop(); tmrShow.Stop(); tmrMatch.Stop(); lblCostTime.Text = "0秒"; // 将记录图片框显示的图片的数组都置为-1 for (int i = 0; i < this.pictureIds.Length; i++) { this.pictureIds[i] = -1; } // 随机指定每个图片框显示的动物图片 for (int i = 1; i <= 8; i++) { // 每张图片都放在两个图片框中 PutIntoBox(i); PutIntoBox(i); } // 显示所有图片 foreach (Control item in this.Controls) { if (item is PictureBox) { int index = Convert.ToInt32(((PictureBox)item).Tag); int pictureIndex = this.pictureIds[index]; ((PictureBox)item).Visible = true; ((PictureBox)item).Image = ilPictures.Images[pictureIndex]; } } // 启动计时器 tmrShow.Start(); } // 将指定索引的图片随机放在一个图片框中,记录在一维数组中 private void PutIntoBox(int pictureIndex) { Random r = new Random(); int boxId = r.Next(16); // 随机找到一个图片框 if (this.pictureIds[boxId] != -1) // 已经有图片了 { // 找到一个还没有图片的图片框 while (this.pictureIds[boxId] != -1) { boxId = r.Next(16); // 随机找到一个图片框 } } this.pictureIds[boxId] = pictureIndex; // 指定这个图片框对应的图片 } // 图片框单击事件 private void picBox_Click(object sender, EventArgs e) { // 如果游戏不在进行中,则不能点击图片框 if (gameState != 0) { return; } int newIndex = Convert.ToInt32(((PictureBox)sender).Tag); // 当前点中的图片框在数组中的索引 int newPictureId = this.pictureIds[newIndex]; // 当前点中的图片框显示的图片的索引 count++; // 计数 if (count == 1) // 点击的是第一张图片 { this.firstIndex = newIndex; this.firstPictureId = newPictureId; ((PictureBox)sender).Image = ilPictures.Images[newPictureId]; tmrShow.Start(); } else if (count == 2) // 点击了两张图片 { this.secondIndex = newIndex; this.secondPictureId = newPictureId; ((PictureBox)sender).Image = ilPictures.Images[newPictureId]; tmrShow.Stop(); // 将控制3秒钟显示的定时器停止 tmrMatch.Start(); // 启动延时0.5s计时器,并判断是否匹配 } } // 恢复状态 private void ResetState() { this.firstIndex = -1; this.secondIndex = -1; this.firstPictureId = -1; this.secondPictureId = -1; this.count = 0; } // 控制图片最多显示3秒 private void tmrShow_Tick(object sender, EventArgs e) { tmrShow.Stop(); // 停止计时器 if (gameState == 1) // 如果是新游戏 { gameState = 0; // 将游戏状态变为进行中 tmrGame.Start(); // 开始计时 } ResetState(); // 清除记录 HidePictures(); // 隐藏图片 } // 隐藏所有图片 private void HidePictures() { // 将所有图片都翻过去 foreach (Control item in this.Controls) { if (item is PictureBox) { ((PictureBox)item).Image = ilPictures.Images[0]; } } } // 将指定索引的图片框置为不可见 private void SetInvisible(int index) { foreach (Control item in this.Controls) { if (item is PictureBox) { if (Convert.ToInt32(((PictureBox)item).Tag) == index) { ((PictureBox)item).Visible = false; } } } } // 显示0.5秒 private void tmrMatch_Tick(object sender, EventArgs e) { tmrMatch.Stop(); if (this.firstIndex != this.secondIndex && this.firstPictureId == this.secondPictureId) { // 将图片框置为不可见 SetInvisible(this.firstIndex); SetInvisible(this.secondIndex); this.matchNum++; } ResetState(); // 重新开始配对 HidePictures(); // 检查是否要停止游戏 if (this.matchNum == 8) { tmrGame.Stop(); string message = string.Format("配对完成,用时{0}秒,继续努力哦!",this.gameTime); MessageBox.Show(message, "游戏结束", MessageBoxButtons.OK, MessageBoxIcon.Information); if (this.gameTime < this.record || this.record ==0) { lblRecord.Text = this.gameTime.ToString() + "秒"; } this.gameState = -1; // 游戏变为未开始状态 } } // 开始新游戏 private void tsmiNewGame_Click(object sender, EventArgs e) { StartGame(); } // 退出 private void tsmiExit_Click(object sender, EventArgs e) { DialogResult result = MessageBox.Show("确实要退出吗?","提示",MessageBoxButtons.YesNo,MessageBoxIcon.Warning); if (result == DialogResult.Yes) { Application.Exit(); } } // 游戏计时 private void tmrGame_Tick(object sender, EventArgs e) { this.gameTime++; // 将时间增加1s lblCostTime.Text = gameTime.ToString() + "秒"; } private void tsmiRule_Click(object sender, EventArgs e) { GameRuleForm ruleForm = new GameRuleForm(); ruleForm.ShowDialog(); } } }
4. 资源链接
CSDN下载:https://mp-new.csdn.net/mp_download/manage/download/UpDetailed
百度网盘:
链接:https://pan.baidu.com/s/1gxe1EVFLz5Lki2kVUyjHlA
提取码:y2j1