C#貪吃蛇游戲實現分析。本站提示廣大學習愛好者:(C#貪吃蛇游戲實現分析)文章只能為提供參考,不一定能成為您想要的結果。以下是C#貪吃蛇游戲實現分析正文
作者:冰封一夏
這篇文章主要為大家分析了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 } }
主界面
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持。