使用 C# 开发智能手机软件:推箱子(九)

推箱子的配置文件(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原创文章,未经博主允许不得转载。

时间: 2024-07-29 05:19:11

使用 C# 开发智能手机软件:推箱子(九)的相关文章

使用 C# 开发智能手机软件:推箱子(四)

这是"使用 C# 开发智能手机软件:推箱子"系列文章的第四篇. 在这篇文章中,介绍 Common/FindPath.cs 源程序文件. using System; using System.Drawing; using System.Collections.Generic; namespace Skyiv.Ben.PushBox.Common { /// <summary> /// 寻找最短路线 /// </summary> static class FindP

使用 C# 开发智能手机软件:推箱子(十二)

这是"使用 C# 开发智能手机软件:推箱子"系列文章的第十二篇.在这篇文章中,介绍 Window/AboutDlg.cs 源程序文件. 这个源程序文件包括 AboutDlg 类,该类继承自 System.Windows.Forms.Form 类.表示推箱子的"关于"对话框.例如以下图所看到的:     以下是 Window/AboutDlg.Designer.cs 源程序的部分代码: namespace Skyiv.Ben.PushBox.Window { part

使用 C# 开发智能手机软件:推箱子(十八)

这是"使用 C# 开发智能手机软件:推箱子" 系列文章的第十八篇.在这篇文章中.介绍 Window/SelectLevelDlg.cs 源程序文件. 这个源程序文件包括 SelectLevelDlg 类,该类继承自 System.Windows.Forms.Form 类.表示推箱子的"选关"对话框.例如以下图所看到的: 以下是 Window/SelectLevelDlg.Designer.cs 的源程序的部分代码: namespace Skyiv.Ben.PushB

使用 C# 开发智能手机软件:推箱子(三)

这是"使用 C# 开发智能手机软件:推箱子"系列文章的第三篇.在这篇文章中,介绍 Common/Block.cs 源程序文件. 1 namespace Skyiv.Ben.PushBox.Common 2 { 3   /// <summary> 4   /// 基本单元格: 地 槽 墙 砖 箱子 工人 5   /// </summary> 6   static class Block 7   { 8     public const byte Land = 0;

使用 C# 开发智能手机软件:推箱子(二)

在上篇文章"使用 C# 开发智能手机软件:推箱子(一)"中.我对推箱子程序作了整体介绍.这次,我先介绍 Common/Fcl.cs 源程序文件. 1 using System; 2 using System.IO; 3 using System.Drawing; 4 5 namespace Skyiv.Ben.PushBox.Common 6 { 7   /// <summary> 8   /// 这里是 .NET Framework 支持.而 .NET Compact F

使用 C# 开发智能手机软件:推箱子(十四)

这是"使用 C# 开发智能手机软件:推箱子"系列文章的第十四篇.在这篇文章中,介绍 Window/ErrorMsgDlg.cs 源程序文件.这个源程序文件包括 ErrorMsgDlg 类.该类继承自 System.Windows.Forms.Form 类,表示推箱子的"错误信息"对话框.例如以下图所看到的:   以下是 Window/ErrorMsgDlg.Designer.cs 源程序的部分代码: namespace Skyiv.Ben.PushBox.Windo

使用 C# 开发智能手机软件:推箱子(七)

这是"使用 C# 开发智能手机软件:推箱子"系列文章的第七篇.在这篇文章中,介绍 Common/Step.cs 源程序文件. 1namespace Skyiv.Ben.PushBox.Common 2{ 3  enum Direction { None, East, South, West, North } // 方向: 无 东 南 西 北 4  public enum Action { None, Create, Edit, Delete } // 设计: 无 创建 编辑 删除 5

使用 C# 开发智能手机软件:推箱子(六)

这是"使用 C# 开发智能手机软件:推箱子"系列文章的第六篇.在这篇文章中,介绍 Common/Pub.cs 源程序文件. 1 using System; 2 using System.Drawing; 3 using System.Text; 4 using System.IO; 5 using System.Reflection; 6 7 namespace Skyiv.Ben.PushBox.Common 8 { 9   /// <summary> 10   /// 

使用 C# 开发智能手机软件:推箱子(十七)

这是"使用 C# 开发智能手机软件:推箱子" 系列文章的第十七篇.在这篇文章中,介绍 Window/SelectGroupDlg.cs 源程序文件.这个源程序文件包含 SelectGroupDlg 类,该类继承自 System.Windows.Forms.Form 类,表示推箱子的"选组"对话框.如下图所示: 下面是 Window/SelectGroupDlg.Designer.cs 的源程序的部分代码: namespace Skyiv.Ben.PushBox.Wi

使用 C# 开发智能手机软件:推箱子(十六)

这是"使用 C# 开发智能手机软件:推箱子" 系列文章的第十六篇.在这篇文章中,介绍 Window/ConfigDlg.cs 源程序文件.这个源程序文件包含 ConfigDlg 类,该类继承自 System.Windows.Forms.Form 类,表示推箱子的"配置"对话框.如下图所示: 下面是 Window/ConfigDlg.Designer.cs 的源程序的部分代码: namespace Skyiv.Ben.PushBox.Window { partial