推箱子的配置文件(PushBox.cfg)是一个 xml 文件,格式如下所示:
<PushBox>
<files>
<file>konka</file>
<file>boxworld</file>
<file>lenovo</file>
<file>sokoban</file>
</files>
<option stepdelay="100" save="True" replaydelay="300" maxlevelsize="32" />
<stack group="2" level="13" data="NEEQQTJMCDDCCBLTJJMCCBBESMDDDEEBBE" />
</PushBox>
“<files>”元素表示组信息(在“配置”对话框中设定,如下面右图所示,每一行表示一组,对应一个“<file>”元素)。
“<option>”元素表示配置信息(在“选项”对话框中设定,如下面左图所示,“移动速度”对应“stepdelay”属性,“回放速度”对应“replaydelay”属性,“最大关尺寸”对应“maxlevelsize”属性,“保护现场”对应“save”属性)。
“<stack>”元素表示走法步骤信息(“group”属性表示当前组,“level”属性表示当前关,“data”属性表示当前走法步骤)。也就是推箱子程序退出时的“现场”,用于程序下次启动时恢复现场。
1 using System;
2 using System.IO;
3 using System.Xml;
4 using System.Text;
5
6 namespace Skyiv.Ben.PushBox.Common
7 {
8 /// <summary>
9 /// 管理配置文件: PushBox.cfg
10 /// </summary>
11 sealed class ConfigFile
12 {
13 const string ElmRoot = "PushBox"; // 配置文件的根元素
14 const string ElmFiles = "files";
15 const string ElmOption = "option";
16 const string AttrMaxLevelSize = "maxlevelsize";
17 const string AttrStepDelay = "stepdelay";
18 const string AttrReplayDelay = "replaydelay";
19 const string AttrSave = "save";
20 const string ElmStack = "stack";
21 const string AttrGroup = "group";
22 const string AttrLevel = "level";
23 const string AttrData = "data";
24
25 int maxLevelSize; // 最大关尺寸(宽度和高度)
26 int stepDelay; // 移动时间间隔(毫秒)
27 int replayDelay; // 回放时间间隔(毫秒)
28 bool isSave; // 是否保护现场
29 bool isSaveOem; // 是否保护现场(第一次读取时的值)
30 int group; // 当前组数(0起始)
31 string[] groups; // 各组的数据文件主名
32 int[] levels; // 指明各组的当前关数(0起始)
33 string steps; // 工人移动路线,用于程序启动时恢复现场
34
35 public int MaxLevelSize { get { return maxLevelSize; } set { maxLevelSize = value; } }
36 public int StepDelay { get { return stepDelay; } set { stepDelay = value; } }
37 public int ReplayDelay { get { return replayDelay; } set { replayDelay = value; } }
38 public bool IsSave { get { return isSave; } set { isSave = value; } }
39 public int Group { get { return group; } set { group = value; } }
40 public string[] Groups { get { return groups; } }
41 public int[] Levels { get { return levels; } }
42 public string Steps { get { return steps; } }
43
44 /// <summary>
45 /// 装入配置文件
46 /// </summary>
47 public void LoadConfig()
48 {
49 maxLevelSize = Pub.DefaultMaxLevelSize;
50 stepDelay = Pub.DefaultStepDelay;
51 replayDelay = Pub.DefaultReplayDelay;
52 isSave = isSaveOem = false;
53 group = 0;
54 int level = 0;
55 XmlDocument doc = new XmlDocument();
56 doc.Load(Pub.ConfigFileName);
57 XmlElement elm = doc.DocumentElement[ElmOption];
58 XmlAttributeCollection attrs;
59 XmlAttribute attr;
60 if (elm != null)
61 {
62 attrs = elm.Attributes;
63 if ((attr = attrs[AttrMaxLevelSize]) != null)
64 {
65 try { maxLevelSize = int.Parse(attr.Value); }
66 catch { }
67 if (maxLevelSize < 1) maxLevelSize = 1;
68 }
69 if ((attr = attrs[AttrStepDelay]) != null)
70 {
71 try { stepDelay = int.Parse(attr.Value); }
72 catch { }
73 if (stepDelay < 0) stepDelay = 0;
74 if (stepDelay > Pub.MaxDelay) stepDelay = Pub.MaxDelay;
75 }
76 if ((attr = attrs[AttrReplayDelay]) != null)
77 {
78 try { replayDelay = int.Parse(attr.Value); }
79 catch { }
80 if (replayDelay < 0) replayDelay = 0;
81 if (replayDelay > Pub.MaxDelay) replayDelay = Pub.MaxDelay;
82 }
83 if ((attr = attrs[AttrSave]) != null)
84 {
85 try { isSave = isSaveOem = bool.Parse(attr.Value); }
86 catch { }
87 }
88 if (isSave && (elm = doc.DocumentElement[ElmStack]) != null)
89 {
90 attrs = elm.Attributes;
91 if ((attr = attrs[AttrGroup]) != null)
92 {
93 try { group = int.Parse(attr.Value) - 1; }
94 catch { }
95 }
96 if ((attr = attrs[AttrLevel]) != null)
97 {
98 try { level = int.Parse(attr.Value) - 1; }
99 catch { }
100 }
101 if ((attr = attrs[AttrData]) != null)
102 {
103 steps = attr.Value;
104 }
105 }
106 }
107 elm = doc.DocumentElement[ElmFiles];
108 if (elm == null) throw new Exception("配置文件错:缺少<" + ElmFiles +">元素");
109 XmlNodeList elms = elm.ChildNodes;
110 if (elms.Count < 1) throw new Exception("配置文件错:<" + ElmFiles + ">元素必须至少包括一项");
111 groups = new string[elms.Count];
112 levels = new int[elms.Count];
113 for (int i = 0; i < elms.Count; i++) groups[i] = elms[i].InnerText;
114 if (group < 0) group = 0;
115 if (group > groups.Length - 1) group = groups.Length - 1;
116 if (level < 0) level = 0;
117 levels[group] = level;
118 }
119
120 /// <summary>
121 /// 保存组信息到配置文件
122 /// </summary>
123 /// <param name="groups">组信息</param>
124 public void SaveConfig(string[] groups)
125 {
126 XmlDocument doc = new XmlDocument();
127 if (File.Exists(Pub.ConfigFileName)) doc.Load(Pub.ConfigFileName);
128 else
129 {
130 XmlElement root = doc.CreateElement(ElmRoot);
131 root.AppendChild(doc.CreateElement(ElmFiles));
132 doc.AppendChild(root);
133 }
134 XmlElement files = (doc.DocumentElement)[ElmFiles];
135 if (files == null)
136 {
137 files = doc.CreateElement(ElmFiles);
138 doc.DocumentElement.AppendChild(files);
139 }
140 files.RemoveAll();
141 foreach (string s in groups)
142 {
143 XmlElement file = doc.CreateElement("file");
144 file.InnerText = s;
145 files.AppendChild(file);
146 }
147 SaveStack(doc, 0, 0, "");
148 doc.Save(Pub.ConfigFileName);
149 }
150
151 /// <summary>
152 /// 保存当前选项及当前走法到配置文件
153 /// </summary>
154 /// <param name="steps">当前走法</param>
155 public void SaveConfig(Step[] steps)
156 {
157 if (!isSave && isSave == isSaveOem) return; // “保护现场”复选框没有选中,且程序启动时就没有选中
158 XmlDocument doc = new XmlDocument();
159 doc.Load(Pub.ConfigFileName);
160 XmlElement elm = doc.DocumentElement[ElmOption];
161 if (elm == null)
162 {
163 elm = doc.CreateElement(ElmOption);
164 doc.DocumentElement.AppendChild(elm);
165 }
166 elm.SetAttribute(AttrSave, isSave.ToString()); // 保存“保护现场”复选框的状态
167 if (isSave) // “保护现场”复选框已选中
168 {
169 elm.SetAttribute(AttrMaxLevelSize, maxLevelSize.ToString()); // 保存“最大关尺寸”
170 elm.SetAttribute(AttrStepDelay, stepDelay.ToString()); // 保存“移动速度”
171 elm.SetAttribute(AttrReplayDelay, replayDelay.ToString()); // 保存“回放速度”
172 SaveStack(doc, group, levels[group], Pub.ToString(steps)); // 保存当前组数、当前关数和当前走法
173 }
174 doc.Save(Pub.ConfigFileName);
175 }
176
177 /// <summary>
178 /// 保存当前组数、当前关数和当前走法到配置文件
179 /// </summary>
180 /// <param name="doc">配置文件</param>
181 /// <param name="group">当前组数</param>
182 /// <param name="level">当前关数</param>
183 /// <param name="steps">当前走法</param>
184 void SaveStack(XmlDocument doc, int group, int level, string steps)
185 {
186 XmlElement elm = doc.DocumentElement[ElmStack];
187 if (elm == null)
188 {
189 elm = doc.CreateElement(ElmStack);
190 doc.DocumentElement.AppendChild(elm);
191 }
192 elm.SetAttribute(AttrGroup, (group + 1).ToString()); // 保存当前组数
193 elm.SetAttribute(AttrLevel, (level + 1).ToString()); // 保存当前关数
194 elm.SetAttribute(AttrData, steps); // 保存当前走法
195 }
196 }
197 }
198
密封类 ConfigFile 用来管理推箱子的配置文件。主是用于以下方面:
1. 推箱子程序启动时或者其他必要情况下读取配置文件(LoadConfig() 方法)。
2. 推箱子程序退出时保存配置信息和走法步骤到配置文件中(SaveConfig(Step[] steps) 方法)。
3. 在“配置”对话框中点击“保存”按钮时保存组信息到配置文件中(SaveConfig(string[] groups) 方法)。
注意,如果在保存配置文件的时候发现配置文件不存在,该程序会自动创建一个空的配置文件。
.NET Compact Framework 不支持各基本类型(int、bool)的 TryParse 方法,只好将 Parse 方法放在 try 块中。
版权声明:本文为博主http://www.zuiniusn.com原创文章,未经博主允许不得转载。