C#实现贪吃蛇小游戏

作者:笔下无书生 时间:2022-09-28 17:17:59 

本文实例为大家分享了C#实现贪吃蛇小游戏的具体代码,供大家参考,具体内容如下

之前一直想写一个贪吃蛇小游戏,上个周末终于有时间做了一个,现在和大家分享。

界面

界面比较简单,一个按钮和一个积分器组成。
基本逻辑:每五个食物出现一次大食物,小食物1分,大食物5分。
控制:撞墙和缠绕时,游戏暂停。

C#实现贪吃蛇小游戏

代码详解

详细介绍下代码

一、代码分详解

1.界面是在pc上,所以移动以上下左右键来控制移动,为了及时响应,所以增加如下代码

protected override bool ProcessDialogKey(Keys keyData)
        {
            //遇到上下左右键 就自定义处理
            if (keyData == Keys.Up || keyData == Keys.Down ||
            keyData == Keys.Left || keyData == Keys.Right)
                return false;
            else
                return base.ProcessDialogKey(keyData);
        }

2.做个枚举,来标记某个时间状态下蛇的移动方向,配合键盘按键

/// <summary>
/// 方向枚举
/// </summary>
    public enum SnakeDirection
    {
        Left,
        Right,
        Down,
        Up
    }
            /// <summary>
        /// 键盘和鼠标按下时 处理 但必须有控件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void SnakeForm_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Up)
            {
                Snake.Sd = SnakeDirection.Up;
            }
            else if (e.KeyCode == Keys.Down)
            {
                Snake.Sd = SnakeDirection.Down;
            }
            else if (e.KeyCode == Keys.Left)
            {
                Snake.Sd = SnakeDirection.Left;
            }
            else if (e.KeyCode == Keys.Right)
            {
                Snake.Sd = SnakeDirection.Right;
            }
        }

3.声明一个蛇的类,存储所有蛇的相关信息,如所有蛇身体的节点位置

public class Snake

主要变量如下

public static SnakeDirection Sd;//蛇进行的方向 上下左右四个方向
public int Location_X;//0为x,1为y 蛇的初始位置
public int Location_Y;
public static List<Snake> Snakebody = new List<Snake>();//蛇身子的具体位置,每次位移都刷新一次 整个蛇身子的所有位置  最后一位是蛇头 
public static int width = 10, height = 10;
public static int CurScore = 1;//当前食物的分数
public static int AllScore = -1;//总分数
public static int MaxScore = 5;//大分出现频次

4.声明一个食物的类,同时增加一个方法,随机在界面上的一个位置显示食物

public class Food
    {
        public int Food_Location_X;
        public int Food_Location_Y;
        public Food()
        {
            Random x = new Random();
            Random y = new Random();
            Food_Location_X = x.Next(0, 49) * 10;//随机点出现食物
            Food_Location_Y = y.Next(0, 49) * 10;//随机点出现食物
        }
    }

5.点击开始按钮,触发开始相关方法,主要是启动刷新的时间器,初始化食物位置,初始化积分等

public  void refreshScore()
        {
            Snake.AllScore = Snake.AllScore+ Snake.CurScore;
           this.SnakeScore.Text = Convert.ToString(Snake.AllScore);
        }
        private int FoodX = 0;//食物X轴
        private int FoodY = 0;//食物Y轴

        private void BeginBtn_Click(object sender, EventArgs e)
        {
            Snake.Start();//创建蛇
            CreateNewFood();
            StartTimer.Start();
            StartTimer.Interval = 100;//毫秒刷新一次
        }

6.定时器启动后,定时刷新,我这边设置的是100毫秒,也可以做一个前端设置按钮,增加游戏趣味性,同时也可以设置根据不同的积分处理此设置

定时器中有画蛇身体的方法、随机一个食物位置的方法、蛇移动的方法、蛇是否吃到食物的方法、游戏有没有结束的方法

/// <summary>
/// 开始的定时器
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
        private void StartTimer_Tick(object sender, EventArgs e)
        {
            DrawSnake();
            DrawFood();

            Snake.Move(Snake.Sd);//蛇移动 移动的方向键盘控制
            EatFood();
            IsOrNotGameOver();
           
        }

7.画蛇的方法如下

