這是“使用 C# 開發智能手機軟件:推箱子”系列文章的第三篇。在這篇文章中,介紹 Common/Block.cs 源程序文件。
以下是引用片段:
1 namespace Skyiv.Ben.PushBox.Common
2 {
3 ///
4 /// 基本單元格: 地 槽 牆 磚 箱子 工人
5 ///
6 static class Block
7 {
8 public const byte Land = 0; // 地
9 public const byte Slot = 1; // 槽
10 public const byte Wall = 2; // 牆
11 public const byte Brick = 3; // 磚: 等同於牆,一般放在牆的外圍
12 public const byte Box0 = 4; // 箱子放在地上
13 public const byte Box1 = 5; // 箱子放在槽上
14 public const byte Man0 = 6; // 工人站在地上
15 public const byte Man1 = 7; // 工人站在槽上
16
17 const string mask = "-+#%xX()"; // (*.bxa)文件用,依次代表以上各項
18
19 public static string GetPenName(byte block)
20 {
21 return "地槽牆磚箱箱人人"[block & 0x07].ToString();
22 }
23
24 public static char GetChar(ushort block)
25 {
26 return mask[block & 0x07];
27 }
28
29 public static byte GetByte(char block)
30 {
31 return (byte)mask.IndexOf(block);
32 }
33
34 public static bool IsOk(ushort block)
35 {
36 return block <= Man1;
37 }
38
39 public static void CleanAllMark(ushort[,] bb)
40 {
41 for (int i = 0; i < bb.GetLength(0); i++)
42 for (int j = 0; j < bb.GetLength(1); j++)
43 bb[i, j] &= 0x07;
44 }
45
46 public static void Mark(ref ushort block, int value)
47 {
48 block |= (ushort)(value << 3);
49 }
50
51 public static int Value(ushort block)
52 {
53 return block >> 3;
54 }
55
56 public static void Update(ref ushort block, byte pen)
57 {
58 if (IsSlot(block) && pen == Block.Man0) pen = Block.Man1;
59 if (IsSlot(block) && pen == Block.Box0) pen = Block.Box1;
60 block = pen;
61 }
62
63 public static void ManIn(ref ushort block)
64 {
65 block += (Man0 - Land);
66 }
67
68 public static void ManOut(ref ushort block)
69 {
70 block -= (Man0 - Land);
71 }
72
73 public static void BoxIn(ref ushort block)
74 {
75 block += (Box0 - Land);
76 }
77
78 public static void BoxOut(ref ushort block)
79 {
80 block -= (Box0 - Land);
81 }
82
83 public static bool IsSlot(ushort block)
84 {
85 return block == Slot || block == Box1 || block == Man1;
86 }
87
88 public static bool IsBlank(ushort block)
89 {
90 return block == Land || block == Slot;
91 }
92
93 public static bool IsBox(ushort block)
94 {
95 return block == Box0 || block == Box1;
96 }
97
98 public static bool IsMan(ushort block)
99 {
100 return block == Man0 || block == Man1;
101 }
102 }
103 }
靜態類 Block 用來表示基本單元格: 空地、槽(箱子最終要存放的目的地)、牆、磚(在本程序中等同於“牆”,一般放在牆的外圍,使圖形看起來漂亮些)、箱子、工人。其中“箱子”和“工人”都可以位於“空地”或“槽”上,所以總共有八種狀態,用 0 到 7 表示,總共只需要三個二進位,可以放入一個字節中。在數據文件(*.bxb)中,每個基本單元格就是用一個字節儲存的,這在以後介紹的 Common/DataFile.cs 源程序文件中會看到。但是為什麼靜態類 Block 的大多數方法的參數都是 ushort 類型呢?這是為了尋找工人最短移動路線算法的需要,看了下一篇介紹 Common/FindPath.cs 源程序文件的文章就會明白了。
這個類還是比較簡單的,現簡要說明如下:
GetPenName 方法返回在設計關卡時所用畫筆的名稱。
Update 方法用來在設計關卡時更新地圖中的基本單元格。
GetChar 方法返回將數據文件(data/*.bxb)導出為文本文件(text/*.bxa)所用的字符。
GetByte 方法返回將文本文件(text/*.bxa)導入為數據文件(data/*.bxb)所用的字節。
IsOk 方法判斷表示基本單元格的字節是否合法,也用在數據導入時。
Mark 方法在尋找工人最短移動路線算法中用來標記已經搜索過的基本單元格。
CleanAllMark 方法在上述算法結束時用來清除地圖中的所有基本單元格的標記。
Value 方法返回上述算法搜索過程中所作的標記。
ManIn、ManOut、BoxIn、BoxOut 方法用來更新推箱子過程中地圖各基本單元格的狀態。
IsSlot、IsBlank、IsBox、IsMan 方法用來判斷各基本單元格的類型。
補充:尋找工人最短移動路線的算法已經作了改進,地圖使用 byte 存儲就行了,所以靜態類 Block 中的所有“ushort”都要修改為“byte”。請參見“使用 C# 開發智能手機軟件:推箱子(五)”中的說明。