C#【进阶】俄罗斯方块
俄罗斯方块
文章目录
- Test1_场景切换相关
- BeginScene.cs
- BegionOrEndScene.cs
- EndScene.cs
- Game.cs
- GameScene.cs
- ISceneUpdate.cs
- Test2_绘制对象基类和枚举信息
- DrawObject.cs
- IDraw.cs
- Position.cs
- Test3_地图相关
- Map.cs
- Test4_坐标信息类
- BlockInfo.cs
- Test5_板砖工人类
- BlockWorker.cs
- Test6_输入模块
- InputThread.cs
- Program.cs
Test1_场景切换相关
BeginScene.cs
namespace CSharp俄罗斯方块 { internal class BeginScene : BegionOrEndScene { public BeginScene() { strTitle = "俄罗斯方块"; strOne = "开始游戏"; } public override void EnterJDoSomthing() { if (nowSelIndex == 0) { Game.ChangeScene(E_SceneType.Game); } else { Environment.Exit(0); } } } }
BegionOrEndScene.cs
namespace CSharp俄罗斯方块 { abstract internal class BegionOrEndScene : ISceneUpdate { protected int nowSelIndex = 0; protected string strTitle; protected string strOne; public abstract void EnterJDoSomthing(); public void Update() { Console.ForegroundColor = ConsoleColor.White; Console.SetCursorPosition(Game.w / 2 - strTitle.Length, 5); Console.Write(strTitle); Console.SetCursorPosition(Game.w / 2 - strOne.Length, 8); Console.ForegroundColor = nowSelIndex == 0 ? ConsoleColor.Red : ConsoleColor.White; Console.Write(strOne); Console.SetCursorPosition(Game.w / 2 - 4, 10); Console.ForegroundColor = nowSelIndex == 1 ? ConsoleColor.Red : ConsoleColor.White; Console.Write("结束游戏"); switch(Console.ReadKey(true).Key) { case ConsoleKey.W: nowSelIndex--; if (nowSelIndex 1) { nowSelIndex = 0; } break; case ConsoleKey.J: EnterJDoSomthing(); break; } } } }
EndScene.cs
namespace CSharp俄罗斯方块 { internal class EndScene : BegionOrEndScene { public EndScene() { strTitle = "结束游戏"; strOne = "回到开始界面"; } public override void EnterJDoSomthing() { if(nowSelIndex == 0) { Game.ChangeScene(E_SceneType.Begin); } else { Environment.Exit(0); } } } }
Game.cs
namespace CSharp俄罗斯方块 { enum E_SceneType { Begin, Game, End, } internal class Game { public const int w = 50; public const int h = 35; public static ISceneUpdate nowScene; public Game() { Console.CursorVisible = false; Console.SetWindowSize(w, h); Console.SetBufferSize(w, h); ChangeScene(E_SceneType.Begin); } public void start() { while (true) { if (nowScene != null) { nowScene.Update(); } } } public static void ChangeScene(E_SceneType type) { Console.Clear(); switch (type) { case E_SceneType.Begin: nowScene = new BeginScene(); break; case E_SceneType.Game: nowScene = new GameScene(); break; case E_SceneType.End: nowScene = new EndScene(); break; } } } }
GameScene.cs
namespace CSharp俄罗斯方块 { internal class GameScene : ISceneUpdate { Map map; BlockWorker blockWorker; //bool isRunning; //新开线程 //Thread inputThread; public GameScene() { map = new Map(this); blockWorker = new BlockWorker(); InputThread.Instance.inputEvent += CheckInputThread; //isRunning = true; //inputThread = new Thread(CheckInputThread); 设置成后台线程(生命周期随主线程) //inputThread.IsBackground = true; 开启线程 //inputThread.Start(); } public void StopThread() { //isRunning = false; //inputThread = null; //移除输入事件监听 InputThread.Instance.inputEvent -= CheckInputThread; } private void CheckInputThread() { //while (isRunning) //{ //检测输入,防止输入卡程序 if (Console.KeyAvailable) { //避免影响主线程,在输入后加锁 lock (blockWorker) { switch (Console.ReadKey(true).Key) { case ConsoleKey.LeftArrow: //判断变形 if (blockWorker.CanChange(E_Change_Type.Left, map)) blockWorker.Change(E_Change_Type.Left); break; case ConsoleKey.RightArrow: if (blockWorker.CanChange(E_Change_Type.Right, map)) blockWorker.Change(E_Change_Type.Right); break; case ConsoleKey.A: if (blockWorker.CanMoveR_L(E_Change_Type.Left, map)) blockWorker.MoveR_L(E_Change_Type.Left); break; case ConsoleKey.D: if (blockWorker.CanMoveR_L(E_Change_Type.Right, map)) blockWorker.MoveR_L(E_Change_Type.Right); break; case ConsoleKey.S: if (blockWorker.CanDown(map)) blockWorker.AutoMove(); break; } } } //} } public void Update() { lock (blockWorker) { map.Draw(); blockWorker.Draw(); if (blockWorker.CanDown(map)) blockWorker.AutoMove(); } //线程休眠减速 Thread.Sleep(100); } } }
ISceneUpdate.cs
namespace CSharp俄罗斯方块 { /// /// 场景更新接口 /// internal interface ISceneUpdate { void Update(); } }
Test2_绘制对象基类和枚举信息
DrawObject.cs
namespace CSharp俄罗斯方块 { /// /// 绘制类型 /// enum E_DrawType { /// /// 墙壁 /// Wall, /// /// 正方形方块 /// Cube, /// /// 直线 /// Line, /// /// 坦克 /// Tank, /// /// 左梯子 /// Left_Ladder, /// /// 右梯子 /// Right_Ladder, /// /// 左长梯子 /// Left_Long_ladder, /// /// 右长梯子 /// Right_Long_ladder, } internal class DrawObject : IDraw { public Position pos; public E_DrawType type; public DrawObject(E_DrawType type) { this.type = type; } public DrawObject(E_DrawType type, int x, int y) : this(type) { pos = new Position(x, y); } public void Draw() { if (pos.y
IDraw.cs
namespace CSharp俄罗斯方块 { internal interface IDraw { void Draw(); } }
Position.cs
namespace CSharp俄罗斯方块 { internal struct Position { public int x; public int y; public Position(int x, int y) { this.x = x; this.y = y; } public static bool operator ==(Position left, Position right) { if (left.x == right.x && left.y == right.y) { return true; } return false; } public static bool operator !=(Position left, Position right) { if (left.x == right.x && left.y == right.y) { return false; } return true; } public static Position operator +(Position left, Position right) { return new Position(left.x + right.x, left.y + right.y); } } }
Test3_地图相关
Map.cs
namespace CSharp俄罗斯方块 { internal class Map : IDraw { //固定墙壁 private List walls = new List(); //动态墙壁 public List dynamicWalls = new List(); private GameScene nowGameScene; //为了外部能快速得到地图边界 //动态墙壁的宽容量,小方块横向个数 public int w; public int h; //记录每一行有多少个小方块的容器,索引就是行号 private int[] recordInfo; public Map(GameScene scene) { nowGameScene = scene; h = Game.h - 6; recordInfo = new int[h]; w = 0; //绘制横向墙壁 for (int i = 0; i
Test4_坐标信息类
BlockInfo.cs
namespace CSharp俄罗斯方块 { internal class BlockInfo { private List list; public BlockInfo(E_DrawType type) { list = new List(); switch (type) { case E_DrawType.Cube: list.Add(new Position[3] { new Position(2, 0), new Position(0, 1), new Position(2, 1) }); break; case E_DrawType.Line: list.Add([new Position(0, -1), new Position(0, 1), new Position(0, 2)]); list.Add([new Position(-4, 0), new Position(-2, 0), new Position(2, 0)]); list.Add([new Position(0, -2), new Position(0, -1), new Position(0, 1)]); list.Add([new Position(-2, 0), new Position(2, 0), new Position(4, 0)]); break; case E_DrawType.Tank: list.Add([new Position(-2, 0), new Position(2, 0), new Position(0, 1)]); list.Add([new Position(0, -1), new Position(-2, 0), new Position(0, 1)]); list.Add([new Position(0, -1), new Position(-2, 0), new Position(2, 0)]); list.Add([new Position(0,-1), new Position(2, 0), new Position(0, 1)]); break; case E_DrawType.Left_Ladder: list.Add([new Position(0, -1), new Position(2, 0), new Position(2, 1)]); list.Add([new Position(2, 0), new Position(-2, 1), new Position(0, 1)]); list.Add([new Position(-2, -1), new Position(-2, 0), new Position(0, 1)]); list.Add([new Position(0, -1), new Position(2, -1), new Position(-2, 0)]); break; case E_DrawType.Right_Ladder: list.Add([new Position(0, -1), new Position(-2, 0), new Position(-2, 1)]); list.Add([new Position(-2, -1), new Position(0, -1), new Position(2, 0)]); list.Add([new Position(2, -1), new Position(2, 0), new Position(0, 1)]); list.Add([new Position(-2, 0), new Position(0, 1), new Position(2, 1)]); break; case E_DrawType.Left_Long_ladder: list.Add([new Position(-2, -1), new Position(0, -1), new Position(0, 1)]); list.Add([new Position(2, 1), new Position(-2, 0), new Position(2, 0)]); list.Add([new Position(0, -1), new Position(0, 1), new Position(2, 1)]); list.Add([new Position(-2, 0), new Position(2, 0), new Position(-2, 1)]); break; case E_DrawType.Right_Long_ladder: list.Add([new Position(0, -1), new Position(2, -1), new Position(0, 1)]); list.Add([new Position(-2, 0), new Position(2, 1), new Position(2, 0)]); list.Add([new Position(0, -1), new Position(0, 1), new Position(-2, 1)]); list.Add([new Position(-2, 0), new Position(2, 0), new Position(-2, -1)]); break; default: break; } } public Position[] this[int index] { get { if (index = list.Count) return list[list.Count - 1]; else return list[index]; } } public int Count { get => list.Count; } } }
Test5_板砖工人类
BlockWorker.cs
namespace CSharp俄罗斯方块 { enum E_Change_Type { Left, Right, } internal class BlockWorker : IDraw { //方块们 private List blocks; //用Dictionary方便查找 private Dictionary blockInfoDic; //随机创建的方块具体形态信息 private BlockInfo nowBlockInfo; //当前形态的索引 private int nowInfoIndex; public BlockWorker() { blockInfoDic = new Dictionary() { { E_DrawType.Cube,new BlockInfo(E_DrawType.Cube)}, { E_DrawType.Line,new BlockInfo(E_DrawType.Line)}, { E_DrawType.Tank,new BlockInfo(E_DrawType.Tank)}, { E_DrawType.Left_Ladder,new BlockInfo(E_DrawType.Left_Ladder)}, { E_DrawType.Right_Ladder,new BlockInfo(E_DrawType.Right_Ladder)}, { E_DrawType.Left_Long_ladder,new BlockInfo(E_DrawType.Left_Long_ladder)}, { E_DrawType.Right_Long_ladder,new BlockInfo(E_DrawType.Right_Long_ladder)}, }; RandomCreatBlock(); } public void Draw() { for (int i = 0; i = nowBlockInfo.Count) nowInfoIndex = 0; break; } //得到索引,取出来 Position[] pos = nowBlockInfo[nowInfoIndex]; for (int i = 0; i = nowBlockInfo.Count) nowIndex = 0; break; } //临时索引信息判断是否和墙壁重合 Position[] nowPos = nowBlockInfo[nowIndex]; //判断是否超出地图边界 Position tempPos; for (int i = 0; i = Game.w - 2 || tempPos.y >= map.h) { return false; } } //判断是否和其他方块重合 for (int i = 0; i = Game.w - 2) return false; } //动态方块重合 for (int i = 0; i = map.h) { //碰到地图,此时变成地图的一部分 map.AddWalls(blocks); //创建新的随机方块 RandomCreatBlock(); return false; } } //动态方块 for (int i = 0; i
Test6_输入模块
InputThread.cs
namespace CSharp俄罗斯方块 { internal class InputThread { //线程成员变量 Thread inputThread; //输入检测事件 public event Action inputEvent; private static InputThread instance = new InputThread(); public static InputThread Instance { get { return instance; } } private InputThread() { inputThread = new Thread(InputCheck); inputThread.IsBackground = true; inputThread.Start(); } private void InputCheck() { while (true) { inputEvent?.Invoke(); } } } }
Program.cs
using CSharp俄罗斯方块; Game game = new Game(); game.start();
文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。