贪吃蛇游戏实验报告

计算机实习报告

姓名:

班级:

学号:

小班序号:

指导老师:

题目:贪吃蛇(运行环境: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;

        }

    }

}

5Game(游戏)类编码

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 的生成、显示、移动、生长与死亡

在游戏开始时,生成一条蛇并能在游戏运行中,正常显示一条蛇的运动。蛇能在游戏运行中,根据用户的按键情况,改变蛇的移动方向。能在蛇吃掉豆时,生长一节。

当蛇头碰到蛇尾或者蛇身的时候,后面的部分将被剪断不再显示,而且能在蛇头碰到场地边界时死亡,并结束游戏。

测试结果

当游戏运行时,游戏能正常运行!

相关推荐