您好,登錄后才能下訂單哦!
這篇文章主要講解了C# 實現俄羅斯方塊的代碼詳解,內容清晰明了,對此有興趣的小伙伴可以學習一下,相信大家閱讀完之后會有幫助。
概述
俄羅斯方塊(Tetris)是一款由俄羅斯人阿列克謝·帕基特諾夫發明的休閑游戲,帕基特諾夫愛玩拼圖,從拼圖游戲里得到靈感,設計出了俄羅斯方塊。由于上手簡單、老少皆宜,從而家喻戶曉,風靡世界。本文簡述如何通過C#來實現俄羅斯方塊,僅供學習分享使用,如有不足之處,還請指正。
涉及知識點
BackgroundWorker 在單獨的線程上執行操作(主要執行比較耗時的操作)。
Action .NetFramework自帶的一個委托方法。
TableLayoutPanel 表示一個面板,它可以在一個由行和列組成的網格中對其內容進行動態布局,本文主要用作俄羅斯方塊的容器。
方塊流程圖
如下圖所示,描述了俄羅斯方塊的設計流程圖
俄羅斯方塊效果圖
如下圖所示:主要包括狀態,得分,開始按鈕,停止按鈕,按鍵盤左右箭頭移動等功能
核心代碼
1. 定義方塊的形狀
如下所示:共7中形狀
/// <summary> /// 俄羅斯方塊的形狀 /// </summary> public enum TetrisStyle { S = 0, Z = 1, L = 2, J = 3, I = 4, O = 5, T = 6 }
2. 定義移動的方向
如下所示:默認向下移動,同時可以左右移動
/// <summary> /// 俄羅斯方塊移動方向 /// </summary> public enum TetrisDirection { UP = 0,//上,表示順時針旋轉 DOWN = 1,//下,表示向下移動 LEFT = 2,//左,表示往左移動 RIGHT = 3, //表示向右移動 DEFAULT=4 //默認動作 }
3. 俄羅斯方塊元素
如下所示,每一種形狀都由四個方塊組成,根據不同形狀設置不同的位置
/// <summary> /// 俄羅斯方塊元素 /// </summary> public class TetrisElement { /// <summary> /// 構造函數 /// </summary> /// <param name="style"></param> public TetrisElement(TetrisStyle style) { this.style = style; } /// <summary> /// 構造函數 /// </summary> /// <param name="style">形狀</param> /// <param name="content">內容</param> /// <param name="location">位置</param> public TetrisElement(TetrisStyle style, Point[] content, Point location) { this.style = style; this.content = content; this.location = location; } /// <summary> /// 元素字母類型 /// </summary> public TetrisStyle style { get; set; } /// <summary> /// 內容 /// </summary> public Point[] content { get; set; } /// <summary> /// 元素位置 /// </summary> public Point location { get; set; } /// <summary> /// 位置改變 /// </summary> /// <param name="x"></param> /// <param name="y"></param> public void move(int x, int y) { this.location = new Point(x, y); } public Point[] getContent(TetrisStyle style) { //內容由四個點組成,順序:先上后下,先左后右 Point[] content = new Point[4]; switch (style) { case TetrisStyle.I: //I形狀 content[0] = new Point(0, 0); content[1] = new Point(0, 1); content[2] = new Point(0, 2); content[3] = new Point(0, 3); break; case TetrisStyle.J: //J形狀 content[0] = new Point(1, 0); content[1] = new Point(1, 1); content[2] = new Point(1, 2); content[3] = new Point(0, 2); break; case TetrisStyle.L: //L形狀 content[0] = new Point(0, 0); content[1] = new Point(0, 1); content[2] = new Point(0, 2); content[3] = new Point(1, 2); break; case TetrisStyle.O: //O形狀 content[0] = new Point(0, 0); content[1] = new Point(1, 0); content[2] = new Point(0, 1); content[3] = new Point(1, 1); break; case TetrisStyle.S: //S形狀 content[0] = new Point(2, 0); content[1] = new Point(1, 0); content[2] = new Point(1, 1); content[3] = new Point(0, 1); break; case TetrisStyle.T: //T形狀 content[0] = new Point(0, 0); content[1] = new Point(1, 0); content[2] = new Point(2, 0); content[3] = new Point(1, 1); break; case TetrisStyle.Z: //Z形狀 content[0] = new Point(0, 0); content[1] = new Point(1, 0); content[2] = new Point(1, 1); content[3] = new Point(2, 1); break; default: //默認I content[0] = new Point(0, 0); content[1] = new Point(0, 1); content[2] = new Point(0, 2); content[3] = new Point(0, 3); break; } return content; } }
4. 容器類
如下所示:容器類主要是移動方塊元素,并更新頁面上的值
/// <summary> /// 俄羅斯方塊容器 /// </summary> public class TetrisContainer { private int[,] tetris = new int[10, 20];//定義二維數組,表示坐標信息,默認值為0 public Action<Point,Point[],TetrisDirection> onPartialChanged;//局部變更事件 public Action<int[,]> onFullChanged;//元素全變更事件,即有整行被清除事件 public Action onCompleted; //結束事件 public int scorce = 0; /// <summary> /// 狀態發生改變 /// </summary> /// <param name="element"></param> /// <param name="direction"></param> /// <returns></returns> public TetrisElement change(TetrisElement element, TetrisDirection direction) { TetrisElement tmp=null; //判斷不同的方向 switch (direction) { case TetrisDirection.DEFAULT: //如果可以向下移動 if (checkDefault(element)) { //向下移動一個元素 element.move(element.location.X, element.location.Y + 1); tmp = element; } else { //如果不可以向下移動,則更新容器 updateTetris(element); tmp = null; } break; case TetrisDirection.DOWN: break; case TetrisDirection.UP: break; case TetrisDirection.LEFT: if (checkLeft(element)){ //判斷是否可以向左移動 //向下移動一個元素 element.move(element.location.X-1, element.location.Y); tmp = element; } break; case TetrisDirection.RIGHT: if (checkRight(element)) { //判斷是否可以右左移動 //向下移動一個元素 element.move(element.location.X+1, element.location.Y); tmp = element; } break; } //局部變更 if (onPartialChanged != null) { Point location = element.location; Point[] content = new Point[4]; element.content.CopyTo(content, 0); for (int i = 0; i < content.Length; i++) { content[i].X = location.X + content[i].X; content[i].Y = location.Y + content[i].Y; } onPartialChanged(location,content,direction); } //判斷游戲是否結束 if (onCompleted != null) { if (checkComplete()) { onCompleted(); } } //全部變更 if (onFullChanged != null) { //判斷是是否有權為1的行,如果有則消掉 int[] rows = checkAllTetris(); if (rows.Length>0) { updateAllTetris(rows);//消掉行 onFullChanged(tetris); } } return tmp; } /// <summary> /// 更新tetris /// </summary> /// <param name="element"></param> private void updateTetris(TetrisElement element) { Point location = element.location; Point[] content = element.content; int minX = element.getMinX(element.style); int maxX = element.getMaxX(element.style); int minY = element.getMinY(element.style); int maxY = element.getMaxY(element.style); foreach (Point p in content) { if (location.Y + p.Y < 20 && location.Y + p.Y >= 0 && location.X + p.X >= 0 && location.X + p.X < 10) { this.tetris[location.X + p.X, location.Y + p.Y] = 1; } } } /// <summary> /// 檢查全部列 /// </summary> private int[] checkAllTetris() { List<int> lst = new List<int>(); //20行 for (int y = 0; y < 20; y++) { int col = 0; //10列 for (int x = 0; x < 10; x++) { if (tetris[x, y] == 0) { break; } else { col += 1; } } if (col == 10) { col = 0; lst.Add(y); } } return lst.ToArray(); } /// <summary> /// 更新 /// </summary> private void updateAllTetris(int[] rows) { foreach (int row in rows) { //當前行清掉 for (int x = 0; x < 10; x++) { tetris[x, row] = 0; } //row行之上的往下移動一行 for (int y = row-1; y >=0; y--) { for (int x = 0; x < 10; x++) { if (tetris[x, y] == 1) { tetris[x, y + 1] = 1; tetris[x, y] = 0; } } } } } /// <summary> /// 判斷游戲是否結束 /// </summary> /// <returns></returns> private bool checkComplete() { bool isComplete = false; for (int i = 0; i < 10; i++) { if (tetris[i, 0] == 1) { isComplete = true; break; } } return isComplete; } /// <summary> /// 更新得分 /// </summary> /// <param name="s"></param> public void updateScore(int s) { this.scorce = this.scorce + s; } /// <summary> /// 重置信息 /// </summary> public void Reset() { this.tetris = new int[10, 20]; this.scorce = 0; } }
5. 隨機生成方塊元素和起始位置
/// <summary> /// 靜態函數,生成Tetris元素對象 /// </summary> /// <returns></returns> public static TetrisElement generate() { Random r = new Random(0); //隨機生成形狀 int tstyle = getRandom(); tstyle = tstyle % 7; TetrisStyle style = TetrisStyle.I; style = (TetrisStyle)Enum.Parse(typeof(TetrisStyle), tstyle.ToString()); //隨機生成起始坐標 int x = getRandom(); x = x % 10; int y = 0; //根據形狀生成位置信息 TetrisElement element = new TetrisElement(style); //內容由四個點組成,順序:先上后下,先左后右 Point[] content = element.getContent(style); //獲取最小坐標和最大坐標,防止越界 int minX = element.getMinX(style); int minY = element.getMinY(style); int maxX = element.getMaxX(style); int maxY = element.getMaxY(style); //修正起始坐標 x = (x <= minX) ? minX : x; x = (x >= maxX) ? maxX : x; y = minY; Point location = new Point(x, y); element.location = location; element.content = content; return element; }
看完上述內容,是不是對C# 實現俄羅斯方塊的代碼詳解有進一步的了解,如果還想學習更多內容,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。