----项目设计报告书
项目名称:贪吃蛇
指导老师:顾洪
所在系别:计算机系
班级:307051项目成员:张炜
[1**********]
孔金蕾[1**********]
目录
第一章引言..................................................................... 错误!未定义书签。
1.1编写目的......................................................................................... 11.2术语................................................................................................. 11.3参考文献......................................................................................... 1第二章系统概述....................................................................................... 22.1实例说明......................................................................................... 22.2设计思路................................................................ 错误!未定义书签。2.3技术要点......................................................................................... 22.4实现过程......................................................................................... 3第三章总体设计....................................................................................... 43.1项目界面图..................................................................................... 43.2新增功能........................................................................................ 8第四章程序代码...................................................................................................................10
第一章
1.1编写目的
引言
鉴于日常工作压力太大,闲暇的时间大多比较零碎,为了缓解紧张的情绪,获得更高工作效率,人们在日常的娱乐生活中,经常会玩一些单机版的益智类小游戏,它的特点是使用的内存小,又无需建立网络,更不会使人沉迷,获得了大多数人的喜爱。
1.2术语
访问修饰符
用于限制对类型或类型成员的访问的关键字,如private 、protected 、internal 或public 。可访问成员
一种可由给定类型访问的成员。一种类型的可访问成员不一定可由另一种类型访问。类(class)
一种描述对象的数据类型。类不仅包含数据,还包含作用于数据的方法。字段(field)
类或结构的一个可直接访问的数据成员。方法
一个提供类或结构的行为的命名代码块。属性(property)
通过访问器访问的数据成员。static
声明为静态的类或方法不必首先使用关键字new 进行实例化就可存在。Main()就属于静态方法。
1.3参考文献
C#范例完全自学手册
第二章系统概述
2.1实例说明
本实例将制作一个贪吃蛇游戏,读者可以根据该实例了解游戏的制作过程,达到举一反三的程度,为以后的开发工作,打下基础。
2.2设计思路
制作贪吃蛇的设计思路如下:
(1)明确贪吃蛇的游戏规则,例如,蛇头不能碰到场地的四周;蛇身不能重叠;当吃到
食物后,应在新的位置重新生成食物,且食物不能在蛇身内出现。
(2)将Panel 控件设为游戏背景。
(3)场地、贪吃蛇及食物都是在Panel 控件的重绘事件中绘制。绘制蛇身的好处是在贪
吃蛇进行移动时,不需要重新绘制背景。
(4)用Timer 组件来实现贪吃蛇的移动,并用该组件的Interval 属性来控制移动速度。
2.3技术要点
本实例主要使用Graphics 类在Panel 控件中绘制游戏场地及贪吃蛇。
蛇身的移动主要是用ArrayList 类来实现的,该类的主要功能是使用大小可按需要动态增加的数组实现IList 接口。本实例主要是用ArrayList 类的Insert 和RemoveAt 方法实现的。(1)Insert 方法。该方法的主要功能是将元素插入ArrayList 的指定索引处。其常用语法
如下:
Public virtual void Insert(intindex, Object value) 参数说明如下:
Index :从零开始的索引,应在该位置插入value 。value :要插入的Object 。该值可以为空引用。例如,在数组的开始位置插入一个值。代码如下:Point[]Place={newPoint(-1,-1)}ArrayList List=newArrayList(Place);Point Ep=newPoint(0,0);List.Insert(0,Ep);
(2)RemoveAt 方法。该方法用于移除ArrayList 类中指引索引处的元素。其常用语法如下:
Public virtual void RemoveAt (intindex) 参数说明如下。
Index :要移除的元素的从零开始的索引。例如,删除数组中的尾部元素。代码如下;
Point[]Place={newPoint(-1,-1)new Point(-1,-1)}
ArrayList List=newArrayList(Place);List. RemoveAt(List.count-1);
2.4实现过程
(1)新建一个Windows 应用程序,将其命名为“贪吃蛇”,默认窗体为From1。(2)在当前项目中添加一个类,将其命名为Snake 。(3)From1窗体主要用到的控件及说明如表12.1所示。
表12.1From1窗体主要用到的控件及说明控件类型
控件名称menuStrip1panel1Timer1Label2Textbox1
属性设置
在Items 属性中添加
命令项
BroderStyle 属性设置为None 无无无
说明
对游戏进行控制游戏场地
控制贪吃蛇的移动显示当前分数用于获得焦点,实现键盘操作
说明:在使用MenuStrip 组件对游戏进行控制时,为了节省编程代码,所有命令项的单击操作,可以在一个命令项的单击事件中执行,主要是在Tag 属性中根据不同命令项的功能设置相应的标识(int 型)。
第三章总体设计
3.1
项目界面图
初始界面图
难度等级图:
控制界面图
游戏结束图
3.2
新增功能
新增功能解释:为了提高贪吃蛇的趣味性,本项目在游戏中添加了障碍物,绿色的方块是食物,蓝色的是障碍物,碰上就结束游戏。
新增功能解释:为了满足玩家对自己的挑战,本项目添加了挑战级别的难度,它的速度越来越快,相信一定能给玩家一个刺激的体验。
第四章程序代码
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace 贪吃蛇
{
public partial class Form1:Form
{
public Form1()
{
InitializeComponent();
}
public bool r; //判断是否是挑战级
public static bool ifStart =false ; //判断是否开始
public static int career =400; //移动的速度
Snake snake =new Snake ();//实例化Snake类
int snake_W=20; //骨节的宽度
int snake_H=20; //骨节的高度
public static bool pause =false ; //是否暂停游戏
//封装一个GDI+绘图图面,绘制游戏场景
public void ProtractTable(Graphics g)
{
for (int i =0; i
g.DrawLine(new Pen (Color .Black, 1), new Point (i*snake_W,0), new Point (i*snake_W,panel1.Height)); //用画笔将两点连接成一线,形成竖线
}
for (int i =0; i
g.DrawLine(new Pen (Color .Black, 1), new Point (0,i *snake_H),new Point (panel1.Width,i *snake_H));//用画笔将两点连接成一线,形成横线
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g =panel1.CreateGraphics();//创建panel1控件的Graphics类
ProtractTable(g);//绘制游戏场景
if (!ifStart)//如是没有开始游戏
{
Snake .timer =timer1;
Snake .label =label2;
snake.Ophidian(panel1,snake_W);//初始化场地及贪吃蛇信息
}
else
{
for (int i =0; i
{
e.Graphics.FillRectangle(Snake .SolidB, ((Point ) Snake .List[i]).X+1,
((Point ) Snake .List[i]).Y+1, snake_W-1, snake_H-1);
}
e.Graphics.FillRectangle(Snake .SolidF, Snake .Food.X +1, Snake .Food.Y +1,
snake_W-1, snake_H-1); //绘制食物
if (Snake .ifGame) //如果游戏结束
//绘制提示文本
e.Graphics.DrawString("Game Over" , new Font ("宋体", 30, FontStyle .Bold),
new SolidBrush (Color .DarkSlateGray), new PointF (150,130));
}
}
private void 开始ToolStripMenuItem_Click(object sender, EventArgs e)
{
NoviceCortrol(Convert .ToInt32(((ToolStripMenuItem )sender).Tag.ToString()));snake.BuildFood();
textBox1.Focus();
}
//控制游戏的开始、暂停和结束等标识
public void NoviceCortrol(int n)
{
switch (n)
{
case 1://开始游戏
{
snake.clear();//清除障碍物点的位置
ifStart =false ;
Graphics g =panel1.CreateGraphics();//创建panel1控件的Graphics类
g.FillRectangle(Snake .SolidD, 0, 0, panel1.Width, panel1.Height); //
刷新游戏场地
ProtractTable(g);//绘制游戏场地
ifStart =true ; //开始游戏
snake.Ophidian(panel1,snake_W);//初始化场地及贪吃蛇信息
timer1.Interval =career; //设置贪吃蛇移动的速度
timer1.Start();//启动计时器
pause =true ; //是否暂停游戏
label2.Text ="0" ; //显示当前分数
break ;
}
case 2://暂停游戏
{
if (pause)//如果游戏正在运行
{
ifStart =true ; //游戏正在开始
timer1.Stop();//停止计时器
pause =false ; //当前已暂停游戏
}
else
{
ifStart =true ; //游戏正在开始
timer1.Start();//启动计时器
pause =true ; //开始游戏
}
break ;
}
case 3://退出游戏
{
timer1.Stop();//停止计时器
Application .Exit();//半闭工程
break ;
}
}
}
private void 初级ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (timer1.Enabled==false ) //如果游戏没有开始
{
初级ToolStripMenuItem.Checked=false ; //设置该项没有被选中
中级ToolStripMenuItem.Checked=false ; //设置该项没有被选中
高级ToolStripMenuItem.Checked=false ; //设置该项没有被选中
挑战ToolStripMenuItem.Checked=false ; //设置该项没有被选中
((ToolStripMenuItem )sender).Checked =true ; //设置当前项被选中
switch (Convert .ToInt32(((ToolStripMenuItem )sender).Tag.ToString()))
{
case 1://初级
{
career =400; //设置移动的速度
r =false ; //标志
label4.Text ="初级";
break ;
}
case 2://中级
{
career =200;
r =false ; //标志
label4.Text ="中级";
break ;
}
case 3://高级
{
career =50;
r =false ; //标志
label4.Text ="高级";
break ;
}
case 4://挑战
{
career =200;
r =true ; //标志
label4.Text ="挑战级";
break ;
}
}
}
textBox1.Focus();//获得焦点
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
int tem_n=-1; //记录移动键值
if (e.KeyCode==Keys .Right) //如果按→键
{
}tem_n=0; //向右移
if (e.KeyCode==Keys .Left) //如果按←键
{
tem_n=1; //向左移
}
if (e.KeyCode==Keys .Up) //如果按↑键
{
tem_n=2; //向上移
}
if (e.KeyCode==Keys .Down) //如果按↓键
{
tem_n=3; //向下移
}
if (tem_n!=-1&&tem_n!=Snake .Aspect) //如果移动的方向不是相同方向
{
if (Snake .ifGame ==false )
{
//如果移动的方向不是相反的方向
if (!((tem_n==0&&Snake .Aspect ==1||tem_n==1&&Snake .Aspect ==0)
||(tem_n==2&&Snake .Aspect ==3||tem_n==3&&Snake .Aspect ==2)))
{
Snake .Aspect =tem_n;//记录移动的方向
snake.SnakeMove(tem_n);//移动贪吃蛇
}
}
}
int tem_p=-1; //记录控制键值
if (e.KeyCode==Keys .F2) //如果按F2键
tem_p=1; //开始游戏
if (e.KeyCode==Keys .F3) //如果按F3键
tem_p=2; //暂停或继续游戏
if (e.KeyCode==Keys .F4) //如果按F4键
tem_p=3; //关闭游戏
if (tem_p!=-1) //如果当前是操作标识
NoviceCortrol(tem_p);//控制游戏的开始、暂止和关闭
}
private void timer1_Tick(object sender, EventArgs e)
{
snake.SnakeMove(Snake .Aspect); //移动贪吃蛇
if (r==true ) //如果是挑战级就将速度加快直至一个值
{
timer1.Interval -=1;
if (timer1.Interval
{
timer1.Interval =20;
}
}
label5.Text =timer1.Interval.ToString();//获取时间间隔
}
}
}
Snake.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
namespace 贪吃蛇
{
class Snake
{
public static int Condyle =0; //设置骨节的大小
public static int Aspect =0; //设置方向
public static Point []Place ={new Point (-1,-1), new Point (-1,-1), new Point (-1,-1), new Point (-1,-1), new Point (-1,-1), new Point (-1,-1) };//设置个骨节的位置
public static Point Food =new Point (-1,-1); //设置食物的所在点
public static Point fod =new Point (-1,-2);
public static bool ifFood =false ; //是否有食物
public static bool ifGame =false ; //游戏是否结束
public static int Field_width=0; //场地的宽度
public static int Field_Height=0; //场地的高度
public static Control control; //记录绘制贪吃蛇的控件
public static Timer timer; //记录Timer组件
public static SolidBrush SolidB =new SolidBrush (Color .Red); //设置贪吃蛇身体的颜色public static SolidBrush SolidD =new SolidBrush (Color .LightCoral); //设置背景颜色public static SolidBrush SolidF =new SolidBrush (Color .Green); //设置食物的颜色
public static SolidBrush solidf =new SolidBrush (Color .Blue);
public static Label label; //记录Label控件
public static ArrayList List =new ArrayList ();//实例化ArrayList数组
Point tem_p=new Point (-1,-1); //定义坐标结构
Point tem_j=new Point (-1,-2);
public Point []a =new Point [10000];
public int b =9999;
Graphics g; //实例化Graphics类
//初始化场地及贪吃蛇的信息,控件,骨节大小等
public void Ophidian(Control Con, int condyle)
{
Field_width=Con.Width; //获取场地的宽度
Field_Height=Con.Height; //获取场地的高度
Condyle =condyle; //记录骨节的大小
control =Con; //记录背景控件
g =control.CreateGraphics();//创建背景控件的Graphics类
SolidD =new SolidBrush (Con.BackColor);//设置画刷颜色
for (int i =0; i
{
Place[i].X=(Place.Length-i -1) *Condyle; //设置骨节的横坐标位置
Place[i].Y=(Field_Height/2) -Condyle; //设置骨节的纵坐标位置
g.FillRectangle(SolidB,Place[i].X+1, Place[i].Y+1, Condyle -1, Condyle -
1); //绘制骨节
}
List =new ArrayList (Place);//记录每个骨节的位置
ifGame =false ; //停止游戏
Aspect =0; //设置方向为右
}
//移动贪吃蛇,标识,判断的移动的方向
public void SnakeMove(int n)
{
Point tem_Point=new Point (-1,-1); //定义坐标结构
switch (n)
{
case 0://右移
{
tem_Point.X=((Point )List[0]).X+Condyle; //蛇头向右移
tem_Point.Y=((Point )List[0]).Y;
break ;
}
case 1://左移
{
tem_Point.X=((Point )List[0]).X-Condyle; //蛇头向左移
tem_Point.Y=((Point )List[0]).Y;
break ;
}
case 2://上移
{
tem_Point.Y=((Point )List[0]).Y-Condyle; //蛇头向上移
tem_Point.X=((Point )List[0]).X;
break ;
}
case 3://下移
{
tem_Point.Y=((Point )List[0]).Y+Condyle; //蛇头向下移
tem_Point.X=((Point )List[0]).X;
break ;
}
}
BuildFood();//生成食物
if (!EstimateMove(tem_Point))//如果没有向相反的方向移动
{
Aspect =n; //改变贪吃蛇的移动方向
if (!GameAborted(tem_Point))//如果游戏没有结束
{
ProtractSnake(tem_Point);//重新绘制蛇身
EatFood();//吃食
}
g.FillRectangle(SolidF,Food.X+1, Food.Y +1, Condyle -1, Condyle -1); //
绘制食物
g.FillRectangle(solidf,fod.X +1, fod.Y +1, Condyle -1, Condyle -1); //绘
制障碍物
}
}
//吃食
public void EatFood()
{
if ((((Point )List[0])==Food)) //如果蛇头吃到了食物
{
List.Add(List[List.Count-1]);//在蛇的尾部添加蛇身
//career+=10;
ifFood =false ; //没有食物
for (int i =500; i >=0; i--)
{
}
BuildFood();//生成食物
label.Text =Convert .ToString(Convert .ToInt32(label.Text)+5); //显示当前分数}
}
///游戏是否失败
//设置文本的显示位置
public bool GameAborted(Point GameP)
{
bool tem_b=false ; //游戏是否结束
bool tem_body=false ; //记录蛇身是否重叠
bool tem_v=false ;
for (int b=9999;b>=0;b--) //遍历数组
{
if ((Point )List[0]==(Point )a[b])
{
tem_v=true ;
}
}
for (int i =1; i
{
if (((Point )List[0])==((Point )List[i]))//如是骨节重叠
tem_body=true ; //游戏失败
}
//判断蛇头是否超出游戏场地
if (GameP.X=control.Width -1||GameP.Y =
control.Height -1||tem_body||tem_v)
{
//绘制游戏结束的提示文本
g.DrawString("Game Over" , new Font ("宋体", 30, FontStyle .Bold), new
SolidBrush (Color .DarkSlateGray), new PointF (150,130));
ifGame =true ; //游戏结束
timer.Stop();//停止记时器
tem_b=true ;
}
return tem_b;
}
//判断蛇是否向相反的方向移动
//移动的下一步位置
public bool EstimateMove(Point Ep)
{
bool tem_bool=false ; //记录蛇头是否向相反的方向移动
if (Ep.X==((Point )List[0]).X&&Ep.Y ==((Point )List[0]).Y)//如果蛇头向相反的方
向移动
tem_bool=true ;
return tem_bool;
}
//重新绘制蛇身
public void ProtractSnake(Point Ep)
{
bool tem_bool=false ; //是否清除移动后的蛇身
List.Insert(0,Ep); //根据蛇头的移动方向,设置蛇头的位置
Point tem_point=((Point )List[List.Count-1]);//记录蛇尾的位置
List.RemoveAt(List.Count-1); //移除蛇的尾部
//使骨节向前移动一位
for (int i =0; i
{
if (tem_point==((Point )List[i]))
tem_bool=true ;
}
if (!tem_bool)//清除贪吃蛇移动前的蛇尾部份
g.FillRectangle(SolidD,tem_point.X+1, tem_point.Y+1, Condyle -1, Condyle
-1);
for (int i =0; i
{
g.FillRectangle(SolidB,((Point )List[0]).X+1, ((Point )List[0]).Y+1, Condyle
-1, Condyle -1);
}
}
//生成食物
public void BuildFood()
{
if (ifFood==false ) //如果没有食物
{
bool tem_bool=true ; //是否计算出食物的合位置
bool tem_b=false ; //判断食物是否和蛇身重叠
while (tem_bool)//计算食物的显示位置
{
tem_b=false ;
tem_p=RectFood();//随机生成食物的位置
tem_j=RectFood();
for (int i =0; i
{
if (((Point )List[i])==tem_p)//如果食物是否和蛇身重叠
{
tem_b=true ; //记录重叠
break ;
}
if ((Point )List[i]==tem_j)
{
tem_b=true ;
break ;
}
if (tem_p==tem_j)
{
tem_b=true ;
break ;
}
}
for (int i =9999; i >=0; i--)
{
if ((Point )a[i]==tem_p)
{
tem_b=true ;
break ;
}
}
if (tem_b==false ) //如果没有重叠
tem_bool=false ; //退出循环
}
Food =tem_p;//记录食物的显示位置
fod =tem_j;
}
a[b].X=tem_j.X;//储存障碍物点位置
a[b].Y=tem_j.Y;
b--;
if (b==0)
b =9999;
ifFood =true ; //有食物
}
//随机生成食物的节点
public Point RectFood()
{
int tem_W=Field_width/20; //获取场地的行数
int tem_H=Field_Height/20; //获取场地的列数
Random RandW =new Random ();//实例化Random类
tem_W=RandW.Next(0,tem_W-1); //生成食物的横向坐标
Random RandH =new Random ();//实例化Random类
tem_H=RandH.Next(0,tem_H-1); //生成食物的纵向坐标
Point tme_P=new Point (tem_W*Condyle, tem_H*Condyle); //生成食物的显示位置return tme_P;
}
//清除障碍物的位置
public void clear()
{
for (int i =9999; i >=0;i--)
a[i]=new Point (0,0);
}
}
}
----项目设计报告书
项目名称:贪吃蛇
指导老师:顾洪
所在系别:计算机系
班级:307051项目成员:张炜
[1**********]
孔金蕾[1**********]
目录
第一章引言..................................................................... 错误!未定义书签。
1.1编写目的......................................................................................... 11.2术语................................................................................................. 11.3参考文献......................................................................................... 1第二章系统概述....................................................................................... 22.1实例说明......................................................................................... 22.2设计思路................................................................ 错误!未定义书签。2.3技术要点......................................................................................... 22.4实现过程......................................................................................... 3第三章总体设计....................................................................................... 43.1项目界面图..................................................................................... 43.2新增功能........................................................................................ 8第四章程序代码...................................................................................................................10
第一章
1.1编写目的
引言
鉴于日常工作压力太大,闲暇的时间大多比较零碎,为了缓解紧张的情绪,获得更高工作效率,人们在日常的娱乐生活中,经常会玩一些单机版的益智类小游戏,它的特点是使用的内存小,又无需建立网络,更不会使人沉迷,获得了大多数人的喜爱。
1.2术语
访问修饰符
用于限制对类型或类型成员的访问的关键字,如private 、protected 、internal 或public 。可访问成员
一种可由给定类型访问的成员。一种类型的可访问成员不一定可由另一种类型访问。类(class)
一种描述对象的数据类型。类不仅包含数据,还包含作用于数据的方法。字段(field)
类或结构的一个可直接访问的数据成员。方法
一个提供类或结构的行为的命名代码块。属性(property)
通过访问器访问的数据成员。static
声明为静态的类或方法不必首先使用关键字new 进行实例化就可存在。Main()就属于静态方法。
1.3参考文献
C#范例完全自学手册
第二章系统概述
2.1实例说明
本实例将制作一个贪吃蛇游戏,读者可以根据该实例了解游戏的制作过程,达到举一反三的程度,为以后的开发工作,打下基础。
2.2设计思路
制作贪吃蛇的设计思路如下:
(1)明确贪吃蛇的游戏规则,例如,蛇头不能碰到场地的四周;蛇身不能重叠;当吃到
食物后,应在新的位置重新生成食物,且食物不能在蛇身内出现。
(2)将Panel 控件设为游戏背景。
(3)场地、贪吃蛇及食物都是在Panel 控件的重绘事件中绘制。绘制蛇身的好处是在贪
吃蛇进行移动时,不需要重新绘制背景。
(4)用Timer 组件来实现贪吃蛇的移动,并用该组件的Interval 属性来控制移动速度。
2.3技术要点
本实例主要使用Graphics 类在Panel 控件中绘制游戏场地及贪吃蛇。
蛇身的移动主要是用ArrayList 类来实现的,该类的主要功能是使用大小可按需要动态增加的数组实现IList 接口。本实例主要是用ArrayList 类的Insert 和RemoveAt 方法实现的。(1)Insert 方法。该方法的主要功能是将元素插入ArrayList 的指定索引处。其常用语法
如下:
Public virtual void Insert(intindex, Object value) 参数说明如下:
Index :从零开始的索引,应在该位置插入value 。value :要插入的Object 。该值可以为空引用。例如,在数组的开始位置插入一个值。代码如下:Point[]Place={newPoint(-1,-1)}ArrayList List=newArrayList(Place);Point Ep=newPoint(0,0);List.Insert(0,Ep);
(2)RemoveAt 方法。该方法用于移除ArrayList 类中指引索引处的元素。其常用语法如下:
Public virtual void RemoveAt (intindex) 参数说明如下。
Index :要移除的元素的从零开始的索引。例如,删除数组中的尾部元素。代码如下;
Point[]Place={newPoint(-1,-1)new Point(-1,-1)}
ArrayList List=newArrayList(Place);List. RemoveAt(List.count-1);
2.4实现过程
(1)新建一个Windows 应用程序,将其命名为“贪吃蛇”,默认窗体为From1。(2)在当前项目中添加一个类,将其命名为Snake 。(3)From1窗体主要用到的控件及说明如表12.1所示。
表12.1From1窗体主要用到的控件及说明控件类型
控件名称menuStrip1panel1Timer1Label2Textbox1
属性设置
在Items 属性中添加
命令项
BroderStyle 属性设置为None 无无无
说明
对游戏进行控制游戏场地
控制贪吃蛇的移动显示当前分数用于获得焦点,实现键盘操作
说明:在使用MenuStrip 组件对游戏进行控制时,为了节省编程代码,所有命令项的单击操作,可以在一个命令项的单击事件中执行,主要是在Tag 属性中根据不同命令项的功能设置相应的标识(int 型)。
第三章总体设计
3.1
项目界面图
初始界面图
难度等级图:
控制界面图
游戏结束图
3.2
新增功能
新增功能解释:为了提高贪吃蛇的趣味性,本项目在游戏中添加了障碍物,绿色的方块是食物,蓝色的是障碍物,碰上就结束游戏。
新增功能解释:为了满足玩家对自己的挑战,本项目添加了挑战级别的难度,它的速度越来越快,相信一定能给玩家一个刺激的体验。
第四章程序代码
Form1.cs
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace 贪吃蛇
{
public partial class Form1:Form
{
public Form1()
{
InitializeComponent();
}
public bool r; //判断是否是挑战级
public static bool ifStart =false ; //判断是否开始
public static int career =400; //移动的速度
Snake snake =new Snake ();//实例化Snake类
int snake_W=20; //骨节的宽度
int snake_H=20; //骨节的高度
public static bool pause =false ; //是否暂停游戏
//封装一个GDI+绘图图面,绘制游戏场景
public void ProtractTable(Graphics g)
{
for (int i =0; i
g.DrawLine(new Pen (Color .Black, 1), new Point (i*snake_W,0), new Point (i*snake_W,panel1.Height)); //用画笔将两点连接成一线,形成竖线
}
for (int i =0; i
g.DrawLine(new Pen (Color .Black, 1), new Point (0,i *snake_H),new Point (panel1.Width,i *snake_H));//用画笔将两点连接成一线,形成横线
}
}
private void panel1_Paint(object sender, PaintEventArgs e)
{
Graphics g =panel1.CreateGraphics();//创建panel1控件的Graphics类
ProtractTable(g);//绘制游戏场景
if (!ifStart)//如是没有开始游戏
{
Snake .timer =timer1;
Snake .label =label2;
snake.Ophidian(panel1,snake_W);//初始化场地及贪吃蛇信息
}
else
{
for (int i =0; i
{
e.Graphics.FillRectangle(Snake .SolidB, ((Point ) Snake .List[i]).X+1,
((Point ) Snake .List[i]).Y+1, snake_W-1, snake_H-1);
}
e.Graphics.FillRectangle(Snake .SolidF, Snake .Food.X +1, Snake .Food.Y +1,
snake_W-1, snake_H-1); //绘制食物
if (Snake .ifGame) //如果游戏结束
//绘制提示文本
e.Graphics.DrawString("Game Over" , new Font ("宋体", 30, FontStyle .Bold),
new SolidBrush (Color .DarkSlateGray), new PointF (150,130));
}
}
private void 开始ToolStripMenuItem_Click(object sender, EventArgs e)
{
NoviceCortrol(Convert .ToInt32(((ToolStripMenuItem )sender).Tag.ToString()));snake.BuildFood();
textBox1.Focus();
}
//控制游戏的开始、暂停和结束等标识
public void NoviceCortrol(int n)
{
switch (n)
{
case 1://开始游戏
{
snake.clear();//清除障碍物点的位置
ifStart =false ;
Graphics g =panel1.CreateGraphics();//创建panel1控件的Graphics类
g.FillRectangle(Snake .SolidD, 0, 0, panel1.Width, panel1.Height); //
刷新游戏场地
ProtractTable(g);//绘制游戏场地
ifStart =true ; //开始游戏
snake.Ophidian(panel1,snake_W);//初始化场地及贪吃蛇信息
timer1.Interval =career; //设置贪吃蛇移动的速度
timer1.Start();//启动计时器
pause =true ; //是否暂停游戏
label2.Text ="0" ; //显示当前分数
break ;
}
case 2://暂停游戏
{
if (pause)//如果游戏正在运行
{
ifStart =true ; //游戏正在开始
timer1.Stop();//停止计时器
pause =false ; //当前已暂停游戏
}
else
{
ifStart =true ; //游戏正在开始
timer1.Start();//启动计时器
pause =true ; //开始游戏
}
break ;
}
case 3://退出游戏
{
timer1.Stop();//停止计时器
Application .Exit();//半闭工程
break ;
}
}
}
private void 初级ToolStripMenuItem_Click(object sender, EventArgs e)
{
if (timer1.Enabled==false ) //如果游戏没有开始
{
初级ToolStripMenuItem.Checked=false ; //设置该项没有被选中
中级ToolStripMenuItem.Checked=false ; //设置该项没有被选中
高级ToolStripMenuItem.Checked=false ; //设置该项没有被选中
挑战ToolStripMenuItem.Checked=false ; //设置该项没有被选中
((ToolStripMenuItem )sender).Checked =true ; //设置当前项被选中
switch (Convert .ToInt32(((ToolStripMenuItem )sender).Tag.ToString()))
{
case 1://初级
{
career =400; //设置移动的速度
r =false ; //标志
label4.Text ="初级";
break ;
}
case 2://中级
{
career =200;
r =false ; //标志
label4.Text ="中级";
break ;
}
case 3://高级
{
career =50;
r =false ; //标志
label4.Text ="高级";
break ;
}
case 4://挑战
{
career =200;
r =true ; //标志
label4.Text ="挑战级";
break ;
}
}
}
textBox1.Focus();//获得焦点
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
int tem_n=-1; //记录移动键值
if (e.KeyCode==Keys .Right) //如果按→键
{
}tem_n=0; //向右移
if (e.KeyCode==Keys .Left) //如果按←键
{
tem_n=1; //向左移
}
if (e.KeyCode==Keys .Up) //如果按↑键
{
tem_n=2; //向上移
}
if (e.KeyCode==Keys .Down) //如果按↓键
{
tem_n=3; //向下移
}
if (tem_n!=-1&&tem_n!=Snake .Aspect) //如果移动的方向不是相同方向
{
if (Snake .ifGame ==false )
{
//如果移动的方向不是相反的方向
if (!((tem_n==0&&Snake .Aspect ==1||tem_n==1&&Snake .Aspect ==0)
||(tem_n==2&&Snake .Aspect ==3||tem_n==3&&Snake .Aspect ==2)))
{
Snake .Aspect =tem_n;//记录移动的方向
snake.SnakeMove(tem_n);//移动贪吃蛇
}
}
}
int tem_p=-1; //记录控制键值
if (e.KeyCode==Keys .F2) //如果按F2键
tem_p=1; //开始游戏
if (e.KeyCode==Keys .F3) //如果按F3键
tem_p=2; //暂停或继续游戏
if (e.KeyCode==Keys .F4) //如果按F4键
tem_p=3; //关闭游戏
if (tem_p!=-1) //如果当前是操作标识
NoviceCortrol(tem_p);//控制游戏的开始、暂止和关闭
}
private void timer1_Tick(object sender, EventArgs e)
{
snake.SnakeMove(Snake .Aspect); //移动贪吃蛇
if (r==true ) //如果是挑战级就将速度加快直至一个值
{
timer1.Interval -=1;
if (timer1.Interval
{
timer1.Interval =20;
}
}
label5.Text =timer1.Interval.ToString();//获取时间间隔
}
}
}
Snake.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
namespace 贪吃蛇
{
class Snake
{
public static int Condyle =0; //设置骨节的大小
public static int Aspect =0; //设置方向
public static Point []Place ={new Point (-1,-1), new Point (-1,-1), new Point (-1,-1), new Point (-1,-1), new Point (-1,-1), new Point (-1,-1) };//设置个骨节的位置
public static Point Food =new Point (-1,-1); //设置食物的所在点
public static Point fod =new Point (-1,-2);
public static bool ifFood =false ; //是否有食物
public static bool ifGame =false ; //游戏是否结束
public static int Field_width=0; //场地的宽度
public static int Field_Height=0; //场地的高度
public static Control control; //记录绘制贪吃蛇的控件
public static Timer timer; //记录Timer组件
public static SolidBrush SolidB =new SolidBrush (Color .Red); //设置贪吃蛇身体的颜色public static SolidBrush SolidD =new SolidBrush (Color .LightCoral); //设置背景颜色public static SolidBrush SolidF =new SolidBrush (Color .Green); //设置食物的颜色
public static SolidBrush solidf =new SolidBrush (Color .Blue);
public static Label label; //记录Label控件
public static ArrayList List =new ArrayList ();//实例化ArrayList数组
Point tem_p=new Point (-1,-1); //定义坐标结构
Point tem_j=new Point (-1,-2);
public Point []a =new Point [10000];
public int b =9999;
Graphics g; //实例化Graphics类
//初始化场地及贪吃蛇的信息,控件,骨节大小等
public void Ophidian(Control Con, int condyle)
{
Field_width=Con.Width; //获取场地的宽度
Field_Height=Con.Height; //获取场地的高度
Condyle =condyle; //记录骨节的大小
control =Con; //记录背景控件
g =control.CreateGraphics();//创建背景控件的Graphics类
SolidD =new SolidBrush (Con.BackColor);//设置画刷颜色
for (int i =0; i
{
Place[i].X=(Place.Length-i -1) *Condyle; //设置骨节的横坐标位置
Place[i].Y=(Field_Height/2) -Condyle; //设置骨节的纵坐标位置
g.FillRectangle(SolidB,Place[i].X+1, Place[i].Y+1, Condyle -1, Condyle -
1); //绘制骨节
}
List =new ArrayList (Place);//记录每个骨节的位置
ifGame =false ; //停止游戏
Aspect =0; //设置方向为右
}
//移动贪吃蛇,标识,判断的移动的方向
public void SnakeMove(int n)
{
Point tem_Point=new Point (-1,-1); //定义坐标结构
switch (n)
{
case 0://右移
{
tem_Point.X=((Point )List[0]).X+Condyle; //蛇头向右移
tem_Point.Y=((Point )List[0]).Y;
break ;
}
case 1://左移
{
tem_Point.X=((Point )List[0]).X-Condyle; //蛇头向左移
tem_Point.Y=((Point )List[0]).Y;
break ;
}
case 2://上移
{
tem_Point.Y=((Point )List[0]).Y-Condyle; //蛇头向上移
tem_Point.X=((Point )List[0]).X;
break ;
}
case 3://下移
{
tem_Point.Y=((Point )List[0]).Y+Condyle; //蛇头向下移
tem_Point.X=((Point )List[0]).X;
break ;
}
}
BuildFood();//生成食物
if (!EstimateMove(tem_Point))//如果没有向相反的方向移动
{
Aspect =n; //改变贪吃蛇的移动方向
if (!GameAborted(tem_Point))//如果游戏没有结束
{
ProtractSnake(tem_Point);//重新绘制蛇身
EatFood();//吃食
}
g.FillRectangle(SolidF,Food.X+1, Food.Y +1, Condyle -1, Condyle -1); //
绘制食物
g.FillRectangle(solidf,fod.X +1, fod.Y +1, Condyle -1, Condyle -1); //绘
制障碍物
}
}
//吃食
public void EatFood()
{
if ((((Point )List[0])==Food)) //如果蛇头吃到了食物
{
List.Add(List[List.Count-1]);//在蛇的尾部添加蛇身
//career+=10;
ifFood =false ; //没有食物
for (int i =500; i >=0; i--)
{
}
BuildFood();//生成食物
label.Text =Convert .ToString(Convert .ToInt32(label.Text)+5); //显示当前分数}
}
///游戏是否失败
//设置文本的显示位置
public bool GameAborted(Point GameP)
{
bool tem_b=false ; //游戏是否结束
bool tem_body=false ; //记录蛇身是否重叠
bool tem_v=false ;
for (int b=9999;b>=0;b--) //遍历数组
{
if ((Point )List[0]==(Point )a[b])
{
tem_v=true ;
}
}
for (int i =1; i
{
if (((Point )List[0])==((Point )List[i]))//如是骨节重叠
tem_body=true ; //游戏失败
}
//判断蛇头是否超出游戏场地
if (GameP.X=control.Width -1||GameP.Y =
control.Height -1||tem_body||tem_v)
{
//绘制游戏结束的提示文本
g.DrawString("Game Over" , new Font ("宋体", 30, FontStyle .Bold), new
SolidBrush (Color .DarkSlateGray), new PointF (150,130));
ifGame =true ; //游戏结束
timer.Stop();//停止记时器
tem_b=true ;
}
return tem_b;
}
//判断蛇是否向相反的方向移动
//移动的下一步位置
public bool EstimateMove(Point Ep)
{
bool tem_bool=false ; //记录蛇头是否向相反的方向移动
if (Ep.X==((Point )List[0]).X&&Ep.Y ==((Point )List[0]).Y)//如果蛇头向相反的方
向移动
tem_bool=true ;
return tem_bool;
}
//重新绘制蛇身
public void ProtractSnake(Point Ep)
{
bool tem_bool=false ; //是否清除移动后的蛇身
List.Insert(0,Ep); //根据蛇头的移动方向,设置蛇头的位置
Point tem_point=((Point )List[List.Count-1]);//记录蛇尾的位置
List.RemoveAt(List.Count-1); //移除蛇的尾部
//使骨节向前移动一位
for (int i =0; i
{
if (tem_point==((Point )List[i]))
tem_bool=true ;
}
if (!tem_bool)//清除贪吃蛇移动前的蛇尾部份
g.FillRectangle(SolidD,tem_point.X+1, tem_point.Y+1, Condyle -1, Condyle
-1);
for (int i =0; i
{
g.FillRectangle(SolidB,((Point )List[0]).X+1, ((Point )List[0]).Y+1, Condyle
-1, Condyle -1);
}
}
//生成食物
public void BuildFood()
{
if (ifFood==false ) //如果没有食物
{
bool tem_bool=true ; //是否计算出食物的合位置
bool tem_b=false ; //判断食物是否和蛇身重叠
while (tem_bool)//计算食物的显示位置
{
tem_b=false ;
tem_p=RectFood();//随机生成食物的位置
tem_j=RectFood();
for (int i =0; i
{
if (((Point )List[i])==tem_p)//如果食物是否和蛇身重叠
{
tem_b=true ; //记录重叠
break ;
}
if ((Point )List[i]==tem_j)
{
tem_b=true ;
break ;
}
if (tem_p==tem_j)
{
tem_b=true ;
break ;
}
}
for (int i =9999; i >=0; i--)
{
if ((Point )a[i]==tem_p)
{
tem_b=true ;
break ;
}
}
if (tem_b==false ) //如果没有重叠
tem_bool=false ; //退出循环
}
Food =tem_p;//记录食物的显示位置
fod =tem_j;
}
a[b].X=tem_j.X;//储存障碍物点位置
a[b].Y=tem_j.Y;
b--;
if (b==0)
b =9999;
ifFood =true ; //有食物
}
//随机生成食物的节点
public Point RectFood()
{
int tem_W=Field_width/20; //获取场地的行数
int tem_H=Field_Height/20; //获取场地的列数
Random RandW =new Random ();//实例化Random类
tem_W=RandW.Next(0,tem_W-1); //生成食物的横向坐标
Random RandH =new Random ();//实例化Random类
tem_H=RandH.Next(0,tem_H-1); //生成食物的纵向坐标
Point tme_P=new Point (tem_W*Condyle, tem_H*Condyle); //生成食物的显示位置return tme_P;
}
//清除障碍物的位置
public void clear()
{
for (int i =9999; i >=0;i--)
a[i]=new Point (0,0);
}
}
}