14.代码汇总
14.1 Program
using System;
namespace CSharp进阶实践教学
{
class Program
{
static void Main(string[] args)
{
Game g = new Game();
g.Start();
}
}
}
14.2 Game
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
/// <summary>
/// 场景类型枚举
/// </summary>
enum E_SceneType
{
/// <summary>
/// 开始场景
/// </summary>
Begin,
/// <summary>
/// 游戏场景
/// </summary>
Game,
/// <summary>
/// 结束场景
/// </summary>
End,
}
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;
}
}
}
}
14.3 ISceneUpdate
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
/// <summary>
/// 场景更新接口
/// </summary>
interface ISceneUpdate
{
void Update();
}
}
14.4 BeginOrEndBaseScene
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
abstract class BeginOrEndBaseScene : ISceneUpdate
{
protected int nowSelIndex = 0;
protected string strTitle;
protected string strOne;
public abstract void EnterJDoSomthing();
public void Update()
{
//开始和结束场景的 游戏逻辑
//选择当前的选项 然后 监听 键盘输入 wsj
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 < 0)
{
nowSelIndex = 0;
}
break;
case ConsoleKey.S:
++nowSelIndex;
if (nowSelIndex > 1)
{
nowSelIndex = 1;
}
break;
case ConsoleKey.J:
EnterJDoSomthing();
break;
}
}
}
}
14.5 BeginScene
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
class BeginScene : BeginOrEndBaseScene
{
public BeginScene()
{
strTitle = "俄罗斯方块";
strOne = "开始游戏";
}
public override void EnterJDoSomthing()
{
//按J键做什么的逻辑
if (nowSelIndex == 0)
{
Game.ChangeScene(E_SceneType.Game);
}
else
{
Environment.Exit(0);
}
}
}
}
14.6 EndScene
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
class EndScene : BeginOrEndBaseScene
{
public EndScene()
{
strTitle = "结束游戏";
strOne = "回到开始界面";
}
public override void EnterJDoSomthing()
{
//按J键做什么的逻辑
if (nowSelIndex == 0)
{
Game.ChangeScene(E_SceneType.Begin);
}
else
{
Environment.Exit(0);
}
}
}
}
14.7 GameScene
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace CSharp进阶实践教学
{
class GameScene : ISceneUpdate
{
Map map;
BlockWorker blockWorker;
#region Lesson10
//bool isRunning;
//Thread inputThread;
#endregion
public GameScene()
{
map = new Map(this);
blockWorker = new BlockWorker();
#region Lesson10 输入线程
//添加输入事件监听
InputThread.Instance.inputEvent += CheckInputThread;
//isRunning = true;
//inputThread = new Thread(CheckInputThread);
////设置成后台线程 声明周期随主线程决定
//inputThread.IsBackground = true;
////开启线程
//inputThread.Start();
#endregion
}
#region Lesson10 输入线程
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.CanMoveRL(E_Change_Type.Left, map))
blockWorker.MoveRL(E_Change_Type.Left);
break;
case ConsoleKey.D:
if (blockWorker.CanMoveRL(E_Change_Type.Right, map))
blockWorker.MoveRL(E_Change_Type.Right);
break;
case ConsoleKey.S:
//向下动
if (blockWorker.CanMove(map))
blockWorker.AutoMove();
break;
}
}
}
//}
}
#endregion
/// <summary>
/// 停止线程
/// </summary>
public void StopThread()
{
//isRunning = false;
//inputThread = null;
//移除输入事件监听
InputThread.Instance.inputEvent -= CheckInputThread;
//在某些c#版本中 会直接报错 没用
//inputThread.Abort();
}
public void Update()
{
//锁里面不要包含 休眠 不然会影响别人
lock(blockWorker)
{
//地图绘制
map.Draw();
//搬运工绘制
blockWorker.Draw();
//自动向下移动
if (blockWorker.CanMove(map))
blockWorker.AutoMove();
}
//用线程休眠的形式
Thread.Sleep(200);
}
}
}
14.8 IDraw
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
interface IDraw
{
void Draw();
}
}
14.9 Position
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
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 p1, Position p2)
{
if (p1.x == p2.x && p1.y == p2.y)
return true;
return false;
}
public static bool operator !=(Position p1, Position p2)
{
if (p1.x == p2.x && p1.y == p2.y)
return false;
return true;
}
public static Position operator +(Position p1, Position p2)
{
Position pos = new Position(p1.x + p2.x, p1.y + p2.y);
return pos;
}
}
}
14.10 DrawObject
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
/// <summary>
/// 绘制类型 根据不同类型 改变绘制的方块的颜色
/// </summary>
enum E_DrawType
{
/// <summary>
/// 墙壁
/// </summary>
Wall,
/// <summary>
/// 正方形方块
/// </summary>
Cube,
/// <summary>
/// 直线
/// </summary>
Line,
/// <summary>
/// 坦克
/// </summary>
Tank,
/// <summary>
/// 左梯子
/// </summary>
Left_Ladder,
/// <summary>
/// 右梯子
/// </summary>
Right_Ladder,
/// <summary>
/// 左长梯子
/// </summary>
Left_Long_Ladder,
/// <summary>
/// 右长梯子
/// </summary>
Right_Long_Ladder,
}
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)
{
this.pos = new Position(x, y);
}
public void Draw()
{
//屏幕外不用再绘制
if (pos.y < 0)
return;
Console.SetCursorPosition(pos.x, pos.y);
switch (type)
{
case E_DrawType.Wall:
Console.ForegroundColor = ConsoleColor.Red;
break;
case E_DrawType.Cube:
Console.ForegroundColor = ConsoleColor.Blue;
break;
case E_DrawType.Line:
Console.ForegroundColor = ConsoleColor.Green;
break;
case E_DrawType.Tank:
Console.ForegroundColor = ConsoleColor.Cyan;
break;
case E_DrawType.Left_Ladder:
case E_DrawType.Right_Ladder:
Console.ForegroundColor = ConsoleColor.Magenta;
break;
case E_DrawType.Left_Long_Ladder:
case E_DrawType.Right_Long_Ladder:
Console.ForegroundColor = ConsoleColor.DarkGray;
break;
}
Console.Write("■");
}
#region Lesson6 添加一个清楚绘制的方法
public void ClearDraw()
{
//屏幕外不用再绘制
if (pos.y < 0)
return;
Console.SetCursorPosition(pos.x, pos.y);
Console.Write(" ");
}
#endregion
/// <summary>
/// 这是切换方块类型 主要用于搬砖下落到地图时 把搬砖类型编程墙壁类型
/// </summary>
/// <param name="type"></param>
public void ChangeType(E_DrawType type)
{
this.type = type;
}
}
}
14.11 Map
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
class Map : IDraw
{
//必须要初始化才能往里面装东西
//固定墙壁
private List<DrawObject> walls = new List<DrawObject>();
//必须要初始化才能往里面装东西
//动态墙壁
public List<DrawObject> dynamicWalls = new List<DrawObject>();
private GameScene nowGameScene;
#region Lesson6 为了外部能快速得到地图边界
//动态墙壁的宽容量 一行可以有多少个
public int w;
public int h;
#endregion
#region Lesson11 跨层
//记录每一行有多少个小方块的容器
//索引对应的就是行号
private int[] recordInfo;
#endregion
//重载一次无参构造 去初始化我们的固定墙壁
public Map(GameScene scene)
{
this.nowGameScene = scene;
//为了方便外部得到地图的高的边界 直接在此记录 避免修改代码时多处修改
h = Game.h - 6;
//这个就代表对应每行的计数初始化 默认都为0
//0~Game.h-7
recordInfo = new int[h];
w = 0;
//在绘制 横向的固定墙壁
for (int i = 0; i < Game.w; i += 2)
{
walls.Add(new DrawObject(E_DrawType.Wall, i, h));
++w;
}
w -= 2;
for (int i = 0; i < h; i++)
{
walls.Add(new DrawObject(E_DrawType.Wall, 0, i));
walls.Add(new DrawObject(E_DrawType.Wall, Game.w - 2, i));
}
}
public void Draw()
{
//绘制固定墙壁
for (int i = 0; i < walls.Count; i++)
{
walls[i].Draw();
}
//绘制动态墙壁 有才绘制
for (int i = 0; i < dynamicWalls.Count; i++)
{
dynamicWalls[i].Draw();
}
}
//清楚动态墙壁
public void ClearDraw()
{
//绘制动态墙壁 有才绘制
for (int i = 0; i < dynamicWalls.Count; i++)
{
dynamicWalls[i].ClearDraw();
}
}
/// <summary>
/// 提供给外部添加动态方块的函数
/// </summary>
/// <param name="walls"></param>
public void AddWalls(List<DrawObject> walls)
{
for (int i = 0; i < walls.Count; i++)
{
//传递方块进来时 把其类型改成 墙壁类型
walls[i].ChangeType(E_DrawType.Wall);
dynamicWalls.Add(walls[i]);
//在动态墙壁添加处 发现 位置顶满了 就结束
if (walls[i].pos.y <= 0)
{
//关闭输入线程
this.nowGameScene.StopThread();
//场景切换 切换到结束界面
Game.ChangeScene(E_SceneType.End);
return;
}
//进行添加动态墙壁的计数
//根据索引来得到行
//h 是 Game.h - 6
//y 最大为 Game.h - 7
recordInfo[h - 1 - walls[i].pos.y] += 1;
}
//先把之前的动态小方块擦掉
ClearDraw();
//检测移除
CheckClear();
//再绘制动态小方块
Draw();
}
#region Lesson11 跨层
/// <summary>
/// 检测是否跨层
/// </summary>
public void CheckClear()
{
List<DrawObject> delList = new List<DrawObject>();
//要选择记录行中有多少个方块的容器
//数组
//判断这个一行是否满(方块)
//遍历数组 检测数组里面存的数
//是不是w-2
for (int i = 0; i < recordInfo.Length; i++)
{
//必须满足条件 才证明满了
//小方块计数 == w(这个w已经是去掉了左右两边的固定墙壁)
if (recordInfo[i] == w)
{
//1.这一行的所有小方块移除
for (int j = 0; j < dynamicWalls.Count; j++)
{
//当前通过动态方块的y计算它在哪一行 如果行号
//和当前记录索引一致 就证明 应该移除
if (i == h - 1 - dynamicWalls[j].pos.y)
{
//移除这个方块 为了安全移除 添加一个记录列表
delList.Add(dynamicWalls[j]);
}
//2.要这一行之上的所有小方块下移一个单位
//如果当前的这个位置 是该行以上 那就该小方块 下移一格
else if (h - 1 - dynamicWalls[j].pos.y > i)
{
++dynamicWalls[j].pos.y;
}
}
//移除待删除的小方块
for (int j = 0; j < delList.Count; j++)
{
dynamicWalls.Remove(delList[j]);
}
//3.记录小方块数量的数组从上到下迁移
for (int j = i; j < recordInfo.Length - 1; j++)
{
recordInfo[j] = recordInfo[j + 1];
}
//置空最顶的计数
recordInfo[recordInfo.Length - 1] = 0;
//跨掉一行后 再次去从头检测是否跨层
CheckClear();
break;
}
}
}
#endregion
}
}
14.12 BlockInfo
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
class BlockInfo
{
//方块信息坐标的容器
private List<Position[]> list;
public BlockInfo(E_DrawType type)
{
//必须要初始化才能往里面装东西
list = new List<Position[]>();
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:
//初始化 长条形状的4种形态的坐标信息
list.Add(new Position[3] {
new Position(0,-1),
new Position(0,1),
new Position(0,2)
});
list.Add(new Position[3] {
new Position(-4,0),
new Position(-2,0),
new Position(2,0)
});
list.Add(new Position[3] {
new Position(0,-2),
new Position(0,-1),
new Position(0,1)
});
list.Add(new Position[3] {
new Position(-2,0),
new Position(2,0),
new Position(4,0)
});
break;
case E_DrawType.Tank:
list.Add(new Position[3] {
new Position(-2,0),
new Position(2,0),
new Position(0,1)
});
list.Add(new Position[3] {
new Position(0,-1),
new Position(-2,0),
new Position(0,1)
});
list.Add(new Position[3] {
new Position(0,-1),
new Position(-2,0),
new Position(2,0)
});
list.Add(new Position[3] {
new Position(0,-1),
new Position(2,0),
new Position(0,1)
});
break;
case E_DrawType.Left_Ladder:
list.Add(new Position[3]{
new Position(0,-1),
new Position(2,0),
new Position(2,1)
});
list.Add(new Position[3]{
new Position(2,0),
new Position(0,1),
new Position(-2,1)
});
list.Add(new Position[3]{
new Position(-2,-1),
new Position(-2,0),
new Position(0,1)
});
list.Add(new Position[3]{
new Position(0,-1),
new Position(2,-1),
new Position(-2,0)
});
break;
case E_DrawType.Right_Ladder:
list.Add(new Position[3]{
new Position(0,-1),
new Position(-2,0),
new Position(-2,1)
});
list.Add(new Position[3]{
new Position(-2,-1),
new Position(0,-1),
new Position(2,0)
});
list.Add(new Position[3]{
new Position(2,-1),
new Position(2,0),
new Position(0,1)
});
list.Add(new Position[3]{
new Position(0,1),
new Position(2,1),
new Position(-2,0)
});
break;
case E_DrawType.Left_Long_Ladder:
list.Add(new Position[3]{
new Position(-2,-1),
new Position(0,-1),
new Position(0,1)
});
list.Add(new Position[3]{
new Position(2,-1),
new Position(-2,0),
new Position(2,0)
});
list.Add(new Position[3]{
new Position(0,-1),
new Position(2,1),
new Position(0,1)
});
list.Add(new Position[3]{
new Position(2,0),
new Position(-2,0),
new Position(-2,1)
});
break;
case E_DrawType.Right_Long_Ladder:
list.Add(new Position[3]{
new Position(0,-1),
new Position(0,1),
new Position(2,-1)
});
list.Add(new Position[3]{
new Position(2,0),
new Position(-2,0),
new Position(2,1)
});
list.Add(new Position[3]{
new Position(0,-1),
new Position(-2,1),
new Position(0,1)
});
list.Add(new Position[3]{
new Position(-2,-1),
new Position(-2,0),
new Position(2,0)
});
break;
default:
break;
}
}
/// <summary>
/// 提供给外部根据索引快速获取 位置偏移信息的
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
public Position[] this[int index]
{
get
{
if (index < 0)
return list[0];
else if (index >= list.Count)
return list[list.Count - 1];
else
return list[index];
}
}
/// <summary>
/// 提供给外部 获取 形态有几种
/// </summary>
public int Count { get => list.Count; }
}
}
14.13 BlockWorker
using System;
using System.Collections.Generic;
using System.Text;
namespace CSharp进阶实践教学
{
/// <summary>
/// 变形左右枚举 决定顺时针还是逆时针
/// </summary>
enum E_Change_Type
{
Left,
Right,
}
class BlockWorker : IDraw
{
//方块们
private List<DrawObject> blocks;
//心中要默默的知道 各个形状的方块信息是什么
//选择一个容器来纪录各个方块的形态信息
//用list和Dictionary都可以用来存储方块的几种信息
//我们选择Dictionary的主要目的是好找 并且起到练习的作用
private Dictionary<E_DrawType, BlockInfo> blockInfoDic;
//记录随机创建出来的方块的 具体形态信息
private BlockInfo nowBlockInfo;
//当前的形态索引
private int nowInfoIndex;
public BlockWorker()
{
//初始化 装块信息
blockInfoDic = new Dictionary<E_DrawType, BlockInfo>()
{
{ 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) },
};
//随机方块
RandomCreateBlock();
}
public void Draw()
{
for (int i = 0; i < blocks.Count; i++)
{
blocks[i].Draw();
}
}
/// <summary>
/// 随机创建一个方块
/// </summary>
public void RandomCreateBlock()
{
//随机方块类型
Random r = new Random();
E_DrawType type = (E_DrawType)r.Next(1, 8);
//每次新建一个 砖块 其实就是创建4个小方形
blocks = new List<DrawObject>()
{
new DrawObject(type),
new DrawObject(type),
new DrawObject(type),
new DrawObject(type),
};
//需要初始化方块位置
//原点位置 我们随机 自己定义 方块List中第0个就是我们的原点方块
blocks[0].pos = new Position(24, -5);
//其它三个方块的位置
//取出方块的形态信息 来进行具体的随机
//应该把取出来的 方块具体的形态信息 存起来 用于之后变形
nowBlockInfo = blockInfoDic[type];
//随机几种形态中的一种来设置方块的信息吧
nowInfoIndex = r.Next(0, nowBlockInfo.Count);
//取出其中一种形态的坐标信息
Position[] pos = nowBlockInfo[nowInfoIndex];
//讲另外的三个小方块进行设置 计算
for (int i = 0; i < pos.Length; i++)
{
//取出来的pos是相对原点方块的坐标 所以需要进行计算
blocks[i + 1].pos = blocks[0].pos + pos[i];
}
}
#region Lesson6 变形相关方法
//擦除的方法
public void ClearDraw()
{
for (int i = 0; i < blocks.Count; i++)
{
blocks[i].ClearDraw();
}
}
/// <summary>
/// 变形
/// </summary>
/// <param name="type">左边还是右边</param>
public void Change(E_Change_Type type)
{
//变之前把之前的位置擦除
ClearDraw();
switch (type)
{
case E_Change_Type.Left:
--nowInfoIndex;
if (nowInfoIndex < 0)
nowInfoIndex = nowBlockInfo.Count - 1;
break;
case E_Change_Type.Right:
++nowInfoIndex;
if (nowInfoIndex >= nowBlockInfo.Count)
nowInfoIndex = 0;
break;
}
//得到索引目的 是得到对应形态的 位置偏移信息
//用于设置另外的三个小方块
Position[] pos = nowBlockInfo[nowInfoIndex];
//将另外的三个小方块进行设置 计算
for (int i = 0; i < pos.Length; i++)
{
//取出来的pos是相对原点方块的坐标 所以需要进行计算
blocks[i + 1].pos = blocks[0].pos + pos[i];
}
//变之后再来绘制
Draw();
}
/// <summary>
/// 判断是否可以进行变形
/// </summary>
/// <param name="type">变形方向</param>
/// <param name="map">地图信息</param>
/// <returns></returns>
public bool CanChange(E_Change_Type type, Map map)
{
//用一个临时变量记录 当前索引 不变化当前索引
//变化这个临时变量
int nowIndex = nowInfoIndex;
switch (type)
{
case E_Change_Type.Left:
--nowIndex;
if (nowIndex < 0)
nowIndex = nowBlockInfo.Count - 1;
break;
case E_Change_Type.Right:
++nowIndex;
if (nowIndex >= nowBlockInfo.Count)
nowIndex = 0;
break;
}
//通过临时索引 取出形态信息 用于重合判断
Position[] nowPos = nowBlockInfo[nowIndex];
//判断是否超出地图边界
Position tempPos;
for (int i = 0; i < nowPos.Length; i++)
{
tempPos = blocks[0].pos + nowPos[i];
//判断左右边界 和 下边界
if (tempPos.x < 2 ||
tempPos.x >= Game.w - 2 ||
tempPos.y >= map.h)
{
return false;
}
}
//判断是否和地图上的动态方块重合
for (int i = 0; i < nowPos.Length; i++)
{
tempPos = blocks[0].pos + nowPos[i];
for (int j = 0; j < map.dynamicWalls.Count; j++)
{
if (tempPos == map.dynamicWalls[j].pos)
{
return false;
}
}
}
return true;
}
#endregion
#region Lesson7 方块左右移动
/// <summary>
/// 左右移动的函数
/// </summary>
/// <param name="type">左或者右</param>
public void MoveRL(E_Change_Type type)
{
//在动之前 要得到原来的坐标 进行擦除
ClearDraw();
//根据传入的类型 决定左动还是右动
//左动 x-2,y0 右动x 2 y 0
//得到我们的便宜位置
Position movePos = new Position(type == E_Change_Type.Left ? -2 : 2, 0);
//遍历我的所有小方块
for (int i = 0; i < blocks.Count; i++)
{
blocks[i].pos += movePos;
}
//动之后 再画上去
Draw();
}
/// <summary>
/// 移动之前判断 判断是否可以进行左右移动
/// </summary>
/// <param name="type"></param>
/// <returns></returns>
public bool CanMoveRL(E_Change_Type type, Map map)
{
//根据传入的类型 决定左动还是右动
//左动 x-2,y0 右动x 2 y 0
//得到我们的便宜位置
Position movePos = new Position(type == E_Change_Type.Left ? -2 : 2, 0);
//要不和左右边界重合
//动过后的结果 不能直接改小方块的位置 改了就覆水难收
//这只是想预判断 所以 得一个临时变量用于判断即可
Position pos;
for (int i = 0; i < blocks.Count; i++)
{
pos = blocks[i].pos + movePos;
if (pos.x < 2 || pos.x >= Game.w - 2)
return false;
}
//要不和动态方块重合了
for (int i = 0; i < blocks.Count; i++)
{
pos = blocks[i].pos + movePos;
for (int j = 0; j < map.dynamicWalls.Count; j++)
{
if (pos == map.dynamicWalls[j].pos)
return false;
}
}
return true;
}
#endregion
#region Lesson8 方块自动向下移动
/// <summary>
/// 自动移动的方法
/// </summary>
public void AutoMove()
{
//变位置之前擦除
ClearDraw();
//首要要得到移动的多少
//Position downMove = new Position(0, 1);
//得到所有的方块 让其向下移动
for (int i = 0; i < blocks.Count; i++)
{
//blocks[i].pos += downMove;
blocks[i].pos.y += 1;
}
//变了位置再画
Draw();
}
public bool CanMove(Map map)
{
//用临时变量存储 下一次移动的位置 然后用于进行重合判断
Position movePos = new Position(0, 1);
Position pos;
//边界
for (int i = 0; i < blocks.Count; i++)
{
pos = blocks[i].pos + movePos;
if (pos.y >= map.h)
{
//停下来 给予地图动态方块
map.AddWalls(blocks);
//随机创建新的方块
RandomCreateBlock();
return false;
}
}
//动态方块
for (int i = 0; i < blocks.Count; i++)
{
pos = blocks[i].pos + movePos;
for (int j = 0; j < map.dynamicWalls.Count; j++)
{
if (pos == map.dynamicWalls[j].pos)
{
//停下来 给予地图动态方块
map.AddWalls(blocks);
//随机创建新的方块
RandomCreateBlock();
return false;
}
}
}
return true;
}
#endregion
}
}
14.14 InputThread
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace CSharp进阶实践教学
{
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();
}
}
}
}
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com