收藏 分销(赏)

WPF游戏-菜鸟版俄罗斯方块.docx

上传人:仙人****88 文档编号:11739625 上传时间:2025-08-11 格式:DOCX 页数:18 大小:80.63KB 下载积分:10 金币
下载 相关 举报
WPF游戏-菜鸟版俄罗斯方块.docx_第1页
第1页 / 共18页
WPF游戏-菜鸟版俄罗斯方块.docx_第2页
第2页 / 共18页


点击查看更多>>
资源描述
WPF游戏 菜鸟版俄罗斯方块 时间:2010-09-20 05:42来源:博客园 作者:lipan 点击: 822次 在以前的MFC、winform中实现一个游戏程序是一件相当困难的事情,自从WPF诞生后,富客户端设计工作变得相对简单。本人刚学WPF不久,写写劣质代码望大侠莫见笑。自于这个游戏本身的实现方式我并未去研究,这里只是根据自己的理解来做。 代码下载: 主要思想: 一、提供一个容器      在以前的MFC、winform中实现一个游戏程序是一件相当困难的事情,自从WPF诞生后,富客户端设计工作变得相对简单。本人刚学WPF不久,写写劣质代码望大侠莫见笑。自于这个游戏本身的实现方式我并未去研究,这里只是根据自己的理解来做。   代码下载:   主要思想:   一、提供一个容器类(Container),用来作为方块活动的网格状区域。由于WPF自带Grid控件支持网格,因此就直接利用了。   1.Container类需要关联到Grid,活动区域;和waitingGrid等候区域(下一个出现的方块)   2.在Container类中实现消层的逻辑   二、提供一个方块基类(Box),7中方块全部从其派生。   1.每个方块包含4个Rectangle(小方格)   2.通过一个工厂类随机产生某个方块的实例   3.基类实现方块移动、变形、等逻辑、子类定义方块颜色、初始化方式,确定每个方格相对坐标。   4.在方块下降到底部触发OnBottom事件,Container接受此事件触发消行逻辑。Container类中OnGameover事件被界面层接受处理。   运行效果:        代码部分: Box方块基类 abstract class Box { public Box() { for (int i = 0; i < 4; i++) { rectangles.Add(new Rectangle()); rectangles[i].Width = 24.0; rectangles[i].Height = 24.0; } dispatcherTimer = new DispatcherTimer(DispatcherPriority.Normal); dispatcherTimer.Tick += new EventHandler(Timer_Tick); dispatcherTimer.Interval = TimeSpan.FromMilliseconds(450 - Result.GetInstance().Level * 50); } protected Grid grid; /// <summary> /// 定义由四个方格组成的方块 /// </summary> protected IList<Rectangle> rectangles = new List<Rectangle>(4); DispatcherTimer dispatcherTimer; /// <summary> /// 当方块到达底部时触发的事件句柄 /// </summary> public event EventHandler OnBottom; /// <summary> /// 判断x行y列是否包含方格 /// </summary> protected bool Existence(int x, int y) { foreach (var r in grid.Children) { if (r is Rectangle) { if (this.rectangles.Contains(r as Rectangle)) return false; if (Convert.ToInt32((r as Rectangle).GetValue(Grid.ColumnProperty)) == x && Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)) == y) { return true; } } } return false; } /// <summary> /// 当前方块是否与其他方块重叠 /// </summary> public bool ISOverlapping() { foreach (var r in rectangles) { int x = Convert.ToInt32((r as Rectangle).GetValue(Grid.ColumnProperty)); int y = Convert.ToInt32((r as Rectangle).GetValue(Grid.RowProperty)); if (Existence(x, y)) return true; } return false; } /// <summary> /// 判断由数值 x,y标示的行列值是否在Grid范围内 /// </summary> protected bool InGrid(int x, int y) { if (x >= 12 || y >= 24 || x < 0 || y < 0) return false; return true; } /// <summary> /// 定义活动方块自动下降 /// </summary> public void AtuoDown() { dispatcherTimer.Start(); } private void Timer_Tick(object sender, EventArgs e) { if (!MoveDown()) { dispatcherTimer.Stop(); OnBottom(this, null); } } public abstract void Ready(); public abstract void ShowWating(ref Grid WaingGrid); protected bool Move(int _x, int _y) { if (IsPause) return false; for (int i = 0; i < 4; i++) { int x = Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty)) + _x; int y = Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + _y; if (Existence(x, y)) return false; if (!InGrid(x, y)) return false; } for (int i = 0; i < 4; i++) { rectangles[i].SetValue(Grid.ColumnProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty)) + _x); rectangles[i].SetValue(Grid.RowProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + _y); } return true; } public bool MoveUp() { return Move(0, -1); } public bool MoveDown() { return Move(0, 1); } public bool MoveLeft() { return Move(-1, 0); } public bool MoveRight() { return Move(1, 0); } /// <summary> /// 快速下降 /// </summary> public bool FastDown() { if (IsPause) return false; bool mark = false; int j = 0; while (!mark) { j++; for (int i = 0; i < 4; i++) { int x = Convert.ToInt32(rectangles[i].GetValue(Grid.ColumnProperty)); int y = Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + j; if (Existence(x, y) || !InGrid(x, y)) { j--; mark = true; } } } for (int i = 0; i < 4; i++) { rectangles[i].SetValue(Grid.RowProperty, Convert.ToInt32(rectangles[i].GetValue(Grid.RowProperty)) + j); } //OnBottom(this, null); return mark; } /// <summary> /// 当前方块是否处于暂停状态 /// </summary> private bool IsPause = false; public void Pause() { dispatcherTimer.IsEnabled = false; IsPause = true; } public void UnPause() { dispatcherTimer.IsEnabled = true; IsPause = false; } public void StopAction() { dispatcherTimer.Stop(); } /// <summary> /// 当前变形状态 /// </summary> protected Status ActivityStatus; /// <summary> /// 变形 /// </summary> public bool ChangeShape() { if (IsPause) return false; IList<Position> P = new List<Position>(4); for (int i = 0; i < 4; i++) P.Add(new Position()); P[0].x = Convert.ToInt32(rectangles[0].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[0].x; P[0].y = Convert.ToInt32(rectangles[0].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[0].y; if (ActivityStatus.NeedCheck[0]) if (Existence(P[0].x, P[0].y) || !InGrid(P[0].x, P[0].y)) return false; P[1].x = Convert.ToInt32(rectangles[1].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[1].x; P[1].y = Convert.ToInt32(rectangles[1].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[1].y; if (ActivityStatus.NeedCheck[1]) if (Existence(P[1].x, P[1].y) || !InGrid(P[1].x, P[1].y)) return false; P[2].x = Convert.ToInt32(rectangles[2].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[2].x; P[2].y = Convert.ToInt32(rectangles[2].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[2].y; if (ActivityStatus.NeedCheck[2]) if (Existence(P[2].x, P[2].y) || !InGrid(P[2].x, P[2].y)) return false; P[3].x = Convert.ToInt32(rectangles[3].GetValue(Grid.ColumnProperty)) + ActivityStatus.NextRelativeposition[3].x; P[3].y = Convert.ToInt32(rectangles[3].GetValue(Grid.RowProperty)) + ActivityStatus.NextRelativeposition[3].y; if (ActivityStatus.NeedCheck[3]) if (Existence(P[3].x, P[3].y) || !InGrid(P[3].x, P[3].y)) return false; for (int i = 0; i < 4; i++) { rectangles[i].SetValue(Grid.ColumnProperty, P[i].x); rectangles[i].SetValue(Grid.RowProperty, P[i].y); } ActivityStatus = ActivityStatus.Next; return true; } } “Z”形方块子类 class Box_Z : Box { public Box_Z(ref Grid grid) { this.grid = grid; for (int i = 0; i < 4; i++) rectangles[i].Fill = new SolidColorBrush(Colors.DarkOrange); } private void ShowAt(Position P, ref Grid grid) { rectangles[0].SetValue(Grid.ColumnProperty, P.x + 0); rectangles[0].SetValue(Grid.RowProperty, P.y + 0); rectangles[1].SetValue(Grid.ColumnProperty, P.x + 1); rectangles[1].SetValue(Grid.RowProperty, P.y + 0); rectangles[2].SetValue(Grid.ColumnProperty, P.x + 1); rectangles[2].SetValue(Grid.RowProperty, P.y + 1); rectangles[3].SetValue(Grid.ColumnProperty, P.x + 2); rectangles[3].SetValue(Grid.RowProperty, P.y + 1); for (int i = 0; i < 4; i++) grid.Children.Add(rectangles[i]); } public override void ShowWating(ref Grid WaingGrid) { ShowAt(new Position(1, 1), ref WaingGrid); } public override void Ready() { ShowAt(new Position(4, 0), ref grid); ActivityStatus = new Status(); ActivityStatus.NextRelativeposition.Add(new Position(1, 2)); ActivityStatus.NextRelativeposition.Add(new Position(0, 1)); ActivityStatus.NextRelativeposition.Add(new Position(1, 0)); ActivityStatus.NextRelativeposition.Add(new Position(0, -1)); ActivityStatus.NeedCheck.Add(true); ActivityStatus.NeedCheck.Add(false); ActivityStatus.NeedCheck.Add(false); ActivityStatus.NeedCheck.Add(true); ActivityStatus.Next = new Status(); ActivityStatus.Next.NextRelativeposition.Add(new Position(-1, -2)); ActivityStatus.Next.NextRelativeposition.Add(new Position(0, -1)); ActivityStatus.Next.NextRelativeposition.Add(new Position(-1, 0)); ActivityStatus.Next.NextRelativeposition.Add(new Position(0, 1)); ActivityStatus.Next.NeedCheck.Add(true); ActivityStatus.Next.NeedCheck.Add(true); ActivityStatus.Next.NeedCheck.Add(false); ActivityStatus.Next.NeedCheck.Add(false); ActivityStatus.Next.Next = ActivityStatus; } }   由于每种方块的变形方式都不一样,Z型有4种状态,I型有2中状态,而O型只有一种状态,现在需要描述方块形状状态,需要定义循环链表数据类型。    定义一个坐标点,描述位置和相对位置 /// <summary> /// 定义一个方格坐标点 /// </summary> 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; } }   /// <summary> /// 定义方块形状状态循环链表,标记变形状态 /// </summary> class Status { /// <summary> /// 方格[四个方块]下一次变形将要去的相对位置 /// </summary> public List<Position> NextRelativeposition = new List<Position>(4); /// <summary> /// 是否需要检查方块[每个方格]到这个位置的可行性 /// </summary> public List<bool> NeedCheck = new List<bool>(4); /// <summary> /// 指向下一状态 /// </summary> public Status Next; }  在方块子类中Ready方法即为每种方块设置状态链表。 由于方块的生成为随机方式,定义简单工厂模式生成方块如下: 代码 class BoxFactory { /// <summary> /// 随机方块工厂 /// </summary> 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); /// <summary> /// 定义活动方块自动下降 /// </summary> public void AtuoDown() { dispatcherTimer.Start(); }           private void Timer_Tick(object sender, EventArgs e)         {             if (!MoveDown())             {                 dispatcherTimer.Stop();                 OnBottom(this, null);             }         }   当方块到达底部时,事件通知容器类执行消层函数:   在Box中: /// <summary> /// 当方块到达底部时触发的事件句柄 /// </summary> public event EventHandler OnBottom; private void Timer_Tick(object sender, EventArgs e) { if (!MoveDown()) { dispatcherTimer.Stop(); OnBottom(this, null); } } 在Container中: ActivityBox.OnBottom += ActivityBox_OnBottom; /// <summary> /// 活动方块到达底部时触发 /// </summary> static public void ActivityBox_OnBottom(object sender, EventArgs e) { Result.GetInstance().CalculateScore(RemoveLine()); NewBoxReadyToDown(); } RemoveLine消层函数 /// <summary> /// 消层,并返回消除的层数 /// </summary> 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 Recta
展开阅读全文

开通  VIP会员、SVIP会员  优惠大
下载10份以上建议开通VIP会员
下载20份以上建议开通SVIP会员


开通VIP      成为共赢上传

当前位置:首页 > 包罗万象 > 大杂烩

移动网页_全站_页脚广告1

关于我们      便捷服务       自信AI       AI导航        抽奖活动

©2010-2026 宁波自信网络信息技术有限公司  版权所有

客服电话:0574-28810668  投诉电话:18658249818

gongan.png浙公网安备33021202000488号   

icp.png浙ICP备2021020529号-1  |  浙B2-20240490  

关注我们 :微信公众号    抖音    微博    LOFTER 

客服