辽宁科技大学课程设计说明书设计题目:基于C#的贪吃蛇游戏学院、系:装备制造学院专业班级:计算机科学与技术学生姓名:***指导教师:**成绩:2015年12月12日目录一、概述 (1)1、用C#实现该设计的方法 (1)2、贪吃蛇游戏说明 (1)二、实验目的及设计要求 (1)1、实验目的 (1)2、实验要求 (2)三、课程设计具体实现 (2)1、概要设计 (2)1.1、设计思想 (2)1.2、主模块实现 (2)1.3、主函数流程图 (4)2、详细设计 (5)2.1、设计思想 (5)2.2、具体模块实现: (5)四、调试过程及运行结果 (10)1、调试过程 (10)2、实验结果 (11)五、实验心得 (12)六、参考资料 (13)七、附录:源代码 (13)一、概述1、用C#实现该设计的方法首先应该了解设计要求,然后按照功能设计出实际模块,每个模块都要完成特定的功能,要实现模块间的高内聚,低耦合。
设计模块是一个相当重要的环节,模块的数量不宜太多,也不宜太少,要是每个模块都能比较简单的转换成流程图。
模块设计完成后,就该给每个模块绘制流程图。
流程图要尽可能的简单且容易理解,多使用中文,补一些过长的代码,增加理解难度。
此外,流程图应容易转换成代码。
根据流程图编写好代码后在WindowsXP操作系统,2008开发环境下进行运行测试,检查错误,最终设计出可行的程序。
2、贪吃蛇游戏说明游戏操作要尽可能的简单,界面要尽可能的美观。
编写程序实现贪吃蛇游戏,贪吃蛇游戏是一个深受人们喜欢的游戏:一条蛇在密闭的围墙内,在围墙内随机出现一个食物,通过键盘上的四个光标键控制蛇向上下左右四个方向移动,蛇头撞到食物,则表示食物被吃掉,这时蛇的身体长一节,同时计10分;接着又出现食物,等待被蛇吃掉,如果蛇在移动过程中,撞到墙壁、障碍物或身体交叉(蛇头撞到自己的身体),则游戏结束。
游戏结束时输出相应得分。
具体要求有以下几点:(1)对系统进行功能模块分析、控制模块分析正确,符合课题要求,实现相应功能;可以加以其他功能或修饰,使程序更加完善、合理;(2)系统设计要实用,采用模块化程序设计方法,编程简练、可用,功能全面;(3)说明书、流程图要清楚;二、实验目的及设计要求1、实验目的.NET课程设计是教学实践环节中一项重要内容,进行此课程设计旨在掌握基础知识的基础上,进一步加深对VC#.NET技术的理解和掌握;提高和加强学生的计算机应用及软件开发能力,使学生具备初级程序员的基本素质;培养学生独立分析问题、解决问题、查阅资料以及自学能力,以适应信息管理行业日新1月异的发展形势;本次课程设计是以学生独立思考解决问题为主,教师指导为辅,结合上机操作,完成指定的任务,做出设计报告。
2、实验要求利用Microsoft Visual Studio 2008 平台设计制作一个贪吃蛇小游戏,要求如下:(1)能够记录游戏成绩(计分按照每吃一块食物增加20累计)(2)可以暂停/继续游戏(通过按钮实现)(3)蛇的身体能够随着吃到食物的数量逐渐变长(4)可以自己添加障碍物,要求设计成红色墙壁(5)积分每增加50分要求蛇相应的加快速度(6)要求在游戏的过程中添加背景音乐和随机炸弹三、课程设计具体实现1、概要设计1.1、设计思想程序关键在于表示蛇的图形及蛇的移动。
用一个小矩形快表示蛇的一节身体,身体每长一节,增加一个矩形块,蛇头(绿色)用三节表示。
移动时必须从蛇头开始,所以蛇不可以向相反的方向移动,如果不按任意键,蛇自行在当前方向右前移,但按下有效方向键后,蛇头朝该方向移动,一步移动一节身体,所以按下有效方向键后,先确定蛇头的位置,而后蛇的身体随蛇头移动,图形的实现是从蛇头新位置开始画出蛇,这时,由于未清屏的原因,原来的蛇的位置和新的位置差一个单位,所以看起来蛇多一节身体,所以将蛇的最后节用背景色覆盖。
食物的出现与消失也是画矩形块和覆盖矩形块。
为了便于理解,定义两个结构体:食物与蛇,同时还定义了一个随意的墙。
然后利用图形驱动,,制作美观的游戏界面,通过随机函数产生随机的食物,控制游戏过程食物的出现。
定义键盘操作控制游戏过程蛇的移动方向,画出边界,并判断游戏是否结束,统计游戏过程中蛇吃的食物数量,计算并输出游戏成绩。
1.2、主模块实现1.snake的设计模块22. Form 的设计模块31.3、主函数流程图是开始游戏蛇开始移动根据键盘控制蛇移动方向判断蛇头和食物的坐标是否重合随机生成下一个食物判断蛇头和自身及墙、炸弹是否重合游戏结束否否是是暂停是否继续否42、详细设计2.1、设计思想首先进入VS2008打开文件新建一个项目,点击windows窗体应用程序,名字设为Snakes 。
进入Form的设计界面,首先我们都知道游戏最基本的功能有开始,暂停,继续,退出,所以首先要先加4个button键来控制游戏,再加一个TextBox文本框来显示成绩。
在窗体中加入Panel来实现贪吃蛇的运动空间,设置有一个游戏的界面运动空间。
之后就要定义一个sakes 类,来实现蛇的一些属性与方法,首先明白这个游戏实现的是贪吃蛇吃食物,所以还需要定义食物,食物被吃后要实现食物的重建。
玩游戏时还需要有控制键的设置,这一模块可以选用Switch语句来实现。
实现基本的功能后要注意怎样的情况会造成蛇的死亡,可以想到的有越界线,咬到自己都会死亡。
随着思想的成熟,觉得只吃食物好像太简单,所以在这个贪吃蛇游戏的基础上又设置了一些障碍,加了几堵墙,还设置了随机的炸弹,这样游戏就更有意思了,加上以前玩俄罗斯方块的一些感觉,还设置了游戏的不断加速的模块。
2.2、具体模块实现:1、snake 属性定义2、Form 属性定义53、创建蛇的模块创建蛇的模块和创建障碍物的思路想法是一致的,都是通过label实现:4、创建食物模块创建食物模块和创建随机炸弹思路是一致的,都是在一定范围内随机出现。
通过坐标点的方法来实现食物,食物是随机出现的,而且一旦被吃掉就会立刻创建新的食物。
而且还需要判断食物出现的地方时是否与墙壁重合。
65、蛇吃食物的模块通过Timer 控件来设置时间,,吃到食物之后身体增长,蛇的身体颜色是三色交替出现,每吃到一个食物积分加10,身体加长对应增长。
而且还要判断是否需要更改蛇的运行速度。
77、是否撞到自己模块当贪吃蛇自己碰到自己的身体时游戏结束8、游戏结束模块9、初始化panel810、初始化Form并添加背景音乐(Kalimba.wav)11、控制蛇的运动方向四、调试过程及运行结果1、调试过程(1)在实现撞障碍物的过程中,刚刚开始的时候墙不能起作用,贪吃蛇总是能穿过障碍物,后来才发现时障碍物的设置范围出现了错误。
经过不停的尝试与计算才算出正确的范围。
(2)在实现固定墙的过程中是通过使用Label来实现的,跟创建贪吃蛇的思想是一样的,但是在运行过程中刚刚开始的时候不出现障碍物,后来在老师的帮助下发现原来少一句话,需要在NowStar()函数中增加障碍物的显示for (int i = 0; i <sk.Wall.Count; i++){ this.panel1.Controls.Add((Label)sk.Wall[i]);}(3)在玩游戏的过程中发现食物会与墙壁还有炸弹重合的情况,然后通过分析原因,这与构造食物时判断食物与身体是否接触的道理是一样的,这里需要加一个循环语句来判断,如果不是墙的话才在这里创造食物。
(4)在创造炸弹的实现过程中,总是在炸弹的右半边任何位置都爆炸,通过一步一步的调试检查是在判断语句时右侧的范围太大,导致有半侧没有炸弹也爆炸。
通过调试找到正确的范围。
2、实验结果(1)游戏运行主界面(2)帮助界面(3)结束界面五、实验心得这次的课设对我来说有很大的收获,我学到了许多课本上没有学到的知识,这次我将将课本上的理论知识充分的转化成了一些实用技能。
通过这次自己制作的软件,丰富了自己的实践技能,扩展课本专业的知识面。
在这次设计的同时,我又从中学到了许多东西。
但由于我对这样的软件开发还只是一个开始,了解的不多,这其中或许还有很多的不足,有些模块做的不是很好,界面的设计及整体的布局还是比较简单。
此外,在这一次的课程设计过程中,我上网查阅了大量的资料,对C#有了更深的理解,对于软件工程这些辅助性的教材也巩固了不少,为我这次的课设提供了很大的帮助,锻炼了我的能力。
更重要的是,它还让我认识到了自己的不足之处,在编程方面,我还是比较欠缺,以后的路任重道远,我需要的事不断地丰富自己,充实自己,这样才能在程序设计方面有所收获。
最后感谢老师在这次课程设计中对我们的悉心教导,通过这次学习,让我们掌握了很多有关C#.NET的应用知识。
六、参考资料[1] 陈俊荣. ASP与网络数据库技术[M]. 北京:中国铁道出版社,2005.[2] 张绣兰. ASP网站建设实录[M]. 北京:北京希望电子出版社. 2008.[3] 李华. DreamWeaver8网页设计程序教程[M]. 北京:清华大学出版社. 2004.[4] 江开耀. 软件工程[M]. 西安:西安电子科技大学出版社.七、附录:源代码snake源代码如下:using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Windows.Forms;using System.Collections;using System.Drawing;using ponentModel;using System.Data;namespace Snake{class snake{public Point food_p;//定义食物的位置private Label food; //定义食物public Label Food //食物属性{get { return food; }set { food = value; }}private ArrayList body = new ArrayList(); //定义食物定义食物链表public ArrayList Body //食物链表属性{get { return body; }set { body = value; }}//定义障碍物上下左右各面墙蛇撞墙即死private ArrayList wall = new ArrayList();public ArrayList Wall{}private ArrayList wall1 = new ArrayList();public ArrayList Wall1{get { return wall1; }set { wall1 = value; }}private ArrayList wall2 = new ArrayList();public ArrayList Wall2{get { return wall2; }set { wall2 = value; }}private ArrayList wall3 = new ArrayList();public ArrayList Wall3{get { return wall3; }set { wall3 = value; }}public void CreateSnake()//使用Label进行创建一个蛇{int left = 20;Label lb;for (int i = 0; i < 2; i++){lb = new Label(); = "label" + i.ToString();lb.BackColor = Color.Green;lb.Width = 10;lb.Height = 10;lb.Top = 0;lb.Left = left;body.Add(lb);left -= 10;}}public void CreateWall()//使用Label进行创建障碍物{int left = 200;Label lb0;for (int i = 0; i < 10; i++ ){lb0 = new Label(); = "label" + i.ToString();lb0.BackColor = Color.Red;lb0.Width = 10;lb0.Top = 50;lb0.Left = left;wall.Add(lb0);left -= 10;}}public void CreateWall1(){int left = 200;Label lb1;for (int i = 0; i < 10; i++){lb1 = new Label(); = "label" + i.ToString();lb1.BackColor = Color.Red;lb1.Width = 10;lb1.Height = 10;lb1.Top = 310;lb1.Left = left;wall1.Add(lb1);left -= 10;}}public void CreateWall2(){int top = 200;Label lb2;for (int i = 0; i < 10; i++){lb2 = new Label(); = "label" + i.ToString();lb2.BackColor = Color.Red;lb2.Width = 10;lb2.Height = 10;lb2.Left = 50;lb2.Top = top;wall2.Add(lb2);top -= 10;}}public void CreateWall3(){int top = 200;Label lb3;for (int i = 0; i < 10; i++){ = "label" + i.ToString();lb3.BackColor = Color.Red;lb3.Width = 10;lb3.Height = 10;lb3.Left = 260;lb3.Top = top;wall3.Add(lb3);top -= 10;}}//创建食物public void CreateFood(){Random rand = new Random();food_p.X = rand.Next(36) * 10;//限定食物物所能出现的横坐标food_p.Y = rand.Next(36) * 10;//限定食物物所能出现的横坐标for (int i = 0; i < body.Count; i++){if (food_p.Y == ((Label)body[i]).Top && food_p.X == ((Label)body[i]).Left){this.CreateFood();break;}}//判断食物和所见障碍物是否重合for (int i = 0; i < wall.Count; i++){if (food_p.Y == ((Label)this.Wall[i]).Top && food_p.X ==((Label)this.Wall[i]).Left){this.CreateFood();}else if (food_p.Y == ((Label)this.Wall1[i]).Top && food_p.X ==((Label)this.Wall1[i]).Left){this.CreateFood();}else if (food_p.X == ((Label)this.Wall2[i]).Left && food_p.Y ==((Label)this.Wall2[i]).Top){this.CreateFood();}else if (food_p.X == ((Label)this.Wall3[i]).Left && food_p.Y ==((Label)this.Wall3[i]).Top){this.CreateFood();}food = new Label();food.Width = 10;food.Height = 10;food.Top = food_p.Y;food.Left = food_p.X;//加载食物图片food.Image = Snake.Properties.Resources.food;}//蛇吃食物通过timer进行速度的设置public Panel EatFood(Panel panel1, Timer timer1, TextBox textBox1, TextBox textBox2) {if (((Label)body[0]).Top == food_p.Y && ((Label)body[0]).Left == food_p.X){panel1 = this.DeFood(panel1);Label lb = new Label();//增加蛇身 = "label" + body.Count.ToString();int i=body.Count%3;if(i==0)lb.BackColor = Color.DimGray;else if(i==1)lb.BackColor = Color.DeepPink;elselb.BackColor = Color.DeepSkyBlue;lb.Width = 10;lb.Height = 10;lb.Top = ((Label)body[body.Count - 1]).Top;lb.Left = ((Label)body[body.Count - 1]).Left;body.Add(lb);textBox1.Text = Convert.ToString(Convert.ToInt32(textBox1.Text) + 10);textBox2.Text = textBox1.Text;if (Convert.ToInt32(textBox2.Text) < Convert.ToInt32(textBox1.Text))textBox2.Text = textBox1.Text;//修改速度if (textBox1.Text == "50")timer1.Interval = 150;else if (textBox1.Text == "100")timer1.Interval = 100;else if (textBox1.Text == "150")timer1.Interval = 80;else if (textBox1.Text == "200")timer1.Interval = 50;else if (textBox1.Text == "250")timer1.Interval = 20;}return panel1;//吃过后销毁再创建食物public Panel DeFood(Panel panel1){panel1.Controls.Remove(food);this.CreateFood();panel1.Controls.Add(food);return panel1;}}}//Form 源代码:using System;using System.Collections.Generic;using ponentModel;using System.Data;using System.Drawing;using System.Linq;using System.Text;using System.Windows.Forms;using System.Collections;using System.Media;namespace Snake{public partial class Form1 : Form{public Form1(){InitializeComponent();}private snake sk = new snake(); //构造一个蛇的对象private int dir = 3; //初始时要运动的方向(向右)private Point bomb_b; //定义炸弹private Label bomb;public void CreatBomb()//创建炸弹{Random rand = new Random();bomb_b.X = rand.Next(20) * 10;bomb_b.Y = rand.Next(20) * 10;bomb = new Label();bomb.Width = 10;bomb.Height = 10;bomb.Top = bomb_b.Y;bomb.Left = bomb_b.X;bomb.Image = Snake.Properties.Resources.b2;//判断随机炸弹是否与随机食物重合{CreatBomb();}}//清除炸弹public Panel DeBomb(Panel panel1){panel1.Controls.Remove(bomb);return panel1;}private int diring = -1; //正在运动的方向private void button1_Click(object sender, EventArgs e) //开始{textBox1.Text = "0";button3.Enabled = true;timer1.Start();panel1 = sk.DeFood(panel1);this.CreatBomb();panel1.Controls.Add(bomb);}private void button2_Click(object sender, EventArgs e) //暂停{timer1.Stop();}private void button3_Click(object sender, EventArgs e) //新游戏{textBox1.Text = "0";timer1.Interval = 200;button3.Enabled = false;panel1.Controls.Clear();sk.Body.Clear();sk.CreateSnake();NowStart();dir = 3;diring = -1;timer1.Stop();}private void NowStart()//初始化{//再panel中添加蛇的身体for (int i = 0; i < sk.Body.Count; i++){this.panel1.Controls.Add((Label)sk.Body[i]);}//再panel中添加障碍物for (int i = 0; i < sk.Wall.Count; i++){this.panel1.Controls.Add((Label)sk.Wall[i]);}for (int i = 0; i < sk.Wall1.Count; i++){this.panel1.Controls.Add((Label)sk.Wall1[i]);}for (int i = 0; i < sk.Wall2.Count; i++){this.panel1.Controls.Add((Label)sk.Wall2[i]);}for (int i = 0; i < sk.Wall3.Count; i++){this.panel1.Controls.Add((Label)sk.Wall3[i]);}}private void GameOver() //结束游戏{panel1.Controls.Remove(sk.Food);PictureBox over = new PictureBox();over.Image = Snake.Properties.Resources.the_end;over.Width = 360;over.Height = 360;this.panel1.Controls.Add(over);timer1.Stop();panel1 = this.DeBomb(panel1);MessageBox.Show("你本次的得分为:" + textBox1.Text+",历史最高分为:"+textBox2.Text);}private void panel1_Paint(object sender, PaintEventArgs e) //初始化panel{NowStart();}private void Form1_Load(object sender, EventArgs e) //初始化Form创建蛇的对象{sk.CreateSnake();sk.CreateWall();sk.CreateWall1();sk.CreateWall2();sk.CreateWall3();this.CreatBomb();SoundPlayer music = new SoundPlayer(@"H:\Kalimba.wav");music.Play();//this.Draws();}private void HitSelf() //撞击自己{for (int i = 1; i < sk.Body.Count; i++){if (((Label)sk.Body[0]).Top == ((Label)sk.Body[i]).Top &&((Label)sk.Body[0]).Left == ((Label)sk.Body[i]).Left){GameOver();break;}}}public void move()//控制蛇的前进{for (int i = sk.Body.Count - 1; i > 0; i--){//判断是否撞墙(所建的障碍物)if (((Label)sk.Body[0]).Top == ((Label)sk.Wall[i]).Top &&(((Label)sk.Wall[i]).Left - 90 <= ((Label)sk.Body[0]).Left &&((Label)sk.Body[0]).Left <= ((Label)sk.Wall[i]).Left + 20)){GameOver();break;}else if (((Label)sk.Body[0]).Top == ((Label)sk.Wall1[i]).Top &&(((Label)sk.Wall1[i]).Left - 90 <= ((Label)sk.Body[0]).Left &&((Label)sk.Body[0]).Left <= ((Label)sk.Wall1[i]).Left + 20)){GameOver();break;}else if (((Label)sk.Body[0]).Left == ((Label)sk.Wall2[i]).Left &&(((Label)sk.Wall2[i]).Top -90 <= ((Label)sk.Body[0]).Top &&((Label)sk.Body[0]).Top<= ((Label)sk.Wall2[i]).Top + 20)){GameOver();break;}else if (((Label)sk.Body[0]).Left == ((Label)sk.Wall3[i]).Left &&(((Label)sk.Wall3[i]).Top - 90 <= ((Label)sk.Body[0]).Top &&((Label)sk.Body[0]).Top <= ((Label)sk.Wall3[i]).Top + 20)){GameOver();break;}//判断是否撞上炸弹else if (bomb_b.Y == ((Label)sk.Body[0]).Top && bomb_b.X ==((Label)sk.Body[0]).Left){GameOver();break;}else if (dir == 0 && diring != 1)//Up//运动方向{((Label)sk.Body[i]).Top = ((Label)sk.Body[i - 1]).Top;((Label)sk.Body[i]).Left = ((Label)sk.Body[i - 1]).Left;if (i == 1){((Label)sk.Body[0]).Top -= 10;panel1 = sk.EatFood(panel1, timer1, textBox1, textBox2);HitSelf();}if (((Label)sk.Body[0]).Top < 0){GameOver();break;}}else if (dir == 1 && diring != 0)//Down{((Label)sk.Body[i]).Top = ((Label)sk.Body[i - 1]).Top;((Label)sk.Body[i]).Left = ((Label)sk.Body[i - 1]).Left;if (i == 1){((Label)sk.Body[0]).Top += 10;panel1 = sk.EatFood(panel1, timer1, textBox1, textBox2);HitSelf();}if (((Label)sk.Body[0]).Top > 360){GameOver();break;}}else if (dir == 2 && diring != 3)//Left{((Label)sk.Body[i]).Top = ((Label)sk.Body[i - 1]).Top;((Label)sk.Body[i]).Left = ((Label)sk.Body[i - 1]).Left;if (i == 1){((Label)sk.Body[0]).Left -= 10;panel1 = sk.EatFood(panel1, timer1, textBox1, textBox2);HitSelf();}if (((Label)sk.Body[0]).Left< 0){GameOver();break;}}else if (dir == 3 && diring != 2)//Right{((Label)sk.Body[i]).Top = ((Label)sk.Body[i - 1]).Top;((Label)sk.Body[i]).Left = ((Label)sk.Body[i - 1]).Left;if (i == 1){((Label)sk.Body[0]).Left += 10;panel1 = sk.EatFood(panel1, timer1, textBox1, textBox2);HitSelf();}if (((Label)sk.Body[0]).Left > 360){GameOver();break;}}else//逆向{GameOver();break;}}}//timer控件具体实现private void timer1_Tick(object sender, EventArgs e){move();}//控制蛇的移动方向protected override bool ProcessDialogKey(Keys keyData){switch (keyData){case Keys.Up:dir = 0; break;case Keys.Down:dir = 1; break;case Keys.Left:dir = 2; break;case Keys.Right:dir = 3; break;}if (keyData == Keys.Up || keyData == Keys.Down || keyData == Keys.Left || keyData== Keys.Right){return false;}else{return base.ProcessDialogKey(keyData);}}private void button4_Click(object sender, EventArgs e) //退出{this.Close();}private void button5_Click(object sender, EventArgs e) //继续{timer1.Start();}private void button6_Click(object sender, EventArgs e) //帮助{MessageBox.Show("游戏介绍:\n" + "\n1、通过上下左右键控制蛇的移动。