扫一扫
分享文章到微信
扫一扫
关注官方公众号
至顶头条
DataFile db; // 数据文件
ConfigFile cfg; // 配置文件
正是我们以前介绍过的管理数据文件的密封类 DataFile 和管理配置文件的密封类 ConfigFile 的实例。密封类 Env 中的不少属性和方法是通过这两个字段调用其各自的属性和方法。
下面对密封类 Env 中的一些方法作点说明:
GetClientSize 方法用来计算当使用标准箱子尺寸时主窗体客户区的尺寸。该方法仅当程序运行在计算机上时才会被调用,使主窗体的尺寸根据当前关的尺寸自动调整。程序运行在
SetBoxInfo 方法的作用是根据客户区尺寸计算箱子的尺寸,并相应设定要显示的图形单元。图形单元共有 24x24、20x20、16x16 和 12x12 四种尺寸,如下所示:
如果使用 12x12 的图形单元还不能在客户区完整显示地图的话,可能这一关的游戏就无法玩了。
Draw 方法用来更新主窗体客户区,也就是在主窗体客户区画出本关的地图,并根据玩家的动作随时更新地图。
Design 方法实现在
StepIt 方法实现工人往指定方向前进一步(可能推着箱子)。
Back 方法实现工人后退一步(可能连带箱子一起后退)。
GetMoveInfo 方法寻找一条将工人移动到鼠标点击的位置的路线。她调用我们以前介绍过的静态类 FindPath 的 Seek 方法来寻找最短路线。
GetPushInfo 方法给出将箱子推动到鼠标点击的位置所需的
到此为止,Common 目录下所有源程序文件都介绍完了,这些源程序文件中包含的类是实现整个程序功能的
下面就是密封类 Env 的源程序代码,虽然稍微长了一点,但是里面的注释比较详细,应该不难理解。
以下是引用片段: 1using System; 2using System.Drawing; 3using System.Collections.Generic; 4 5namespace Skyiv.Ben.PushBox.Common 6{ 7 /**//// 8 /// 工作环境 9 /// 10 sealed class Env : IDisposable 11 { 12 DataFile db; // 数据文件 13 ConfigFile cfg; // 配置文件 14 string errorMsg; // 错误信息 15 string debugMsg; // 调试信息 16 bool isReplay; // 是否正在回放 17 Action active; // 模式: 正常 新建 编辑 删除 18 byte pen; // 设计时的笔 19 Bitmap img; // 图形单元, 横向被均匀分为八份 20 Stack stack; // 历史路线, 用于后退功能 21 Size clientSize; // 工作区域尺寸(以像素为单位) 22 Size boxSize; // 图形元素尺寸(以像素为单位) 23 Point toPixel; // 将要到达的位置(以像素为单位) 24 Point worker; // 当前工人位置(以单元格为单位) 25 int pushSteps; // 推动着箱子走的步数 26 int levelOem; // 原来的关数,仅用于“菜单 -> 数据 -> 设计 -> 新建”放弃后恢复现场 27 28 public string ErrorMsg { get { return errorMsg; } } 29 public string DebugMsg { get { return debugMsg; } } 30 public string[] Groups { get { return cfg.Groups; } } 31 public int Group { get { return cfg.Group; } set { cfg.Group = value; } } 32 public int Level { get { return cfg.Levels[Group]; } set { cfg.Levels[Group] = value; } } 33 public int LeveLOem { get { return levelOem; } } 34 public int MaxLevel { get { return db.MaxLevel; } } 35 public string Steps { get { return cfg.Steps; } } 36 public Size LevelSize { get { return db.LevelSize; } } 37 public Size ClientSize { set { clientSize = value; } } 38 public Point ToPixel { set { toPixel = value; } } 39 public int MaxLevelSize { get { return cfg.MaxLevelSize; } set { cfg.MaxLevelSize = value; } } 40 public int StepDelay { get { return cfg.StepDelay; } set { cfg.StepDelay = value; } } 41 public int ReplayDelay { get { return cfg.ReplayDelay; } set { cfg.ReplayDelay = value; } } 42 public Action Active { get { return active; } set { active = value; } } 43 public byte Pen { get { return pen; } set { pen = value; } } 44 public bool HasError { get { return !string.IsNullOrEmpty(errorMsg); } } 45 public bool HasWorker { get { return db.HasWorker; } } 46 public bool CanUndo { get { return stack.Count != 0; } } 47 public bool CanReplay { get { return db.IsFinished && !CanUndo; } } 48 public bool IsSave { get { return cfg.IsSave; } set { cfg.IsSave = value; } } 49 public bool IsFinish { get { return db.Tasks == db.Boths; } } 50 public bool IsReplay { get { return isReplay; } set { isReplay = value; } } 51 public bool IsDesign { get { return active != Action.None; } } 52 53 public Env() 54 { 55 stack = new Stack(); 56 cfg = new ConfigFile(); 57 db = new DataFile(); 58 Init(); 59 } 60 61 /**//// 62 /// 状态栏信息 63 /// 64 public string StatusMessage 65 { 66 get 67 { 68 return HasError ? "请点击“菜单 -> 帮助 -> 错误信息”" : string.Format( 69 "{0} {1}/{2} {3} {4} {5} [{6}] {7}", 70 (active == Action.Create) ? '+' : (active == Action.Edit) ? '=' : isReplay ? "|/-\\"[stack.Count % 4] : '>', 71 Level + 1, MaxLevel, Pub.ToString(LevelSize), 72 IsDesign ? string.Format("{0}={1}", db.Boxs, db.Slots) : string.Format("{0}/{1}", db.Boths, db.Tasks), 73 IsDesign ? Block.GetPenName(pen) : string.Format("{0}({1})", stack.Count, pushSteps), 74 IsDesign ? (active == Action.Create ? "新建" : "编辑") : db.IsFinished ? 75 string.Format("{0}({1})", db.MovedSteps, db.PushedSteps) : string.Empty, 76 db.GroupName); 77 } 78 } 79 80 public void Dispose() 81 { 82 db.Dispose(); 83 } 84 85 public void Init() 86 { 87 active = Action.None; 88 pen = Block.Land; 89 stack.Clear(); 90 SetExceptionMessage(null); 91 } 92 93 void SetExceptionMessage(Exception ex) 94 { 95 errorMsg = Pub.GetMessage(ex, false); 96 debugMsg = Pub.GetMessage(ex, true); 97 } 98 99 /**//// 100 /// 计算当使用标准箱子尺寸时主窗体客户区的尺寸 101 /// 102 /// 状态条的高度 103 /// 客户区的尺寸 104 public Size GetClientSize(int statusBarHeight) 105 { 106 int width = (Properties.Resources.PushBox24.Width / 8) * LevelSize.Width; 107 int height = Properties.Resources.PushBox24.Height * LevelSize.Height + statusBarHeight; 108 if (width < 240) width = 240; 109 if (height < 48) height = 48; 110 if (width > 1008) width = 1008; 111 if (height > 672) height = 672; 112 return new Size(width, height); 113 } 114 115 /**//// 116 /// 根据客户区尺寸,计算箱子的尺寸,并相应设定要显示的图形单元 117 /// 118 public void SetBoxInfo() 119 { 120 if (HasError) return; 121 if (LevelSize.IsEmpty) return; 122 int rX = clientSize.Width / LevelSize.Width; 123 int rY = clientSize.Height / LevelSize.Height; 124 int r = Math.Min(rX, rY); 125 if (r >= 24) img = Properties.Resources.PushBox24; 126 else if (r >= 20) img = Properties.Resources.PushBox20; 127 else if (r >= 16) img = Properties.Resources.PushBox16; 128 else img = Properties.Resources.PushBox12; 129 boxSize = new Size(img.Height, img.Width / 8); 130 } 131 132 /**//// 133 /// 装入配置文件 134 /// 135 public void LoadConfig() 136 { 137 if (HasError) return; 138 try 139 { 140 cfg.LoadConfig(); 141 } 142 catch (Exception ex) 143 { 144 SetExceptionMessage(ex); 145 } 146 } 147 148 /**//// 149 /// 保存组信息到配置文件 150 /// 151 /// 组信息 152 public void SaveConfig(string[] groups) 153 { 154 if (HasError) return; 155 try 156 { 157 cfg.SaveConfig(groups); 158 } 159 catch (Exception ex) 160 { 161 SetExceptionMessage(ex); 162 } 163 } 164 165 /**//// 166 /// 保存当前选项及当前走法到配置文件 167 /// 168 public void SaveConfig() 169 { 170 if (HasError) return; 171 try 172 { 173 cfg.SaveConfig(stack.ToArray()); 174 } 175 catch (Exception ex) 176 { 177 SetExceptionMessage(ex); 178 } 179 } 180 181 /**//// 182 /// 装入当前组信息 183 /// 184 public void LoadGroup() 185 { 186 if (HasError) return; 187 try 188 { 189 db.LoadGroup(Groups[Group]); 190 } 191 catch (Exception ex) 192 { 193 SetExceptionMessage(ex); 194 } 195 } 196 197 /**//// 198 /// 装入当前关信息 199 /// 200 public void LoadLevel() 201 { 202 active = Action.None; 203 if (HasError) return; 204 try 205 { 206 db.LoadLevel(Level); 207 worker = db.Worker; 208 stack.Clear(); 209 pushSteps = 0; 210 isReplay = false; 211 } 212 catch (Exception ex) 213 { 214 SetExceptionMessage(ex); 215 } 216 } 217 218 /**//// 219 /// 新建一关 220 /// 221 /// 是否复制当前关 222 /// 新建关的尺寸 223 public void NewLevel(bool isCopy, Size size) 224 { 225 if (HasError) return; 226 try 227 { 228 levelOem = Level; 229 Level = MaxLevel; 230 db.NewLevel(isCopy, size); 231 } 232 catch (Exception ex) 233 { 234 SetExceptionMessage(ex); 235 } 236 } 237 238 /**//// 239 /// 给出通关步骤 240 /// 241 /// 通关步骤 242 public string GetSteps() 243 { 244 string steps = ""; 245 if (!HasError) 246 { 247 try 248 { 249 steps = db.GetSteps(Level); 250 } 251 catch (Exception ex) 252 { 253 SetExceptionMessage(ex); 254 } |
如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。
现场直击|2021世界人工智能大会
直击5G创新地带,就在2021MWC上海
5G已至 转型当时——服务提供商如何把握转型的绝佳时机
寻找自己的Flag
华为开发者大会2020(Cloud)- 科技行者