技术经验解读:【转】详细解析用C#写的小游戏《彩色连珠》(附源代码)

简介: 技术经验解读:【转】详细解析用C#写的小游戏《彩色连珠》(附源代码)

不久前写的一个小游戏,最近拿出来稍微修改完善了一下,因为自己现在“不得已”改行学Java了,这个小游戏就当是自己与C#的告别吧,不过以后如果自己有什么想写的小程序,C#仍然是首先考虑的语言了,因为Java做GUI太蛋疼了。


首先声明本人菜鸟一个,快毕业的学生党,这篇文章完全是记录自己的一些点滴吧。


游戏的规则很简单,大概是:10X10的方格,游戏开始时随机出5个球,颜色也是随机的,用户点击球让其移动,5个(或更多)相同颜色的球在一起就可以消掉,如果没有可以消的,就又随机出3个球,直到棋盘满为止。


游戏界面如下:


具体思路如下:


左边的是一个panel面板,用来当做棋盘,启动时把方格线画好,这些球都是一些事先弄好的图片文件(考虑过用图形学的方法代码生成,但是感觉效率太低,最重要的是不好看,所以还是放弃了),通过g.DrawImage()的方法画在面板上,清空的话就是用背景色填充,点击某个球会动态的变化大小,点击空白处会将之前点过的球动态的移动到那里,球每次移动时需要查找能够到达指定位置的最短路径,所以会用到《人工智能》课上用过的查找算法查找最短路径,出子就是用Random随机函数随机的在某个位置画某种颜色的球,每次移动球后都要判断在横、竖、左斜、右斜四个方向上是否有可以消的球,消完球后随机出3个球,出球的同时要判断棋盘是否满。


简单的实现了保存成绩的功能(以及对成绩进行加密),功能做的很简陋,其实还可以添加一些声音的,限于时间就没弄了,有兴趣的可以尝试一下。


好了,也不多写什么了,因为我觉得代码里面的注释已经够详细了,更多的问题还是看代码里面的注释吧。


下面把几个比较重要的地方单独写出来。


首先最重要的是画图要怎么画,也就是采用什么函数来画。


C#画图最常见的一般有3种方式:


一种是,这种方法优点是窗体最小化或者被其它窗体遮挡后画的图不会消失,缺点是每次画完图都要刷新整个区域,所以有可能闪屏很严重:


Bitmap bit = new Bitmap(panel游戏区.Width,panel游戏区.Height);//实例化一个Bitmap


Graphics g = Graphics.FromImage(bit);


g.DrawImage(Image.FromFile("picturePath"),left,top,width,height);//画图


panel游戏区.BackgroundImage = bit;


还有一种是用控件的CreateGraphics()方法创建一个Graphic对象,优点很明显,就是非常方便,不用每次都要刷新,所以一般不会出现闪屏现象,但是当窗体最小化还原或者被其它窗体遮挡后就一片空白了,到网上查过一些资料,好像是因为这种画图方式数据都是保存在缓存中的,窗体只要最小化就会触发paint事件重绘,系统自带的控件重绘的代码都写好了,但是我们自己的这个画图区域因为没有写重绘事件,所以还原后一片空白,解决办法就是在paint事件里手动对空白区域进行重绘,本游戏采用的就是这种方法:


Graphics g = panel游戏区.CreateGraphics();


g.DrawImage(Image.FromFile("picturePath"), left, top, width, height);


还有一种方法是写在控件的Paint事件里,缺点很明显,都是不方便,很多代码我们没办法写在这里,比如鼠标事件发生的一些画图代码。


Graphics g = e.Graphics;


g.DrawImage(Image.FromFile("picturePath"), left, top, width, height);


首先是画方格线,比较简单:


private void drawLine()//画方格线的函数


{


Graphics g = panel游戏区.CreateGraphics();


for (int i = 0; i < m; i++)


{


g.DrawLine(new Pen(Color.Black), 0, panel游戏区.Height / m i, panel游戏区.Width, panel游戏区.Height / m i);


g.DrawLine(new Pen(Color.Black), panel游戏区.Width / m i, 0, panel游戏区.Width / m i, panel游戏区.Height);


}


}


其次是在指定行和列处画指定颜色的球,因为后面有些地方有需要,重载了3次,这里只列出其中一个,其它类似。这里顺便讲一下关于资源文件的使用,因为把所以图片放在文件夹里不方便,所以我还是想把所以图片放到资源文件里面去,但是C#里根据资源文件名来查找资源文件还确实不是那么容易,找了很久的资料才解决,具体的就是ResourceManager里面的一个参数不好写,很容易写错,具体事项看下面代码和注释吧:



