這篇文章給大家分享的是有關C#實現貪吃蛇游戲的案例的內容。小編覺得挺實用的,因此分享給大家做個參考。一起跟隨小編過來看看吧。
貪吃蛇分析
游戲規則:
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#實現貪吃蛇游戲的案例就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。