您好,欢迎来到年旅网。
搜索
您的当前位置:首页贪吃蛇项目分析文档

贪吃蛇项目分析文档

来源:年旅网


----项目设计报告书

项目名称:贪吃蛇

指导老师:顾洪

所在系别:计算机系

班级:307051

项目成员:张炜 32007051034 孔金蕾 32007051053

I

目录

第一章 引言........................................................... 错误!未定义书签。 1.1编写目的 ........................................................................................ 1 1.2术语 ................................................................................................. 1 1.3参考文献 ........................................................................................ 1 第二章 系统概述 ...................................................................................... 2 2.1实例说明 ........................................................................................ 2 2.2设计思路 ..................................................... 错误!未定义书签。 2.3技术要点 ........................................................................................ 2 2.4实现过程 ........................................................................................ 3 第三章 总体设计 ...................................................................................... 4 3.1项目界面图 .................................................................................... 4 3.2 新增功能 ....................................................................................... 8 第四章 程序代码 ................................................................................................................. 10

第一章 引言

1.1编写目的

鉴于日常工作压力太大,闲暇的时间大多比较零碎,为了缓解紧张的情绪,获得更高工作效率,人们在日常的娱乐生活中,经常会玩一些单机版的益智类小游戏,它的特点是使用的内存小,又无需建立网络,更不会使人沉迷,获得了大多数人的喜爱。

1.2术语

访问修饰符

用于对类型或类型成员的访问的关键字,如 private、protected、internal 或 public。 可访问成员

一种可由给定类型访问的成员。一种类型的可访问成员不一定可由另一种类型访问。 类 (class)

一种描述对象的数据类型。类不仅包含数据,还包含作用于数据的方法。 字段 (field)

类或结构的一个可直接访问的数据成员。 方法

一个提供类或结构的行为的命名代码块。 属性 (property)

通过访问器访问的数据成员。 static

声明为静态的类或方法不必首先使用关键字 new 进行实例化就可存在。Main() 就属于静态方法。

1.3参考文献

C#范例完全自学手册

1

第二章 系统概述

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(int index, Object value) 参数说明如下:

Index:从零开始的索引,应在该位置插入value。 value:要插入的Object。该值可以为空引用。 例如,在数组的开始位置插入一个值。代码如下: Point[] Place={new Point(-1,-1)} ArrayList List=new ArrayList(Place); Point Ep=new Point(0,0); List.Insert(0,Ep);

(2) RemoveAt方法。该方法用于移除ArrayList类中指引索引处的元素。其常用语法如下: Public virtual void RemoveAt (int index) 参数说明如下。

Index:要移除的元素的从零开始的索引。 例如,删除数组中的尾部元素。代码如下;

Point[] Place={new Point(-1,-1) new Point(-1,-1)}

2

ArrayList List=new ArrayList(Place); List. RemoveAt(List.count-1);

2.4实现过程

(1) 新建一个Windows应用程序,将其命名为“贪吃蛇”,默认窗体为From1。 (2) 在当前项目中添加一个类,将其命名为Snake。 (3) From1窗体主要用到的控件及说明如表12.1所示。 表12.1 From1窗体主要用到的控件及说明 控件类型 panel1 Timer1 Textbox1 无 用于获得焦点,实现键盘操作 Label2 无 显示当前分数 控件名称 menuStrip1 属性设置 在Items属性中添加命令项 BroderStyle属性设置为None 无 说明 对游戏进行控制 游戏场地 控制贪吃蛇的移动

说明:在使用MenuStrip组件对游戏进行控制时,为了节省编程代码,所有命令项的单击操作,可以在一个命令项的单击事件中执行,主要是在Tag属性中根据不同命令项的功能设置相应的标识(int型)。

3

第三章 总体设计

3.1项目界面图

初始界面图

4

难度等级图:

5

控制界面图

6

游戏结束图

7

3.2新增功能

新增功能解释:为了提高贪吃蛇的趣味性,本项目在游戏中添加了障碍物,绿色的方块是食物,蓝色的是障碍物,碰上就结束游戏。

8

新增功能解释:为了满足玩家对自己的挑战,本项目添加了挑战级别的难度,它的速度越来越快,相信一定能给玩家一个刺激的体验。

9

第四章 程序代码

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 <= panel1.Width / snake_W; 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 <= panel1.Height / snake_H; i++)//绘制单元格的横向线 {

g.DrawLine(new Pen(Color.Black, 1), new Point(0, i * snake_H), new Point(panel1.Width, i * snake_H));//用画笔将两点连接成一线,形成横线 }

10

}

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 < Snake.List.Count; 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();//清除障碍物点的位置

11

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;//设置该项没有被选中

12

中级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)//如果按→键

13

{ 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);//移动贪吃蛇

14

if (r == true)//如果是挑战级就将速度加快直至一个值 {

timer1.Interval -= 1; if (timer1.Interval <= 20) {

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);//设置食物的颜色

15

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.Length; 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;

16

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))//如果蛇头吃到了食物

17

{

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 < List.Count; i++)//遍历所有骨节 {

if (((Point)List[0]) == ((Point)List[i]))//如是骨节重叠 tem_body = true;//游戏失败 }

//判断蛇头是否超出游戏场地

if (GameP.X <= -20 || GameP.X >= control.Width - 1 || GameP.Y <= -20 || 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();//停止记时器

18

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 < List.Count - 1; 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 < List.Count; i++)//重新绘制蛇身 {

g.FillRectangle(SolidB, ((Point)List[0]).X + 1, ((Point)List[0]).Y + 1, Condyle - 1, Condyle - 1); } }

19

//生成食物

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 < List.Count; 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;//退出循环 }

20

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); } } }

21

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- oldu.cn 版权所有 浙ICP备2024123271号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务