///


/// 画球的函数


///


///


行数


///


列数


///


要画的球的颜色


///


指定球比方格要小的像素个数


private void drawBall(int i, int j, Color color,int dx)


{


//关于图片:如果直接将这些不同颜色的球的图片放在程序根目录文件夹来操作比较简单,


//但是缺点就是老是要跟一个文件夹,不方便,所以将所有图片放入程序的资源文件


//至于怎样调用程序的资源文件,查找了很多资料后终于得到解决,具体方法看下面的代码。


Graphics g = panel游戏区.CreateGraphics();


g.InterpolationMode = InterpolationMode.HighQualityBicubic;//高质量显示图片


int x = panel游戏区.Width / m, y = panel游戏区.Height / m;//x,y分别为单个方块宽和高


string temp = color.ToString().Substring(7).Replace("】", "");//color的颜色值转换为字符串后形如:color【Red】,本句代码执行后的结果为Red


//string picturePath = Application.StartupPath + @"\球\" + temp + ".png";//到程序目录中查找指定颜色球的路径,如:C:\Documents and Settings\Administrator\桌面\刘显安\彩色连珠\bin\Debug\球\Red.png


//代码效果参考:http://www.lyjsj.net.cn/wz/art_22850.html

System.Resources.ResourceManager manager = new System.Resources.ResourceManager("彩色连珠.Properties.Resources", System.Reflection.Assembly.GetExecutingAssembly());

//上面一句话是实例化一个ResourceManager,这里一定要注意baseName的写法,为:命名空间+文件夹名+资源文件名(不带后缀名),不知道怎么写的可以到“Resources.Designer.cs”这个文件里去找


//用这个写法的目的是为了方便根据资源文件名来查找,如果不需要查找的画则比较简单,如下:


//首先添加以下引用:using 彩色连珠.Properties;然后直接写:Resources.Red就可以获取资源文件了。


g.DrawImage((Bitmap)manager.GetObject(temp), x j + dx, y i + dx, x - dx - dx, y - dx - dx);//将图片画在游戏区


ball【i, j】 = color;//同时更新ball数组


//g.FillEllipse(new SolidBrush(color),xj+5,yi+5,x-10,y-10);//如果是直接用系统函数画圆的画就用这句话


}


清空某个方格的代码:


///


/// 用背景色填充指定方格,以达到清除的目的


///


///



///



private void clearBall(int i,int j)


{


Graphics g = panel游戏区.CreateGraphics();


int x = panel游戏区.Width / m, y = panel游戏区.Height / m;


g.FillRectangle(new SolidBrush(panel游戏区.BackColor), x j + 2, y i + 2, x - 4, y - 4);


ball【i, j】= panel游戏区.BackColor;


}


随机出球的函数:


///


/// 游戏开始时随机出球,位置随机,颜色也随机(用于没有下一组提示的时候)


///


private void drawBallRandom()


{


if (!checkOver())


{


Random random = new Random();


bool flag = true;


while (flag)


{


int i = random.Next(0, 10);


int j = random.Next(0, 10);


if (ball【i, j】 == panel游戏区.BackColor)


{


flag = false;


int c = random.Next(0, colorNum);


//MessageBox.Show(i + "," + j + ":" + color【c】.ToString());


drawBall(i, j, color【c】);


checkSuccess(i, j);//出子后要判断是否有可以消的球


}


}


}


}


产生下一组随机球:


///


/// 产生下一组随机球


///


private void makeNextColor()


{


Graphics g = pictureBox下一组.CreateGraphics();


g.Clear(pictureBox下一组.BackColor);


Random random = new Random();


for (int i = 0; i < 3; i++)


{


nextColor【i】 = random.Next(0,colorNum);


drawBall(i,nextColor【i】);


}


}


panel的paint事件,作用在下面的注释已经写明了,有些函数是在后面定义的,这里暂时还没写出来:


//游戏区的重绘事件,这个事件的作用主要有2个:一个是让游戏第一次运行时画方格线


//以及随机出5个子(这些代码不能放在Form_Loaded事件里,因为窗体第一次生成会触发


//Paint事件进而覆盖原图),第二个作用是解决当窗体最小化或改变大小时绘图区一片空


