首页 > 编程 > C# > 正文

C#贪吃蛇游戏实现分析

2019-10-29 21:10:03
字体:
来源:转载
供稿:网友

今天无聊突发奇想做个贪吃蛇,虽然网上很多这东西了,不过自己写的感觉还行吧

贪吃蛇分析

游戏规则:

1、蛇起始长度5,每吃一个食物增加1,最大15过关

2、蛇用蓝色表示,食物用绿色,障碍物用黑色

3、当蛇碰到自己、墙壁、障碍物则游戏失败

4、方向键控制蛇的移动方向,蛇不可反方向移动,如正在向上移动,不能马上向下,只能向左、右、上运动

5、每过关一次速度提升一次

大概思路:

1、地图用网格的形式表示,蛇由方格组成,保存在list中

2、1中提到了方格,方格保存的内容有,颜色,坐标,是否可以通过,是否是食物

3、向前移动一次,将前面方格添加进蛇列表中,将列表最后一个移除,若为前方格子为食物,则不移除最后一个

4、使用while死循环来做整个移动

5、空格键为加速键,通过修改while循环sleep时间来实现加速

包括了3个类一个主窗体,分别是Node(用来表示方格)、Map(用来表示地图)、Serpent(用来表示蛇),另外一个主窗体。下面依次把代码贴上,基本上每个方法都有注释

代码1:

using System;using System.Collections.Generic;using System.Text;using System.Drawing;namespace EngorgeSerpent{ /// <summary> /// 节点 /// </summary> class Node { #region 字段 private int x; private int y; private int width = 10; private bool isFood = false; private bool isPass = true;//是否可通过 private Color bgColor = Color.FromArgb(224, 224, 224); private Color foodColor = Color.Green; private Color hinderColor = Color.Black; private Color thisColor; private Color serpentColor = Color.Chocolate; #endregion /// <summary> /// 设置食物参数 /// </summary> /// <param name="_isFood"></param> public void SetFood(bool _isFood) {  IsFood = _isFood;  if (_isFood)  {  ThisColor = FoodColor;  }  else  {  ThisColor = BgColor;  } } /// <summary> /// 设置障碍物参数 /// </summary> /// <param name="_isHinder">是否为障碍物</param> public void SetHinder(bool _isHinder) {  IsPass =! _isHinder;  if (_isHinder)  {  ThisColor = HinderColor;  }  else  {  ThisColor = BgColor;  } } /// <summary> /// 设置蛇颜色 /// </summary> /// <param name="_isSerpent"></param> public void SetSerpent(bool _isSerpent) {  IsPass = !_isSerpent;  if (_isSerpent)  {  ThisColor = SerpentColor;  }  else  {  ThisColor = BgColor;  } } #region 构造函数 public Node() {  thisColor = bgColor; } /// <summary> /// 有参构造方法 /// </summary> /// <param name="_x">相对x坐标</param> /// <param name="_y">相对y坐标</param> /// <param name="_width">边长</param> /// <param name="_isFood">是否是食物</param> /// <param name="_isPass">是否可通过</param> public Node(int _x, int _y, int _width, bool _isFood, bool _isPass) {  thisColor = bgColor;  X = _x;  Y = _y;  Width = _width;  IsFood = _isFood;  IsPass = _isPass; } /// <summary> /// 有参构造方法 /// </summary> /// <param name="_x">相对x坐标</param> /// <param name="_y">相对y坐标</param> /// <param name="_width">边长</param> public Node(int _x, int _y, int _width) {  X = _x;  Y = _y;  Width = _width; } /// <summary> /// 有参构造方法 /// </summary> /// <param name="_x">相对x坐标</param> /// <param name="_y">相对y坐标</param> public Node(int _x, int _y) {  X = _x;  Y = _y; } #endregion #region 属性 /// <summary> /// 蛇颜色 /// </summary> public Color SerpentColor {  get { return serpentColor; } } /// <summary> /// 背景色 /// </summary> public Color BgColor {  get { return bgColor; } } /// <summary> /// 食物颜色 /// </summary> public Color FoodColor {  get { return foodColor; } } /// <summary> /// 障碍物颜色 /// </summary> public Color HinderColor {  get { return hinderColor; } } /// <summary> /// 当前颜色 /// </summary> public Color ThisColor {  get { return thisColor; }  set { thisColor = value; } } /// <summary> /// 获取或设置相对横坐标 /// </summary> public int X {  get { return x; }  set { x = value; } } /// <summary> /// 获取或设置相对纵坐标 /// </summary> public int Y {  get { return y; }  set { y = value; } } /// <summary> /// 获取或设置节点边长 /// </summary> public int Width {  get { return width; }  set { width = value; } } /// <summary> /// 获取或设置是否为食物 /// </summary> public bool IsFood {  get { return isFood; }  set { isFood = value; } } /// <summary> /// 获取或设置是否可以通过 /// </summary> public bool IsPass {  get { return isPass; }  set { isPass = value; } } #endregion }}

代码2:

using System;using System.Collections.Generic;using System.Text;using System.Drawing;namespace EngorgeSerpent{ /// <summary> /// 地图 /// </summary> class Map { /// <summary> /// 节点数组 /// </summary> private List<List<Node>> _nodes; private int RowCount; private int ComsCount; private Color bgColor = Color.FromArgb(224, 224, 224); private System.Windows.Forms.Control MapPanel; Graphics g; /// <summary> /// 地图背景色 和node中背景色一致 /// </summary> public Color BgColor {  get { return bgColor; } } /// <summary> /// 构造方法 /// </summary> /// <param name="rows">行数</param> /// <param name="coms">列数</param> public Map(int rows, int coms, System.Windows.Forms.Control c) {  RowCount = rows;  ComsCount = coms;  MapPanel = c;  g = c.CreateGraphics();  _nodes = new List<List<Node>>();  for (int i = 0; i < rows; i++)//行  {  List<Node> index = new List<Node>();  for (int j = 0; j < coms; j++)  {   Node node = new Node(j, i);   index.Add(node);  }  _nodes.Add(index);  } } /// <summary> /// 构造方法 /// </summary> /// <param name="rows">行数</param> /// <param name="coms">列数</param> /// <param name="width">节点宽度</param>  public Map(int rows, int coms, int width, System.Windows.Forms.Control c) {  RowCount = rows;  ComsCount = coms;  MapPanel = c;  g = c.CreateGraphics();  _nodes = new List<List<Node>>();  for (int i = 0; i < coms; i++)//行  {  List<Node> index = new List<Node>();  for (int j = 0; j < rows; j++)  {   Node node = new Node(j, i, width);   index.Add(node);  }  _nodes.Add(index);  } } /// <summary> /// 重新加载地图 /// </summary> public void ResetMap() {  for (int i = 0; i < ComsCount; i++)//行  {  for (int j = 0; j < RowCount; j++)  {   Node node = GetNode(i, j);   node.IsPass = true;   node.IsFood = false;    }  } } /// <summary> /// 获得节点 /// </summary> /// <param name="x"></param> /// <param name="y"></param> /// <returns></returns> public Node GetNode(int x, int y) {  return _nodes[y][x]; } /// <summary> /// 设置食物 /// </summary> public void SetFood() {  SolidBrush brush = null;  int _x, _y;  Random r = new Random();  while (true)  {  _x = r.Next(0, RowCount);  _y = r.Next(0, ComsCount);  if (_nodes[_x][_y].IsPass)  {   break;  }  }  Node nodeindex = _nodes[_x][_y];  nodeindex.SetFood(true);  brush = new SolidBrush(nodeindex.FoodColor);  RectangleF[] rects = { new RectangleF(nodeindex.X * nodeindex.Width, nodeindex.Y * nodeindex.Width, nodeindex.Width, nodeindex.Width) };  g.FillRectangles(brush, rects); } /// <summary> /// 设置障碍物 /// </summary> /// <param name="list"></param> public void SetHinder(List<Node> list) {  SolidBrush brush = null;  RectangleF[] rects = new RectangleF[list.Count];  for (int i = 0; i < list.Count; i++)  {  Node _node = list[i];  _node.SetHinder(true);  _node.IsPass = false;  if (brush == null)  {   brush = new SolidBrush(_node.HinderColor);  }  RectangleF r = new RectangleF(_node.X * _node.Width, _node.Y * _node.Width, _node.Width, _node.Width);  rects[i] = r;  }  g.FillRectangles(brush, rects); } /// <summary> /// 设置边界 /// </summary> public void SetBorder() {  //通过计算得出边界的个数是2(x+y-2)个方格  SolidBrush brush = null;  int borders = 2 * (ComsCount + RowCount - 2);  RectangleF[] rects = new RectangleF[borders];  int indexcount = 0;  //添加顶部方格进rects列表中  for (int i = 0; i < RowCount; i++)  {  Node _node = _nodes[i][0];  _node.SetHinder(true);  if (brush == null)  {   brush = new SolidBrush(_node.HinderColor);  }  RectangleF r = new RectangleF(_node.X * _node.Width, _node.Y * _node.Width, _node.Width, _node.Width);  rects[indexcount] = r;  indexcount++;  }  //添加底部方格进rects列表中  for (int i = 0; i < RowCount; i++)  {  Node _node = _nodes[i][ComsCount - 1];  _node.SetHinder(true);  RectangleF r = new RectangleF(_node.X * _node.Width, _node.Y * _node.Width, _node.Width, _node.Width);  rects[indexcount] = r;  indexcount++;  }  //添加左侧方格进列表,因为左侧最上面以及最下面的两个方格已经添加进去,这里不需要重复添加  for (int i = 1; i < ComsCount - 1; i++)  {  Node _node = _nodes[0][i];  _node.SetHinder(true);  RectangleF r = new RectangleF(_node.X * _node.Width, _node.Y * _node.Width, _node.Width, _node.Width);  rects[indexcount] = r;  indexcount++;  }  //添加右侧方格进列表,因为右侧最上面以及最下面两个方格已经添加进去,这里不需要重复添加  for (int i = 1; i < ComsCount - 1; i++)  {  Node _node = _nodes[RowCount - 1][i];  _node.SetHinder(true);  RectangleF r = new RectangleF(_node.X * _node.Width, _node.Y * _node.Width, _node.Width, _node.Width);  rects[indexcount] = r;  indexcount++;  }  g.FillRectangles(brush, rects); } }}

代码3:

using System;using System.Collections.Generic;using System.Text;using System.Drawing;namespace EngorgeSerpent{ /// <summary> /// 蛇 /// </summary> class Serpent { private List<Node> serpentList = new List<Node>(); private Direction direction = Direction.Right;//运动方向 private int maxCount = 15; private int minCount = 5; private System.Windows.Forms.Control MapPanel; Graphics g; /// <summary> /// 设置蛇长度数据 /// </summary> /// <param name="maxLength">最大长度</param> /// <param name="minLength">最小长度</param> public Serpent(int maxLength, int minLength, System.Windows.Forms.Control c) {  maxCount = maxLength;  minCount = minLength;  MapPanel = c;  g = MapPanel.CreateGraphics(); } /// <summary> /// 初始化蛇 /// </summary> public void InitializeSerpent() {  SolidBrush brush = null;  RectangleF[] rects = new RectangleF[minCount];  for (int i = 1; i < minCount; i++)  {  Node indexnode = new Node(i, 1);  indexnode.SetSerpent(true);//设置蛇颜色  serpentList.Insert(0, indexnode);  if (brush == null)  {   brush = new SolidBrush(indexnode.SerpentColor);  }  rects[i] = new RectangleF(indexnode.X * indexnode.Width, indexnode.Y * indexnode.Width, indexnode.Width, indexnode.Width);  }  g.FillRectangles(brush, rects); } /// <summary> /// 插入一个 /// </summary> /// <param name="node"></param> public void InsertNode(Node node) {  serpentList.Insert(0, node);  node.SetSerpent(true);  SolidBrush brush = new SolidBrush(node.SerpentColor);  RectangleF rect = new RectangleF(node.X * node.Width, node.Y * node.Width, node.Width, node.Width);  g.FillRectangle(brush, rect); } /// <summary> /// 移除尾巴 /// </summary> /// <param name="node"></param> public void RemoveNode() {  Node node = serpentList[serpentList.Count - 1];  serpentList.Remove(node);  node.SetSerpent(false);  SolidBrush brush = new SolidBrush(node.BgColor);  RectangleF rect = new RectangleF(node.X * node.Width, node.Y * node.Width, node.Width, node.Width);  g.FillRectangle(brush, rect); } /// <summary> /// 获取蛇头 /// </summary> /// <returns>蛇头方格</returns> public Node GetSerpentHead() {  return serpentList[0]; } /// <summary> /// 蛇是否最长 /// </summary> /// <returns></returns> public bool IsMax() {  if (serpentList.Count == maxCount)  return true;  else  return false; } /// <summary> /// 蛇运动方向 /// </summary> public Direction Direction {  get { return direction; }  set { direction = value; } } } /// <summary> /// 运动方向 /// </summary> public enum Direction { Left, Up, Right, Down }}

代码4:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Threading;namespace EngorgeSerpent{ public partial class MainForm : Form { public MainForm() {  InitializeComponent(); } List<List<Node>> maplist = new List<List<Node>>(); Map map; Serpent serpent; Graphics g; int level = 1; /// <summary> /// 运行线程 /// </summary> Thread Work_Thread = null; /// <summary> /// 运行线程监控值 /// </summary> bool IsWork = false; int sleepTime = 1000; int thissleeptime; private void MainForm_Load(object sender, EventArgs e) {  g = this.panel1.CreateGraphics();  map = new Map(40, 30, this.panel1);//这里可以对画布进行下大小设置 此处偷懒省略   LoadMapList();//加载障碍物列表   } /// <summary> /// 默认将地图设置为30*40 /// </summary> private void SetMap() {  map.ResetMap();  g.Clear(map.BgColor);  map.SetBorder();//设置边界  List<Node> hiderList = GetHider();//获取障碍物列表  map.SetHinder(hiderList);//设置障碍物  SetSerpent();//初始化蛇  } /// <summary> /// 设置蛇 /// </summary> private void SetSerpent() {  serpent = new Serpent(15, 5, this.panel1);  serpent.InitializeSerpent();//初始化蛇 } /// <summary> /// 获取地图障碍物列表 以增加不同级别难度 /// </summary> private void LoadMapList() {  //目前分为5个级别  //第一级别  List<Node> hiderList1 = new List<Node>();  for (int i = 15; i < 25; i++)  {  hiderList1.Add(map.GetNode(i, 15));  hiderList1.Add(map.GetNode(15, i));  }  maplist.Add(hiderList1);  //第二级别  List<Node> hiderList2 = new List<Node>();  for (int i = 7; i < 25; i++)  {  hiderList2.Add(map.GetNode(i, 15));  hiderList2.Add(map.GetNode(15, i));  }  maplist.Add(hiderList2);  //第三级别  List<Node> hiderList3 = new List<Node>();  for (int i = 7; i < 25; i++)  {  hiderList3.Add(map.GetNode(i, 15));  hiderList3.Add(map.GetNode(15, i));  hiderList3.Add(map.GetNode(i, 25));  }  maplist.Add(hiderList3);  //第四级别  List<Node> hiderList4 = new List<Node>();  for (int i = 7; i < 25; i++)  {  hiderList4.Add(map.GetNode(i, 25));  hiderList4.Add(map.GetNode(i, 15));  hiderList4.Add(map.GetNode(15, i));  hiderList4.Add(map.GetNode(i, 7));  }  maplist.Add(hiderList4);  //第五级别  List<Node> hiderList5 = new List<Node>();  for (int i = 7; i < 25; i++)  {  hiderList5.Add(map.GetNode(i, 25));  hiderList5.Add(map.GetNode(i, 15));  hiderList5.Add(map.GetNode(15, i));  hiderList5.Add(map.GetNode(i, 7));  hiderList5.Add(map.GetNode(i, 35));  }  for (int i = 12; i < 20; i++)  {  hiderList5.Add(map.GetNode(7, i));  hiderList5.Add(map.GetNode(25, i));  }  maplist.Add(hiderList5); } /// <summary> /// 获取障碍物列表 /// </summary> /// <returns></returns> private List<Node> GetHider() {  //这里可以添加多个地图,当级别改变时需要重新加载  return maplist[level - 1]; } /// <summary> /// 重置地图 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnResetMap_Click(object sender, EventArgs e) {  IsWork = false;  btnStop.Enabled = false;  button3.Enabled = false;  button2.Enabled = true;  //map.ResetMap();  SetMap(); } /// <summary> /// 运行 /// </summary> private void Work() {  map.SetFood();//设置食物  while (IsWork)  {  Node node_index;  Node serpentHead = serpent.GetSerpentHead();  switch (serpent.Direction)  {   case Direction.Left:   node_index = map.GetNode(serpentHead.X - 1, serpentHead.Y);   break;   case Direction.Right:   node_index = map.GetNode(serpentHead.X + 1, serpentHead.Y);   break;   case Direction.Up:   node_index = map.GetNode(serpentHead.X, serpentHead.Y - 1); break;   default:   node_index = map.GetNode(serpentHead.X, serpentHead.Y + 1);   break;  }  SerpentState index_move = SerpentMove(node_index);  if (index_move == SerpentState.Error)//游戏结束  {   IsWork = false;   //map.ResetMap();   MessageBox.Show("游戏结束!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);   sleepTime = 1000;   level = 1;   thissleeptime = sleepTime;   lblLevel.BeginInvoke(new MethodInvoker(delegate()   {   btnStop.Enabled = false;   button3.Enabled = false;   button2.Enabled = true;   lblLevel.Text = "1";   lblCount.Text = "5";   }));  }  else if (index_move == SerpentState.NextLevel)  {   IsWork = false;   this.lblCount.BeginInvoke(new MethodInvoker(delegate()   {   level += 1;   lblLevel.Text = level.ToString();   lblCount.Text = "5";   }));   sleepTime = sleepTime / 2;   thissleeptime = sleepTime;   SetMap();//重置地图  }  else  {   Thread.Sleep(thissleeptime);  }  }  map.ResetMap(); } /// <summary> /// 开始 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button2_Click(object sender, EventArgs e) {  IsWork = false;  btnStop.Enabled = false;  button3.Enabled = false;  button2.Enabled = true;  //map.ResetMap();  SetMap();  thissleeptime = sleepTime;  this.panel1.Focus();  IsWork = true;  this.btnStop.Enabled = true;  this.button3.Enabled = true;  button2.Enabled = false;  Work_Thread = new Thread(new ThreadStart(Work));  Work_Thread.IsBackground = true;  Work_Thread.Start(); } private void MainForm_KeyDown(object sender, KeyEventArgs e) {  if (e.KeyCode == Keys.Right)  {  if (serpent.Direction != Direction.Left)   serpent.Direction = Direction.Right;  }  else if (e.KeyCode == Keys.Left)  {  if (serpent.Direction != Direction.Right)   serpent.Direction = Direction.Left;  }  else if (e.KeyCode == Keys.Up)  {  if (serpent.Direction != Direction.Down)   serpent.Direction = Direction.Up;  }  else if (e.KeyCode == Keys.Down)  {  if (serpent.Direction != Direction.Up)   serpent.Direction = Direction.Down;  }  else if (e.KeyCode == Keys.Space)  {  thissleeptime = sleepTime / 2;  }  else if (e.KeyCode == Keys.Escape)  {  if (IsWork)  {   this.button3.Text = "继续";   IsWork = false;  }  } } /// <summary> /// 暂停 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button3_Click(object sender, EventArgs e) {  if (!IsWork)  {  this.button3.Text = "暂停";  IsWork = true;  Work_Thread = new Thread(new ThreadStart(Work));  Work_Thread.IsBackground = true;  Work_Thread.Start();  }  else  {  this.button3.Text = "继续";  IsWork = false;  } } /// <summary> /// 退出 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void button4_Click(object sender, EventArgs e) {  this.Close(); } private void MainForm_FormClosing(object sender, FormClosingEventArgs e) {  IsWork = false;  Application.Exit();  System.Diagnostics.Process.GetCurrentProcess().Kill(); } private void btnStop_Click(object sender, EventArgs e) {  // map.ResetMap();  btnStop.Enabled = false;  button3.Enabled = false;  button2.Enabled = true;  IsWork = false;  Work_Thread.Abort();  SetMap(); } /// <summary> /// 移动 /// </summary> /// <param name="node">将要移动到的节点</param> /// <returns>返回状态</returns> private SerpentState SerpentMove(Node node) {  if (!node.IsPass)  {  return SerpentState.Error;  }  serpent.InsertNode(node);  if (!node.IsFood)  {  //不是食物,则移除最后一个节点  serpent.RemoveNode();  }  else  {  lblCount.BeginInvoke(new MethodInvoker(delegate()  {   this.lblCount.Text = (Convert.ToInt32(this.lblCount.Text.Trim()) + 1).ToString();  }));  map.SetFood();//设置食物  }  if (serpent.IsMax())  {  return SerpentState.NextLevel;  }  return SerpentState.Moving; } private void MainForm_KeyUp(object sender, KeyEventArgs e) {  if (e.KeyCode == Keys.Space)  {  thissleeptime = sleepTime;  } } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {  int index = 1;  int index_count = Convert.ToInt32(comboBox1.Text);  for (int i = 1; i < index_count; i++)  {  index = index * 2;  }  level = index_count;  sleepTime = 1000 / index;  thissleeptime = sleepTime;  btnStop.Enabled = false;  button3.Enabled = false;  button2.Enabled = true;  IsWork = false;  SetMap();  lblCount.Text = "5";  lblLevel.Text = index_count.ToString();  serpent.Direction = Direction.Right; } private void checkBox1_Click(object sender, EventArgs e) {  comboBox1.Enabled = this.checkBox1.Checked; } } public enum SerpentState { Moving, NextLevel, Error }}

主界面

C#,贪吃蛇

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持VEVB武林网。


注:相关教程知识阅读请移步到c#教程频道。
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表