定义一个坐标点,描述位置和相对位置 /// /// 定义一个方格坐标点/// class Position{public Position(int x, int y){this.x = x;this.y = y;}public Position(){}public int x { get; set; }public int y { get; set; }}
/// /// 定义方块形状状态循环链表,标记变形状态/// class Status{/// /// 方格[四个方块]下一次变形将要去的相对位置/// public List NextRelativeposition = new List(4);/// /// 是否需要检查方块[每个方格]到这个位置的可行性/// public List NeedCheck = new List(4);/// /// 指向下一状态/// public Status Next;}
在方块子类中Ready方法即为每种方块设置状态链表。
由于方块的生成为随机方式,定义简单工厂模式生成方块如下:
代码 class BoxFactory{/// /// 随机方块工厂/// static public Box GetRandomBox(ref Grid grid){//return new Box_Z(ref grid);Random ran = new Random();int index = ran.Next(7);switch (index){case 0: return new Box_S(ref grid);case 1: return new Box_Z(ref grid);case 2: return new Box_J(ref grid);case 3: return new Box_L(ref grid);case 4: return new Box_I(ref grid);case 5: return new Box_O(ref grid);case 6: return new Box_T(ref grid);default: return null;}}}
到此为止,方块定义好了,也可以随机产生了,怎么让展示在Grid中?
1.方块子类ShowAt函数标示展示到指定Grid;
2.ShowWating表示展示在等候区域。
当方块展示到容器Grid中时,怎么自动下降呢?这里用到DispatcherTimer。
dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal);dispatcherTimer.Tick += new EventHandler(Timer_Tick);dispatcherTimer.Interval = TimeSpan.FromMilliseconds(450 - Result.GetInstance().Level * 50);/// /// 定义活动方块自动下降/// public void AtuoDown(){dispatcherTimer.Start();} private void Timer_Tick(object sender, EventArgs e) { if (!MoveDown()) { dispatcherTimer.Stop(); OnBottom(this, null); } }
RemoveLine消层函数 /// /// 消层,并返回消除的层数/// static int RemoveLine(){if (grid == null) new Exception("缺少活动区域,必须为容器指定grid值。");int[] lineCount = new int[24];for (int i = 0; i < 24; i++) lineCount[i] = 0;int RemoveLineCount = 0;//计算每一行方块总数foreach (var r in grid.Children){if (r is Rectangle){int x = Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty));lineCount[x]++;}}for (int i = 23; i >= 0; i--){if (lineCount[i] >= 12){//移除一行小方格for (int j = 0; j < grid.Children.Count; j++)// (var r in mygrid.Children){if (grid.Children[j] is Rectangle){if (Convert.ToInt32((grid.Children[j] as Rectangle).GetValue(Grid.RowProperty)) == i + RemoveLineCount){grid.Children.Remove((grid.Children[j] as Rectangle));j--;}}}//将上面的所有小方格下降一行foreach (var r in grid.Children){if (r is Rectangle){if (Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)) < i + RemoveLineCount){(r as Rectangle).SetValue(Grid.RowProperty, Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)) + 1);}}}//被移除行数加1RemoveLineCount++;}}return RemoveLineCount;}
OK,到此方块可以自动下降,可消层了,现在要统计消层得分和游戏级别(难度)。
定义一个新类Result
Result类 /// /// 记录分数和级别/// class Result : INotifyPropertyChanged{Result(){Score = 0;Level = 1;}//单例模式private static Result instance;private static readonly object syncRoot = new object();public static Result GetInstance(){if (instance == null){lock (syncRoot){if (instance == null){instance = new Result();}}}return instance;}int score;int level;public int Score{get { return score; }set { score = value; Notify("Score"); }}public int Level{get { return level; }set { level = value; Notify("Level"); }}public void CalculateScore(int Lines){switch (Lines){case 1: Score += 5;break;case 2: Score += 15;break;case 3: Score += 30;break;case 4: Score += 50;break;default: Score += 0;break;}if (Score < 20) Level = 1;else if (Score < 100) Level = 2;else if (Score < 300) Level = 3;else if (Score < 500) Level = 4;else if (Score < 1000) Level = 5;else if (Score < 3000) Level = 6;else if (Score < 5000) Level = 7;else Level = 8;}void Notify(string propName){if (PropertyChanged != null){PropertyChanged(this, new PropertyChangedEventArgs(propName));}}public event PropertyChangedEventHandler PropertyChanged;}
在该类中用单例模式控制产生单一实例,并通过实现接口绑定到界面分数展示台。
界面XAML如下:
这样,代码中对Result赋值,直接影响界面控件展示数值的变化:
/// /// 活动方块到达底部时触发/// static public void ActivityBox_OnBottom(object sender, EventArgs e){Result.GetInstance().CalculateScore(RemoveLine());NewBoxReadyToDown();}