//白的问题,解决的思路就是方格线和球全部重绘。


//用“Bitmap bit= new Bitmap(x,y);Graphics g=Graphics.FromImage(bit);”的方法


//不会出现最小化变空白的现象,但每次画完图后都必须刷新,因此闪屏现象严重。


private void panel游戏区_Paint(object sender, PaintEventArgs e)


{


drawLine();//画方格线


for (int i = 0; i < m; i++)


for (int j = 0; j < m; j++)


if (ball【i, j】 != panel游戏区.BackColor)


{


drawBall(i,j,ball【i,j】); //如果该位置的颜色不是背景色(即没有球)则按照指定颜色画球


}


makeNextColor();//防止窗口最小化后还原一片空白


if (isFirstRun)//如果是第一次运行


{


for (int i = 0; i < 5; i++)


drawBallRandom();//随机出5个球


makeNextColor();


isFirstRun = false;


}


}


鼠标的单击事件,游戏的主要驱动都来自这个事件:


private void panel游戏区_MouseClick(object sender, MouseEventArgs e)//游戏区的鼠标单击事件


{


timer缩放.Enabled = false;//结束球的缩放


int x = panel游戏区.Width / m, y = panel游戏区.Height / m;


if (ball【e.Y / y, e.X / x】 != panel游戏区.BackColor)//如果单击的是球


{


dx = 5;//让dx恢复到默认值


if(move_i>=0)


drawBall(move_i, move_j, ball【move_i, move_j】, dx);


//在新的球缩放时将上次点的球(如果有)重置为默认大小(因为球动态变换大


//小,所以停止缩放时可能不是默认大小,这句话是重新画一个默认大小的球)


move_i = e.Y / y;


move_j = e.X / x;


timer缩放.Enabled = true;//让单击过的球开始动态变换大小


}


else if (move_i >= 0 && move_j >= 0)//如果单击的是空白处,且有一个即将移动的球


{


bool【,】 isHaveBall = new bool【m, m】;//保存棋盘上每个位置是否有球的信息


for (int i = 0; i < m; i++)


for (int j = 0; j < m; j++)


{


if (ball【i, j】 == panel游戏区.BackColor)


isHaveBall【i, j】 = false;


else


isHaveBall【i, j】 = true;


}


int end_i = e.Y / y, end_j = e.X / x;//目标行与列


Search s = new Search(isHaveBall, m, move_i, move_j, end_i, end_j);//实例化一个查找类


path = s.start();//开始查找


if (path【0】【0】 != 0)//如果查找成功


{


path_idx = 2;//path数组第一组数据是长度,第二组数据是起点,所以要从第三组数据开始


timer移动.Enabled = true;


//string t = ""; //下面注释的代码用来查看文本形式的路径信息,仅供程序员调试看,玩家不需要管


//for (int i = 1; i <= path【0】【0】; i++)


//{


// t += path【i】【0】 + "," + path【i】【1】 + " ";


//}


// MessageBox.Show(t);


}


}


}


检查是否有5个(或更多)颜色相同的球在一起,并计算分数,5个子10分,6个子20分,以此类推:


///


/// 检查是否有5个颜色相同的球连在一起


///


///


起始查找位置的行


///


起始查找位置的列,为什么不用字母“l”呢?因为和数字“1”长得太像了!(汗)


/// 检查的结果


private bool checkSuccess(int h,int lie)


