집 >백엔드 개발 >C#.Net 튜토리얼 >Snake 게임을 구현하기 위한 C# 샘플 코드 분석
이 글은 주로 C# 스네이크 게임의 구현 코드를 분석합니다. 관심있는 친구들은 참고하시면 됩니다
오늘은 심심해서 뱀을 만들어보고 싶었는데 인터넷에 그런거 많지만 직접 써봐도 괜찮을 것 같아요
뱀 분석
게임 규칙:
1. 뱀의 초기 길이는 5이며, 먹을 때마다 1개씩 증가하며, 레벨을 통과하려면 최대 15개가 필요합니다.
2 뱀은 파란색으로 표시되고, 음식은 녹색, 장애물은 검은색으로 표시됩니다.
3. 뱀이 조우할 때 자신이나 벽, 장애물을 사용하면 게임이 실패합니다.
4. 방향키는 뱀의 이동 방향을 제어합니다. .위로 이동하는 경우 바로 내려갈 수는 없으며 왼쪽, 오른쪽, 위로만 이동할 수 있습니다.
5 레벨을 통과할 때마다 속도가 증가합니다.
일반 아이디어:
1.지도는 그리드 형태로 표현되며, 뱀은 사각형으로 구성되어 목록
2개와 1개의 언급된 사각형이 있으며, 사각형에 저장되는 내용은 색상, 좌표, 통과 가능 여부, 음식인지
3입니다. 한 번 앞으로 나아가면 앞에 있는 사각형을 뱀 목록에 추가하고 목록에서 마지막 사각형을 제거하세요. 앞에 있는 사각형이 음식인 경우 마지막 사각형을 제외하고는 이동하지 마세요.
4. "http://www.php.cn/wiki/121.html" target="_blank">그 동안 반복하여 전체 이동
5. 스페이스바는 while 루프가속을 달성하기 위한 절전 시간
3개의 클래스와 기본 양식, 즉 Node(그리드를 나타내는 데 사용됨), Map(지도를 나타내는 데 사용됨), Serpent(뱀을 나타내는 데 사용됨), 또 다른 주요 형태입니다. 아래 코드를 순서대로 붙여넣으세요. 기본적으로 모든 메소드에는 설명
이 있습니다.Code 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 } }
Code 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); } } }
Code 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 } }
Code 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 } }
메인 인터페이스
위 내용은 Snake 게임을 구현하기 위한 C# 샘플 코드 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!