/// <summary>
/// 画蛇
/// </summary>
        public void DrawSnake()
        {
            RectangleF[] rectangles = new RectangleF[Snake.Snakebody.Count];

            int num;
            for (num = 0; num < Snake.Snakebody.Count; num++)
            {
                rectangles[num] = new RectangleF(Snake.Snakebody[num].Location_X,
                    Snake.Snakebody[num].Location_Y, Snake.width, Snake.height);
            }
            this.Refresh();

            Graphics g = this.Snake_Panel.CreateGraphics();
            SolidBrush myBrush = new SolidBrush(Color.Black);
            g.FillRectangles(myBrush, rectangles);
        }

8.食物显示的方法如下,其中MaxScore表示小食物出现的次数,每出现一次此值减一,当为0时,食物变为大食物。

/// <summary>
/// 食物的位置
/// </summary>
        public void DrawFood()
        {
            Graphics f = this.Snake_Panel.CreateGraphics();
            SolidBrush mybrush = new SolidBrush(Color.Red);
          
            if (Snake.MaxScore==0)
            {
                f.FillRectangle(mybrush, FoodX, FoodY, 20, 20);//随机了食物的位置
            }
            else
            {
                f.FillRectangle(mybrush, FoodX, FoodY, 10, 10);//随机了食物的位置
            }
        }

9.当每次刷新时,蛇都会移动,相应的蛇整体的位置也会发生变化,但蛇身有痕迹,所以使用如下方式进行蛇体变化

//蛇的移动操作 每次移动 都需要改变蛇身体
public static void Move(SnakeDirection Sd)
            {
                int i = Snakebody.Count - 1;//根据不同的移动方向 需要对相对位置发生变化,这个操作保证蛇身按照蛇头的轨迹运转
                switch (Sd)
                {
                    case SnakeDirection.Up:
                        ChangeSnakeLine();
                        Snakebody[i].Location_Y -= 10;
                        break;
                    case SnakeDirection.Left:
                        ChangeSnakeLine();
                        Snakebody[i].Location_X -= 10;
                        break;
                    case SnakeDirection.Down:
                        ChangeSnakeLine();
                        Snakebody[i].Location_Y += 10;
                        break;
                    case SnakeDirection.Right:
                        ChangeSnakeLine();
                        Snakebody[i].Location_X += 10;
                        break;
                }
            }
            /// <summary>
            /// 每次移动一次 改变蛇身体的相对位置
            /// </summary>
            public static void ChangeSnakeLine()
            {
                int j = 0;
                int x, y;
                int i = Snakebody.Count - 1;
                for (j = 0; j < i; j++)//蛇 1位置变为蛇0  2=》1  3=》2
                {
                    x = Snakebody[j + 1].Location_X;
                    y = Snakebody[j + 1].Location_Y;
                    Snakebody[j].Location_Y = y;
                    Snakebody[j].Location_X = x;
                }
            }

10.刷新蛇身体后,要判断食物位置是否和蛇头碰撞,当发生碰撞时,表示蛇吃掉了食物,食物刷新,蛇身体增长

/// <summary>
/// 吃掉食物 判断蛇头位置和食物位置相同时,食物重新刷新
/// </summary>
        public void EatFood()
        {
            if (Snake.Snakebody[Snake.Snakebody.Count - 1].Location_X == FoodX
                && Snake.Snakebody[Snake.Snakebody.Count - 1].Location_Y == FoodY)
            {
                Snake.AddBody();//增加 蛇身增加
                //吃掉食物之后 随机创建一个新的食物
                CreateNewFood();
            }
        }
                    //吃一个节点 变为新的蛇头
            public static void AddBody()
            {
                Snake S_eat = new Snake();
                int xx = Snakebody[Snakebody.Count - 1].Location_X;
                int yy = Snakebody[Snakebody.Count - 1].Location_Y;
                switch (Sd)
                {
                    case SnakeDirection.Up:
                        S_eat.Location_Y = yy - 10;
                        S_eat.Location_X = xx;
                        Snakebody.Add(S_eat);
                        break;
                    case SnakeDirection.Left:
                        S_eat.Location_X = xx - 10;
                        S_eat.Location_Y = yy;
                        Snakebody.Add(S_eat);
                        break;
                    case SnakeDirection.Down:
                        S_eat.Location_Y = yy + 10;
                        S_eat.Location_X = xx;
                        Snakebody.Add(S_eat);
                        break;
                    case SnakeDirection.Right:
                        S_eat.Location_Y = yy;
                        S_eat.Location_X = xx + 10;
                        Snakebody.Add(S_eat);
                        break;
                }
            }

11.食物被吃掉后,食物刷新,同时判断小食物出现的次数