{


bool f = false;


int【】【】 res = new <span style="color: rgba(0, 0,

相关文章
|
4月前
|
存储 算法 安全
如何控制上网行为——基于 C# 实现布隆过滤器算法的上网行为管控策略研究与实践解析
在数字化办公生态系统中,企业对员工网络行为的精细化管理已成为保障网络安全、提升组织效能的核心命题。如何在有效防范恶意网站访问、数据泄露风险的同时,避免过度管控对正常业务运作的负面影响,构成了企业网络安全领域的重要研究方向。在此背景下,数据结构与算法作为底层技术支撑,其重要性愈发凸显。本文将以布隆过滤器算法为研究对象,基于 C# 编程语言开展理论分析与工程实践,系统探讨该算法在企业上网行为管理中的应用范式。
139 8
|
4月前
|
存储 监控 算法
解析公司屏幕监控软件中 C# 字典算法的数据管理效能与优化策略
数字化办公的时代背景下,企业为维护信息安全并提升管理效能,公司屏幕监控软件的应用日益普及。此软件犹如企业网络的 “数字卫士”,持续记录员工电脑屏幕的操作动态。然而,伴随数据量的持续增长,如何高效管理这些监控数据成为关键议题。C# 中的字典(Dictionary)数据结构,以其独特的键值对存储模式和高效的操作性能,为公司屏幕监控软件的数据管理提供了有力支持。下文将深入探究其原理与应用。
98 4
|
5月前
|
机器学习/深度学习 监控 算法
员工上网行为监控软件中基于滑动窗口的C#流量统计算法解析​
在数字化办公环境中,员工上网行为监控软件需要高效处理海量网络请求数据,同时实时识别异常行为(如高频访问非工作网站)。传统的时间序列统计方法因计算复杂度过高,难以满足低延迟需求。本文将介绍一种基于滑动窗口的C#统计算法,通过动态时间窗口管理,实现高效的行为模式分析与流量计数。
137 2
|
5月前
|
人工智能 运维 算法
基于 C# 深度优先搜索算法的局域网集中管理软件技术剖析
现代化办公环境中,局域网集中管理软件是保障企业网络高效运行、实现资源合理分配以及强化信息安全管控的核心工具。此类软件需应对复杂的网络拓扑结构、海量的设备信息及多样化的用户操作,而数据结构与算法正是支撑其强大功能的基石。本文将深入剖析深度优先搜索(Depth-First Search,DFS)算法,并结合 C# 语言特性,详细阐述其在局域网集中管理软件中的应用与实现。
126 3
|
6月前
|
传感器 人工智能 物联网
穿戴科技新风尚:智能服装设计与技术全解析
穿戴科技新风尚:智能服装设计与技术全解析
542 85
|
6月前
|
人工智能 API 语音技术
HarmonyOS Next~鸿蒙AI功能开发:Core Speech Kit与Core Vision Kit的技术解析与实践
本文深入解析鸿蒙操作系统(HarmonyOS)中的Core Speech Kit与Core Vision Kit,探讨其在AI功能开发中的核心能力与实践方法。Core Speech Kit聚焦语音交互,提供语音识别、合成等功能,支持多场景应用;Core Vision Kit专注视觉处理,涵盖人脸检测、OCR等技术。文章还分析了两者的协同应用及生态发展趋势,展望未来AI技术与鸿蒙系统结合带来的智能交互新阶段。
384 31
|
6月前
|
编解码 监控 网络协议
RTSP协议规范与SmartMediaKit播放器技术解析
RTSP协议是实时流媒体传输的重要规范,大牛直播SDK的rtsp播放器基于此构建,具备跨平台支持、超低延迟(100-300ms)、多实例播放、高效资源利用、音视频同步等优势。它广泛应用于安防监控、远程教学等领域,提供实时录像、快照等功能,优化网络传输与解码效率,并通过事件回调机制保障稳定性。作为高性能解决方案,它推动了实时流媒体技术的发展。
349 5
|
6月前
|
数据采集 机器学习/深度学习 存储
可穿戴设备如何重塑医疗健康:技术解析与应用实战
可穿戴设备如何重塑医疗健康:技术解析与应用实战
234 4
|
6月前
|
机器学习/深度学习 人工智能 自然语言处理
AI技术如何重塑客服系统?解析合力亿捷AI智能客服系统实践案例
本文探讨了人工智能技术在客服系统中的应用,涵盖技术架构、关键技术和优化策略。通过感知层、认知层、决策层和执行层的协同工作,结合自然语言处理、知识库构建和多模态交互技术,合力亿捷客服系统实现了智能化服务。文章还提出了用户体验优化、服务质量提升和系统性能改进的方法,并展望了未来发展方向,强调其在客户服务领域的核心价值与潜力。
326 6
|
6月前
|
监控 算法 安全
基于 C# 的内网行为管理软件入侵检测算法解析
当下数字化办公环境中,内网行为管理软件已成为企业维护网络安全、提高办公效率的关键工具。它宛如一位恪尽职守的网络守护者,持续监控内网中的各类活动,以确保数据安全及网络稳定。在其诸多功能实现的背后,先进的数据结构与算法发挥着至关重要的作用。本文将深入探究一种应用于内网行为管理软件的 C# 算法 —— 基于二叉搜索树的入侵检测算法,并借助具体代码例程予以解析。
108 4

热门文章

最新文章

推荐镜像

更多
  • DNS