您的位置:首页 > 编程语言 > C#

C#贪吃蛇游戏实现分析

2017-06-03 16:49 891 查看

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

贪吃蛇分析

游戏规则:

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# 贪吃蛇