/// </summary>
public void CreateNewFood()
        {
            refreshScore();
            bool IsCreate = false;
            while (!IsCreate)//是否创建成功
            {
                Food NewFood = new Food();
                FoodX = NewFood.Food_Location_X;
                FoodY = NewFood.Food_Location_Y;
                //判断这个不会出现在蛇身上
                IsCreate = true;//创建成功
                for (int i = 0; i < Snake.Snakebody.Count; i++)
                {
                    if (Snake.Snakebody[i].Location_X == FoodX && Snake.Snakebody[i].Location_Y == FoodY)//当坐标相同 终止for 未创建成功
                    {
                        IsCreate = false;
                        break;
                    }
                }
                if (IsCreate)
                {
                    if (!(FoodX <= this.Snake_Panel.Width-10 && FoodX >= 10 && FoodY <= this.Snake_Panel.Height-10 && FoodY >= 10))//食物不在范围内 重新刷新
                    {
                        IsCreate = false;
                    }
                }
                if (IsCreate)
                {
                    if (Snake.Snakebody.Count != 4)
                    {
                        Snake.MaxScore--;//不是第一次创建食物时
                    }
                    Snake.CurScore = 1;//当前小节点的分数
                    if (Snake.MaxScore == 0)
                    {
                        Snake.CurScore = 5;//当前小节点的分数
                    }
                    else if (Snake.MaxScore<0)
                    {
                        Snake.MaxScore = 5;//初始化次数
                    }
                }
                
            }
        }

12.每次定时器刷新,蛇身会发生变化,同时就需要判断蛇是否触发终止规则
蛇身体缠绕,蛇头碰壁表示游戏终止

/// <summary>
/// 
/// </summary>
public void IsOrNotGameOver()
        {
            int x = Snake.Snakebody[Snake.Snakebody.Count - 1].Location_X;
            int y = Snake.Snakebody[Snake.Snakebody.Count - 1].Location_Y;
            bool IsGameOver = false;
            if (!(x <= this.Snake_Panel.Width && x >= 0 && y <= this.Snake_Panel.Height && y >= 0))//蛇头碰触到边框
            {
                IsGameOver = true;
            }
            //蛇头碰到自己蛇身
            for(int i=0;i< Snake.Snakebody.Count - 2; i++)
            {
                if(Snake.Snakebody[i].Location_X==x&& Snake.Snakebody[i].Location_Y == y)
                {
                    IsGameOver = true;
                    break;
                }
            }

            if (IsGameOver)
            {
                GameOver();
                StartTimer.Stop();
            }
        }

来源:https://blog.csdn.net/weixin_45005931/article/details/109446742

标签:C#,贪吃蛇
0
投稿

猜你喜欢

  • Java异常处理try catch的基本使用

    2023-11-24 05:04:38
  • Druid基本配置及内置监控使用_动力节点Java学院整理

    2022-12-16 20:55:58
  • SpringCloud可视化链路追踪系统Zipkin部署过程

    2023-11-27 04:34:06
  • Android 动态加载二维码视图生成快照的示例

    2023-08-04 19:57:54
  • Android自定义View控件实现刷新效果

    2022-05-12 14:43:22
  • C#中神器类BlockingCollection的实现详解

    2022-10-13 07:41:02
  • java并发编程包JUC线程同步CyclicBarrier语法示例

    2023-01-18 07:44:58
  • Mybatis-Plus 条件构造器 QueryWrapper 的基本用法

    2022-07-07 13:28:18
  • Android Retrofit文件下载进度显示问题的解决方法

    2021-09-23 20:24:10
  • Java利用POI读取、写入Excel的方法指南

    2023-11-23 15:39:23
  • Android实现仿Windows7图片预览窗格效果

    2022-10-14 01:48:04
  • SpringMVC中使用Thymeleaf模板引擎实例代码

    2021-10-20 20:03:44
  • Android中实现iOS中的毛玻璃效果

    2023-01-27 01:44:14
  • Java集合中的fail-fast(快速失败)机制详解

    2023-05-10 16:31:33
  • Android 实现调用系统照相机拍照和录像的功能

    2021-12-05 10:58:51
  • Android使用Sensor感应器实现线程中刷新UI创建android测力计的功能

    2023-03-05 07:51:48
  • C#实现鼠标移动到曲线图上显示值的方法

    2023-06-01 00:56:06
  • Java分析讲解序列化与字典功能的序列化

    2021-11-12 11:19:25
  • maven基础教程——简单了解maven的特点与功能

    2023-09-07 03:43:02
  • JAVASE系统实现抽卡功能

    2023-11-19 19:49:41
  • asp之家 软件编程 m.aspxhome.com