您好,登錄后才能下訂單哦!
本文小編為大家詳細介紹“怎么用C#實現貪吃蛇小游戲”,內容詳細,步驟清晰,細節處理妥當,希望這篇“怎么用C#實現貪吃蛇小游戲”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
界面比較簡單,一個按鈕和一個積分器組成。
基本邏輯:每五個食物出現一次大食物,小食物1分,大食物5分。
控制:撞墻和纏繞時,游戲暫停。
詳細介紹下代碼
一、代碼分詳解
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(); } }
以上就是整個蛇運行的邏輯
二、完整代碼
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; namespace Project_Snake { public partial class SnakeForm : Form { public SnakeForm() { InitializeComponent(); } //為了上下左右鍵起作用 需要重寫這個操作 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); } /// <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; } } /// <summary> /// 蛇的控件 記錄蛇的基本方法 /// </summary> 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;//大分出現頻次 //當前方向 public Snake() { Location_X = 300; Location_Y = 300; } /// <summary> /// 蛇初始化 朝向 初始長度等 /// </summary> public static void Start() { MaxScore = 5; AllScore = -1; CurScore = 1; Sd = SnakeDirection.Left;//默認往左跑 Snakebody.Clear();//每次操作舍身重置 //添加初始化的小蛇位置 Snake s0 = new Snake();//蛇1 Snake s1 = new Snake();//蛇2 Snake s2 = new Snake(); Snake s3 = new Snake(); //默認四個長度 蛇的位置 Snakebody.Add(s0);//默認蛇1位置 Snakebody[0]是蛇頭 s1.Location_X = s0.Location_X - 10; Snakebody.Add(s1); s2.Location_X = s1.Location_X - 10; Snakebody.Add(s2); s3.Location_X = s2.Location_X - 10; Snakebody.Add(s3); } //蛇的移動操作 每次移動 都需要改變蛇身體 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; } } //吃一個節點 變為新的蛇頭 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; } } } 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;//毫秒刷新一次 } /// <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(); } /// <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); } /// <summary> /// 創建一個新的食物,也就是一個小點,紅色 /// </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;//初始化次數 } } } } /// <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);//隨機了食物的位置 } } /// <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(); } } /// <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(); } } /// <summary> /// 游戲結束 /// </summary> public void GameOver() { } } /// <summary> /// 方向枚舉 /// </summary> public enum SnakeDirection { Left, Right, Down, Up } //食物類 食物的縱軸橫軸 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;//隨機點出現食物 } } }
讀到這里,這篇“怎么用C#實現貪吃蛇小游戲”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。