这是“
使用 C# 开发智能手机软件:推箱子
”系列文章的第三篇。在这篇文章中,介绍 Common/Block.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”。
1
namespace
Skyiv.Ben.PushBox.Common
2 {
3 /// <summary>
4 /// 基本单元格: 地 槽 墙 砖 箱子 工人
5 /// </summary>
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 }
104
静态类 Block 用来表示基本单元格: 空地、槽(箱子终于要存放的目的地)、墙、砖(在本程序中等同于“墙”。一般放在墙的外围,使图形看起来美丽些)、箱子、工人。当中“箱子”和“工人”都能够位于“空地”或“槽”上,所以总共同拥有八种状态,用 0 到 7 表示,总共仅仅须要三个二进位,能够放入一个字节中。在数据文件(*.bxb)中。每一个基本单元格就是用一个字节储存的,这在以后介绍的 Common/DataFile.cs 源程序文件里会看到。
可是为什么静态类 Block 的大多数方法的參数都是 ushort 类型呢?
这是为了寻找工人最短移动路线算法的须要,看了下一篇介绍 Common/FindPath.cs 源程序文件的文章就会明确了。
2 {
3 /// <summary>
4 /// 基本单元格: 地 槽 墙 砖 箱子 工人
5 /// </summary>
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 }
104
这个类还是比較简单的。现简要说明例如以下:
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”。