计算机实习报告
姓名:
班级:
学号:
小班序号:
指导老师:
题目:贪吃蛇(运行环境:visual,studio 2010)
邮箱:
1.1总体功能说明
[主要完成什么功能,特色是什么。]、
我设计的的游戏首先在主界面选择游戏难度,接着进行游戏,在游戏过程中贪吃蛇不停地吃掉随机产生的食物,蛇身增长,直到蛇触碰到自己的身躯或边框,游戏结束
特色:1.游戏过程伴有音乐,游戏开始会出现一段游戏剧情,增加趣味性
2,游戏可以自选难度,且蛇身长每增加5,设速度都会增快直到最快速度为止,且游戏过程中一直显示难度,
3,游戏可以储存游戏分数,你可以查看最高分
4,游戏过程中蛇的颜色,食物的颜色,分数的颜色,可以不停变换,增加视觉效果
5,为降低难度,分数到达12的倍数时,蛇身会变为5
1.2用户界面
[关键游戏界面,并且要说明该界面完成的功能,不用把所有界面都显示出来]
游戏开始界面:选择游戏的难度
游戏过程界面:进行游戏
游戏结束界面:选择是否重新游戏
1.3使用方法
[比如:可以是什么键控制游戏?是否可以划分那难度?游戏是否可配置,界面风格是否可选等等]
用方向键控制蛇的移动,输入1,2,3,选择难度,游戏中按除方向键其他键暂停,结束界面y重新游戏,n退出游戏
2.1 总体设计框架
[包括程序执行流程,模块划分等,需要有文字说明和框图表示]
2.2 关键算法描述
算法1:[算法输入参数和输出参数,算法功能,使用什么存储结构,在主程序中起什么作用,可以使用框图或伪代码表示。
算法2: 同上
算法1:蛇的移动
使用数组静态存储蛇身于食物,如果不控制方向,则蛇处于一个循环中,每次蛇身后一个元素取代前一个位置,蛇头向前移动一,如有按键,则跳出内循环,根据按键寻则蛇的运动
伪代码: while循环
检测是否有按键,若有,进入相应循环
休眠
原来蛇位置变为空白
蛇身数组后一个元素取代前一个元素位置
根据按键改变蛇头位置
显示蛇身
若有按键,跳出内循环
算法2:水果的产生
使用结构表示水果,当水果被蛇吃掉后,随机产生一个水果
伪代码:if 蛇头位置与水果位置重合
While 循环
随机产生水果的坐标
If 坐标在框图内
{
If 水果坐标不与蛇每一个坐标重合 跳出循环
}
算法3:判断蛇的死亡
While a=0
For 取遍蛇身每一个元素
{
If 蛇头出了框图或蛇头与蛇身重合
a=1
}(a=1则循环停止)
2.3 程序设计的难点和关键点
:1随机产生水果的位置,要保证水果在框图内且水果与蛇身不重和,
2,判断蛇的死亡
3,控制蛇的颜色变换
4,对于分数的储存和导入
2.4 调试的方法
[过程中出现的问题和解决方法]
有时候蛇吃掉水果后没有产生水果,经过多次实验和同学讨论,发现逻辑错误,水果可能被蛇身覆盖
在检测按键时无法识别,经过debug逐过程逐语句调试最后解决问题
2.5 程序性能评价
[从运行效果上进行分析,找出程序的优点和不足]
[从程序设计上进行分析,找出程序的优点和不足]
优点:游戏拥有剧情,音乐,可以自己调节难度,蛇的颜色和分数的颜色,水果的颜色随蛇的运动而变化,色彩绚丽,随游戏进行蛇速度越来越快,难度增加,但蛇增到一定程度又会变短,降低游戏难度,增加游戏持久性
缺点:游戏单调,限于能力与时间,没有设置各种小物件,如障碍物,奖励,过关入口
这次计算机课程让我实际运用搜学知识去解决问题,让我学到了许多编程知识,我发现仅仅运用课上所学无法编实际问题,实际执行过程与预想不一致,偶尔会出现bug。很考验我的逻辑与耐心,在编程中我学到了许多编程知识,学会了许多的调试程序的方法,在实际编程中,我遇到许多困难,例如:蛇的头部与食物的检测问题,蛇的移动与显示问题,蛇的转向问题,食物的随机生成问题等等,我通过在网上搜集资料与自己的分析,终于从最初的一头雾水理出一丝头绪,最终终于完成了这个游戏,使我对编程产生了强烈的兴趣,也是我明白了万事开头难,只要入门,就可以完成许多看似不可能的事
*****************
实验报告
实验名称:网络编程基础实训教程(贪吃蛇)
1. 实验目的
通过开发一款贪吃蛇游戏程序,熟练掌握C#编程语言、和面向对象程序设计方法,独立完成一个游戏程序的开发。
2. 实验题目
使用C#编程语言,开发一款贪吃蛇游戏,如下图所示。
3. 功能描述
a) 游戏场地是一片矩形区域的草坪。
b) 一条蛇由蛇头和蛇身组成。
c) 当游戏开始之后,草坪中出现一颗豆和一条蛇,并且蛇不停地移动,蛇移动方向与蛇头一致。
d) 当游戏暂停之后,蛇停止移动。
e) 当蛇移动时,玩家使用“↑”、“↓”、“←”和“→”四个键控制蛇的移动方向。
f) 当蛇头与豆的位置重合时,豆被蛇吃掉,同时在草坪中再生成一颗新的豆,蛇身增加一节。
g) 当蛇头碰到蛇身时,则咬断蛇身,后半部分的蛇身消失。
h) 当蛇头碰到草坪四周时,蛇立即毙命,游戏结束。
4. 需求分析
根据功能描述可知,贪吃蛇游戏的系统结构图如下所示。
定义数据字典如下:
1) 草坪(Lawn):草坪是贪吃蛇游戏的场地。豆和蛇只能存在于草坪范围之内。草坪具有大小和颜色等属性。
2) 蛇(Snake):在贪吃蛇游戏中,蛇由若干节组成,其中第一节是蛇头,其余是蛇身。在游戏过程中,有且仅有一条蛇,并且蛇在不停地移动。如果蛇吃了豆,则蛇生长一节。如果蛇头碰到蛇身,则咬断蛇身,后半部分的蛇身消失。如果蛇头离开草坪,则蛇死亡游戏结束。蛇具有长度、颜色、运动方向、每一节的位置等属性。
3) 豆(Bean):在贪吃蛇游戏中,豆是蛇的食物。在游戏过程中,有且仅有一颗豆。如果蛇吃了豆,则重新生成一颗豆。豆具有位置、大小和颜色等属性。
5. 设计说明
根据需求分析可知,Snake的每一节都有位置和大小等属性。而Bean也具有这两个属性。抽象出二者的共同特征,抽象出一般类Block,用于描述一个块。Block派生出Bean和SnakeBlock两个类,其中SnakeBlock类用于描述蛇的一节。
为了使游戏的运行更易于控制,定义Game类用于启动、暂停和继续游戏。
根据需求分析可知,Lawn仅包含大小和颜色两个属性。为了减少类的数量,可将其大小和颜色等属性添加到Game类中。
综上所述,在贪吃蛇游戏中,有Block(块)、Bean(豆)、SankeBlock(节)、Snake(蛇)、Game(游戏)和MainForm(用户接口)六个类。贪吃蛇游戏的逻辑模型如下图所示。
6. 源代码
1) Block(块)类的编码
Block是用来构成Bean(豆)和Snake(蛇)的最基本的单位,是Bean和SnakeBlock的基类。Block类的参考代码如下。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace WindowsFormsApplication1
{
class Block
{
protected Point origion; //Block的左上顶点
public const int WIDTH = 10; //Block的宽度
public const int HEIGHT = 10; //Block的高度
protected Color color; //Block的颜色
public Block()
{
origion = new Point(0, 0);
color = new Color();
}
public Block(int x, int y, Color _color)
{
origion = new Point(x, y);
color = _color;
}
public Point Origion
{
get
{
return origion;
}
}
public void Display(Graphics g)
{
SolidBrush brush = new SolidBrush(color);
g.FillRectangle(brush, origion.X, origion.Y, WIDTH, HEIGHT);
Pen pen = new Pen(Color.Black);
g.DrawRectangle(pen, new Rectangle(origion.X, origion.Y, WIDTH - 1, HEIGHT - 1));
}
public void Clear(Graphics g, Color backGroundColor)
{
SolidBrush brush = new SolidBrush(backGroundColor);
g.FillRectangle(brush, origion.X, origion.Y, WIDTH, HEIGHT);
}
}
}
2)Bean(豆)类编码
Bean表示豆,是由Block派生而来的。Bean类的参考代码如下。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace WindowsFormsApplication1
{ class Bean : Block
{
public Bean(Color _color)
{
origion = new Point(0, 0);
color = _color;
}
public void Creat(Graphics g, Color backGroundColor, int lawnWidth, int lawnHeight, Snake snake)
{
Clear(g, backGroundColor);
bool bGetAPosition = false; //是否找到生成豆的位置
Random random = new Random();
while (!bGetAPosition)
{
origion.X = random.Next(0, lawnWidth - 1) / WIDTH * WIDTH;
origion.Y = random.Next(0, lawnHeight - 1) / HEIGHT * HEIGHT;
int i;
for (i = 0; i < snake.Length; i++)
{
if (origion == snake.blocks[i].Origion)
break;
}
if (i == snake.Length)
bGetAPosition = true;
}
Display(g);
}
}
}
3)SnakeBlock(节)类编码
SnakeBlock表示蛇的一节,是由Block派生而来的。SnakeBlock类的参考代码如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace WindowsFormsApplication1
{ class SnakeBlock : Block
{
private bool isHead;
public bool IsHead
{
get
{
return isHead;
}
}
public SnakeBlock(int x, int y, Color _color, bool _isHead)
{
origion = new Point(x, y);
color = _color;
isHead = _isHead;
}
public void ChangeHeadToBody()
{
if (isHead)
isHead = false;
}
public void Display(Graphics g, Direction direction)
{
base.Display(g);
if (isHead)
{
//绘制蛇眼
SolidBrush brush = new SolidBrush(Color.Brown);
switch (direction)
{
case Direction.Up:
case Direction.Down:
g.FillRectangle(brush, origion.X + WIDTH / 4, origion.Y +HEIGHT / 2, 2, 2);
g.FillRectangle(brush, origion.X + WIDTH / 4 * 3, origion.Y + HEIGHT / 2, 2, 2);
break;
case Direction.Left:
case Direction.Right:
g.FillRectangle(brush, origion.X + WIDTH / 2, origion.Y + HEIGHT / 4, 2, 2);
g.FillRectangle(brush, origion.X + WIDTH / 2, origion.Y + HEIGHT / 4 * 3, 2, 2);
break;
}
}
}
}
}
Snake(蛇)类编码
4)Snake(蛇)类编码
Snake表示蛇。Snake类的参考代码如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace HungrySanke
{
public enum Direction
{
Up,
Down,
Left,
Right
};
class Snake
{
private int length;
public Direction direction;
private Color color;
public List blocks;
private const int INIT_LENGTH = 3;
public int Length
{
get
{
return length;
}
}
public Snake(Color _color, Direction _direction)
{
direction = _direction;
color = _color;
blocks = new List();
}
public void Creat(Graphics g, Color backGroundColor, int lawnWidth, int lawnHeight)
{
Clear(g, backGroundColor);
blocks.Clear();
length = INIT_LENGTH;
int x;
int y;
Random random = new Random();
x = random.Next(lawnWidth / 4, lawnWidth / 4 * 3) / Block.WIDTH * Block.WIDTH;
y = random.Next(lawnHeight / 4 - 1, lawnHeight / 4 * 3) / Block.HEIGHT * Block.HEIGHT;
blocks.Add(new SnakeBlock(x, y, color, true));
switch (direction)
{
case Direction.Up:
for (int i = 1; i < length; i++)
{
blocks.Add(new SnakeBlock(x, y + Block.HEIGHT * i, color, false));
}
break;
case Direction.Down:
for (int i = 1; i < length; i++)
{
blocks.Add(new SnakeBlock(x, y - Block.HEIGHT * i, color, false));
}
break;
case Direction.Left:
for (int i = 1; i < length; i++)
{
blocks.Add(new SnakeBlock(x + Block.WIDTH * i, y, color, false));
}
break;
case Direction.Right:
for (int i = 1; i < length; i++)
{
blocks.Add(new SnakeBlock(x - Block.WIDTH * i, y, color, false));
}
break;
}
Display(g);
}
public void Grow()
{
int x = 2 * blocks[blocks.Count - 1].Origion.X - blocks[blocks.Count - 2].Origion.X;
int y = 2 * blocks[blocks.Count - 1].Origion.Y - blocks[blocks.Count - 2].Origion.Y;
blocks.Insert(length, new SnakeBlock(x, y, color, false));
length++;
}
public void Move()
{
int x = 0;
int y = 0;
blocks[0].ChangeHeadToBody();
switch (direction)
{
case Direction.Up:
x = blocks[0].Origion.X;
y = blocks[0].Origion.Y - Block.HEIGHT;
break;
case Direction.Down:
x = blocks[0].Origion.X;
y = blocks[0].Origion.Y + Block.HEIGHT;
break;
case Direction.Left:
x = blocks[0].Origion.X - Block.WIDTH;
y = blocks[0].Origion.Y;
break;
case Direction.Right:
x = blocks[0].Origion.X + Block.WIDTH;
y = blocks[0].Origion.Y;
break;
}
blocks.Insert(0, new SnakeBlock(x, y, color, true));
blocks.RemoveAt(blocks.Count - 1);
}
public void Display(Graphics g)
{
for (int i = 0; i < length; i++)
{
blocks[i].Display(g, direction);
}
}
public void Clear(Graphics g, Color backGroundColor)
{
for (int i = 0; i < length; i++)
{
blocks[i].Clear(g, backGroundColor);
}
}
public void RemoveAfter(Graphics g,Color backGroundColor,int blockNum)
{
for (int i=length -1;i>blockNum -1;i--)
{
blocks[i].Clear (g,backGroundColor );
blocks.RemoveAt(i);
length =blockNum;
}
}
public bool CanEatBean(Bean bean)
{
if (blocks[0].Origion == bean.Origion)
return true;
else
return false;
}
public int CanEatSnake()
{
for (int i = 3; i < blocks.Count; i++)
{
if (blocks[0].Origion == blocks[i].Origion)
return i;
}
return 0;
}
public void EatBean(Bean bean, Graphics g, Color backGroundColor, int lawnWidth, int lawnHeight)
{
bean.Clear(g, backGroundColor);
Grow();
bean.Creat(g, backGroundColor, lawnWidth, lawnHeight, this);
}
public bool IsAlive(int lawnWidth, int lawnHeight)
{
if (blocks[0].Origion.X < 0)
return false;
if (blocks[0].Origion.Y < 0)
return false;
if (blocks[0].Origion.X + Block.WIDTH > lawnWidth)
return false;
if (blocks[0].Origion.Y + Block.HEIGHT > lawnHeight)
return false;
else
return true;
}
}
}
5)Game(游戏)类编码
Game控制游戏的运行,负责在游戏开始时生成Bean和Snake,以及负责在游戏运行中Snake的移动、Snake的生长、Bean的重生,并随时检测Snake的生死状态。Game类的参考代码如下:
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
namespace HungrySanke
{
class Game
{
public Snake snake;
public Bean bean;
public bool isSnakeAlive;
public int lawnWidth;
public int lawnHeight;
public Game(int _lawnWidth, int _lawnHeight)
{
Random random = new Random();
int x = random.Next(0, _lawnWidth - 1) / Block.WIDTH * Block.WIDTH;
int y = random.Next(0, _lawnHeight - 1) / Block.HEIGHT * Block.HEIGHT;
Direction direction = (Direction)random.Next(1, 4);
snake = new Snake(Color.YellowGreen, direction);
bean = new Bean(Color.Pink);
isSnakeAlive = false;
lawnWidth = _lawnWidth;
lawnHeight = _lawnHeight;
}
public void Begin(Graphics g, Color backGroundColor, int lawnWidth, int
lawnHeight)
{
isSnakeAlive = true;
snake.Clear(g, backGroundColor);
snake.Creat(g, backGroundColor, lawnWidth, lawnHeight);
bean.Creat(g, backGroundColor, lawnWidth, lawnHeight, snake);
}
public void OnTime(Graphics g, Color backGroundColor, int lawnWidth, int
lawnHeight)
{
if (isSnakeAlive)
{
snake.Clear(g, backGroundColor);
snake.Move();
snake.Display(g);
bean.Display(g);
if (snake.CanEatBean(bean))
{
bean.Clear(g, backGroundColor);
snake.EatBean(bean, g, backGroundColor, lawnWidth,
lawnHeight);
bean.Display(g);
}
int blockNum = snake.CanEatSnake();
if (blockNum > 0)
{
snake.RemoveAfter(g, backGroundColor, blockNum);
}
if (!snake.IsAlive(lawnWidth, lawnHeight))
isSnakeAlive = false;
}
}
}
}
Form1的设计代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace HungrySanke
{
public partial class Form1 : Form
{
private Game game;
public Form1()
{
InitializeComponent();
game = new Game(lawn.Width, lawn.Height);
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void timer1_Tick(object sender, EventArgs e)
{
if ( game.isSnakeAlive)
{
Graphics g;
g = lawn.CreateGraphics();
game.OnTime(g, lawn.BackColor, lawn.Width, lawn.Height);
if (!game.isSnakeAlive)
{
MessageBox.Show("Game Over");
}
}
}
private void ToolStrpMenuItemStart_Click(object sender, EventArgs e)
{
Graphics g;
g = lawn.CreateGraphics();
game.Begin(g, lawn.BackColor, lawn.Width, lawn.Height);
timer1.Enabled = true;
ToolStripMenuItemPause.Enabled = true;
ToolStripMenuItemContinue.Enabled = false;
}
private void ToolStripMenuItemPause_Click(object sender, EventArgs e)
{
timer1.Enabled = false ;
ToolStripMenuItemPause.Enabled = false ;
ToolStripMenuItemContinue.Enabled = true ;
}
private void ToolStripMenuItemCONTINUE_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
ToolStripMenuItemPause.Enabled = true;
ToolStripMenuItemContinue.Enabled = false;
}
private void Form1_KeyDown(object sender, KeyEventArgs e)
{
if (game.snake.direction == Direction.Down || game.snake.direction == Direction.Up)
{
switch (e.KeyCode)
{
case Keys.Left :
game.snake.direction = Direction.Left;
break ;
case Keys .Right :
game .snake .direction =Direction .Right ;
break ;
}
}
else
{
switch (e.KeyCode )
{
case Keys .Up:
game .snake .direction =Direction .Up;
break ;
case Keys .Down :
game .snake .direction =Direction .Down ;
break ;
}
}
}
private void lawn_Paint(object sender, PaintEventArgs e)
{
}
private void menuStrip1_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
{
}
private void ToolStripMenuItemStart_Click(object sender, EventArgs e)
{
Graphics g;
g = lawn.CreateGraphics();
game.Begin(g, lawn.BackColor, lawn.Width, lawn.Height);
timer1.Enabled = true;
ToolStripMenuItemPause.Enabled = true;
ToolStripMenuItemContinue.Enabled = false;
}
private void ToolStripMenuItemPause_Click_1(object sender, EventArgs e)
{
timer1.Enabled = false;
ToolStripMenuItemPause.Enabled = false;
ToolStripMenuItemContinue.Enabled = true;
}
private void ToolStripMenuItemContinue_Click_1(object sender, EventArgs e)
{
timer1.Enabled = true;
ToolStripMenuItemPause.Enabled = true;
ToolStripMenuItemContinue.Enabled = false;
}
}
}
7. 测试报告
测试用例;
1)、Bean 的生成、消除与显示
Bean在游戏开始时,能生成一颗豆且能在游戏运行中,正常显示,能在豆被蛇吃掉时,消除原先的豆,并重新生成一颗豆。
Snake 的生成、显示、移动、生长与死亡
在游戏开始时,生成一条蛇并能在游戏运行中,正常显示一条蛇的运动。蛇能在游戏运行中,根据用户的按键情况,改变蛇的移动方向。能在蛇吃掉豆时,生长一节。
当蛇头碰到蛇尾或者蛇身的时候,后面的部分将被剪断不再显示,而且能在蛇头碰到场地边界时死亡,并结束游戏。
测试结果
当游戏运行时,游戏能正常运行!
计算机实习报告姓名:班级:学号:小班序号:指导老师:题目:贪吃蛇(运行环境:visual,studio2010)邮箱:题目贪吃蛇实…
实验报告课程名称:Windows程序设计实验名称:贪吃蛇设计成员:##专业年级:20##级软件工程填写时间:20##/12/24贪…
C语言程序设计实训报告姓名专业班级指导教师20##年7月14日目录1实训的目的和要求.11.1实训的目的.11.2实训的要求.12…
三实验步骤1编程环境的选择本程序采用MicrosoftVisualC60的英文版本进行编译VisualC60是Microsoft公…
20xx年计算机实习报告计算机实习报告姓名向睿班级07班学号10210197小班序号11指导老师方莉题目贪吃蛇邮箱hgjngh12…
程序设计基础课程设计C课程设计报告贪吃蛇院系:计算机学院网络工程系班级:122班姓名:指导教师:20##年12月25日程序设计基础…
贪吃蛇游戏C程序设计报告目录一设计要求2二设计的作用目的2三课题分析21贪吃蛇游戏功能分析22游戏界面分析33设计思路分析3四设计…
贪吃蛇游戏C程序设计报告目录一设计要求2二设计的作用目的2三课题分析21贪吃蛇游戏功能分析22游戏界面分析33设计思路分析3四设计…
目录一软件设计要求和规范2二软件制作过程2三收获和体会13参考文献13一软件设计要求和规范11设计要求通过游戏程序设计提高编程兴趣…
前言Java最初被命名为Oak目标设定在家用电器等小型系统的编程语言来解决诸如电视机电话闹钟烤面包机等家用电器的控制和通讯问题由于…
电子与信息工程系开放性实验报告JAVA程序设计开放性实验报告专业班级学号姓名实验报告实验2贪吃蛇游戏设计4学时1实验内容1创建软件…