{
承上篇
介绍一下对于bloxorz的程序解决方法
Bloxorz果然是这几个游戏中
最奇妙 最有趣 最复杂的
这几天净绕着这个程序转了
不堪回首
}
//建议玩一玩之后再行阅读本文
BloxOrz
据某神解释 Blox就是方块 Orz就是你玩不出来的状态
这名字好邪恶
刚推出的时候号称全世界就4个人玩的过
我下载手动通关也就3个小时左右
相当自豪啊 不过当时好像Orz了几次 都撑过去了
当时没想过去用程序做
现在想到了 就试着做了一下
写程序Orz了好久 比自己玩Orz的程度还要深
主要是游戏的细节比较多
可见细节决定成败啊
先介绍一下规则吧 比前2篇的游戏复杂多了
*首先你有一个1*1*2的方块 可以滚来滚去
*游戏目标要滚进洞里
*地上有各种机关各种地形 这就是它的复杂之处
(具体在程序实现时会讲 先略过)
*不准让方块的任何一部分超出界外 不然就会死惨
先分析一下具体实现用什么算法
我曾经用2500步走完33关
所以估计平均解决一局70+步
然后分析有多少不同的状态
每步4个方向 一共70步 是4^70=10^42种状态吗?
不是 这样分析是错误的
如果真是这样我也不会用搜索来解决了
因为任何搜索也受不了这么大的状态数
我们考虑方块在地图上的摆放方式和地图的情况来确定状态数量
方块的摆放方式就是方块是如何放在地图上的
可以横放 竖放 立放 还可以分置
地图的情况主要是桥的情况
什么是桥呢 桥就是由开关控制的可以动的道路
开关就是和 桥就是
以相应的方式 在相应的时候 踩到相应的开关 就会触发相应的桥事件
显然如果桥的情况相同 方块摆放也相同 这就是同一种状态
所以状态数就是方块摆放状态数*桥的状态数
在桥不超过6个 地图最大为10*15情况下
状态数的上界为:[C(1,150)+C(2,150)]*(2^6)=144w
这样的话普通的BFS就可就以解决 用A*更好 启发函数就可以从曼哈顿距离一方面考虑
决定用什么方法解决实际问题 是解决问题的第一步 也是最关键的一步
我觉得 真正程序实现其实不如以上这些分析来的重要
然后是确定如何存储状态
有了上面的分析 状态存储也变得简单了
我用的是sx[] x1[] y1[] x2[] y2[] f[]记录方块的状态
sx[]记录方块是什么摆放方式 1:立放 2:横放 3:竖放 4:分置
x1[] y1[] x2[] y2[]就是记录的方块的具体位置
sx[]=1时 x2[] y2[]都为0
sx[]=2,3时 分别记录每一半的位置 当然是相连的2个位置
sx[]=4时 也是记录每一半的位置 此时是不相邻的
f[]记录当sx[]=4时 当前操作的是哪半块
用br[]记录每个桥的开关状态
之后是由现有状态生成新状态
分sx[]的情况讨论
向四个方向需要如何改变方块状态 分别枚举即可
方块确定后判断是否符合要求
是否出界/踩到没开的桥上
是否立放踩到黄砖 等等
确定合法后看是否触发开关 如果触发了就生成新的桥的状态
然后用hash表+BKDRhash判重
当sx[]=1 且到达洞口位置就说明出解了
输入输出比较复杂
需要说明一下输入输出
Sample1.in
{第16关地图}
7 13 //描述地图大小
T +++
U+VaaAB+bb+Z+
W +++
+++ +++
+Y+++++X+ //描述地图情况 A-S表示桥开关 T-X表示分置开关 Y是开始位置 Z是洞口 a-z为桥
+++ +++ //黄地砖为- 白地砖为+ 没有地砖的地方补上空格
T 2 8 2 6
U 2 3 1 2
V 2 1 2 3
W 3 2 2 1 //描述分置开关的情况 每行一个分置开关 后面2个坐标 表示分置到哪里
X 1 2 2 1 //前一个坐标是分置之后的 当前操作位置(*1)
A T X a
B T X b //描述桥开关 T/F表示开关种类(*2) X/O是开关形状 之后是开关所控制的桥
a 0
b 0 //描述桥的初始状态 0为关 1为开
注释 *1 踩到分置开关分开后 有半块是当前可以操作的(带[]的) 要操作另一个需要用Space键切换
*2 开关有3种 只能把桥关掉的 只能把桥开启的 和踩到就改变桥状态的
我把后面2种都看成1种了 算是一个bug 不高兴改了 没什么影响 就是很少情况下步数要多一些
Sample1.out
28 //总步数 空格不计
RRRR RD RU RLLLRRRRLLLLLD RU RRR //'L','R','D','U'为方向键 ' '为按Space键切换
Sample2.in
{最后一关地图}
10 15
++A+++
++++++b
+++ B++C+++++
+Y+aa++++DE++F
++G++H+++
++++++I++
+++ ++++++J+++
+Z+cc+K+ +++LM
+++ +++ ++++
+++ +++
A F O c
B F O c
C F O c
D F O c
E F O c
F F O c
G F O c
H F O c
I F O c
J F O c
K F O c
L F O c
M T X b
a 1
b 0
c 1
Sample2.out
65
RRRRULDDLURUURRDRDRULLURDRDDRDLDDRRUDLLUURULUULULDRULLLDDDLDLLDLU
这样对Bloxorz的程序解决就完成了
当这个游戏出续集的时候我会考虑用A*做做的 嘿嘿
给代码
1 { $I+,Q+,R+,S+ }
2 const maxn = 15 ;
3 maxk = 10 ;
4 maxq = 20000 ;
5 base = $FFFF;
6 but: set of char = [ ' A ' .. ' S ' ];
7 sep: set of char = [ ' T ' .. ' X ' ];
8 bri: set of char = [ ' a ' .. ' z ' ];
9 dx: array [ 1 .. 4 ] of longint = ( 0 , 1 , 0 , - 1 );
10 dy: array [ 1 .. 4 ] of longint = ( 1 , 0 , - 1 , 0 );
11 dc: array [ 1 .. 4 ] of char = ( ' R ' , ' D ' , ' L ' , ' U ' );
12 var sx,x1,y1,x2,y2: array [ 1 ..maxq] of longint;
13 br: array [ 1 ..maxq, ' a ' .. ' z ' ] of boolean;
14 f: array [ 1 ..maxq] of boolean;
15 ans: array [ 1 ..maxq] of string[ 2 ];
16 prev,dep: array [ 1 ..maxq] of longint;
17 hash: array [ 0 ..base] of longint;
18 nxt,tab: array [ 1 ..maxq] of longint;
19 ch: array [ 0 ..maxn + 1 , 0 ..maxn + 1 ] of char;
20 sp: array [ ' T ' .. ' X ' ] of record x1,y1,x2,y2:longint; end ;
21 bt: array [ ' A ' .. ' Z ' , 1 ..maxn] of char;
22 btxo,bttf: array [ ' A ' .. ' Z ' ] of boolean;
23 p: array [ ' a ' .. ' z ' ] of boolean;
24 btn: array [ ' A ' .. ' Z ' ] of longint;
25 n,m,i,j,k,ex,ey,tt,t1,t2,t3,h,t:longint;
26 blank,ch0,ch1:char;
27 function BKDRhash:boolean;
28 var ans0,p:longint;
29 b:boolean;
30 begin
31 ans0: = 0 ;
32 ans0: = (ans0 * 131 + x1[t]) and base;
33 ans0: = (ans0 * 131 + x2[t]) and base;
34 ans0: = (ans0 * 131 + y1[t]) and base;
35 ans0: = (ans0 * 131 + y2[t]) and base;
36 for ch0: = ' a ' to ' z ' do
37 begin
38 if br[t][ch0]
39 then ans0: = (ans0 * 131 + 11 ) and base
40 else ans0: = (ans0 * 131 + 13 ) and base;
41 end ;
42 p: = hash[ans0];
43 while p <> 0 do
44 begin
45 b: = (x1[tab[p]] = x1[t]) and (x2[tab[p]] = x2[t])
46 and (y1[tab[p]] = y1[t]) and (y2[tab[p]] = y2[t]);
47 for ch0: = ' a ' to ' z ' do
48 b: = b and (br[tab[p]][ch0] = br[t][ch0]);
49 if b then exit(true);
50 p: = nxt[p];
51 end ;
52 BKDRhash: = false;
53 inc(tt); tab[tt]: = t;
54 nxt[tt]: = hash[ans0];
55 hash[ans0]: = tt;
56 end ;
57 function max(a,b:longint):longint;
58 begin
59 if a > b then max: = a else max: = b;
60 end ;
61 function min(a,b:longint):longint;
62 begin
63 if a < b then min: = a else min: = b;
64 end ;
65 procedure change(ch:char);
66 var i:longint;
67 begin
68 if bttf[ch]
69 then for i: = 1 to btn[ch] do
70 br[t][bt[ch][i]]: = not br[t][bt[ch][i]]
71 else for i: = 1 to btn[ch] do
72 br[t][bt[ch][i]]: = false;
73 end ;
74 procedure out(x:longint);
75 begin
76 if prev[x] =- 1 then exit;
77 out(prev[x]);
78 write { ln } (ans[x]);
79 // writeln(x1[x], ' ' ,y1[x], ' ' ,x2[x], ' ' ,y2[x]);
80 end ;
81 begin
82 assign(input, ' bloxorz.in ' ); reset(input);
83 assign(output, ' bloxorz.out ' ); rewrite(output);
84 readln(n,m);
85 t1: = 0 ; t2: = 0 ;
86 for i: = 0 to m + 1 do ch[ 0 ,i]: = ' * ' ;
87 for i: = 0 to m + 1 do ch[n + 1 ,i]: = ' * ' ;
88 for i: = 1 to n do ch[i, 0 ]: = ' * ' ;
89 for i: = 1 to n do ch[i,m + 1 ]: = ' * ' ;
90 ch[ 0 , 0 ]: = ' $ ' ;
91 for i: = 1 to n do
92 begin
93 k: = 0 ;
94 while not eoln do
95 begin
96 inc(k);
97 read(ch[i,k]);
98 if ch[i,k] = ' ' then ch[i,k]: = ' * ' ;
99 if ch[i,k] = ' Z ' then begin ex: = i; ey: = k; end ;
100 if ch[i,k] = ' Y '
101 then begin
102 x1[ 1 ]: = i; y1[ 1 ]: = k;
103 ch[i,k]: = ' + ' ;
104 end ;
105 if ch[i,k] in sep then inc(t1);
106 if ch[i,k] in but then inc(t2);
107 if (ch[i,k] in bri) and ( not p[ch[i,k]])
108 then begin p[ch[i,k]]: = true; inc(t3); end ;
109 end ;
110 for j: = k + 1 to m do ch[i,j]: = ' * ' ;
111 readln;
112 end ;
113 for i: = 1 to t1 do
114 begin
115 read(ch0);
116 readln(sp[ch0].x1,sp[ch0].y1,sp[ch0].x2,sp[ch0].y2);
117 end ;
118 for i: = 1 to t2 do
119 begin
120 read(ch0);
121 read(blank); read(ch1); bttf[ch0]: = ch1 = ' T ' ;
122 read(blank); read(ch1); btxo[ch0]: = ch1 = ' O ' ;
123 while not eoln do
124 begin
125 read(blank); read(ch1);
126 inc(btn[ch0]); bt[ch0,btn[ch0]]: = ch1;
127 end ;
128 readln;
129 end ;
130 for i: = 1 to t3 do
131 begin
132 read(ch0); read(blank);
133 readln(t1); br[ 1 ][ch0]: = t1 = 1 ;
134 end ;
135 h: = 1 ; t: = 1 ;
136 BKDRhash;
137 dep[ 1 ]: = 0 ; prev[ 1 ]: =- 1 ;
138 sx[ 1 ]: = 1 ;
139 while h <= t do
140 begin
141 if h = 19
142 then h: = h;
143 case sx[h] of
144 1 : begin
145 for i: = 1 to 4 do
146 begin
147 inc(t);
148 x1[t]: = x1[h] + dx[i];
149 y1[t]: = y1[h] + dy[i];
150 x2[t]: = x1[h] + dx[i] + dx[i];
151 y2[t]: = y1[h] + dy[i] + dy[i];
152 sx[t]: = 3 - i and 1 ;
153 move(br[h],br[t],sizeof(br[h]));
154 if (ch[x1[t],y1[t]] = ' * ' ) or (ch[x2[t],y2[t]] = ' * ' )
155 then begin dec(t); continue; end ;
156 if (ch[x1[t],y1[t]] in but) and (btxo[ch[x1[t],y1[t]]])
157 then change(ch[x1[t],y1[t]]);
158 if (ch[x2[t],y2[t]] in but) and (btxo[ch[x2[t],y2[t]]])
159 then change(ch[x2[t],y2[t]]);
160 if (ch[x1[t],y1[t]] in bri) and ( not br[t][ch[x1[t],y1[t]]])
161 or (ch[x2[t],y2[t]] in bri) and ( not br[t][ch[x2[t],y2[t]]]) or BKDRhash
162 then begin dec(t); continue; end ;
163 dep[t]: = dep[h] + 1 ;
164 prev[t]: = h;
165 ans[t]: = dc[i];
166 end ;
167 end ;
168 2 : begin
169 for i: = 1 to 4 do
170 begin
171 inc(t);
172 case i of
173 1 : begin
174 sx[t]: = 1 ;
175 x1[t]: = x1[h]; y1[t]: = max(y1[h],y2[h]) + 1 ;
176 x2[t]: = 0 ; y2[t]: = 0 ;
177 end ;
178 2 : begin
179 sx[t]: = 2 ;
180 x1[t]: = x1[h] + 1 ; y1[t]: = y1[h];
181 x2[t]: = x2[h] + 1 ; y2[t]: = y2[h];
182 end ;
183 3 : begin
184 sx[t]: = 1 ;
185 x1[t]: = x1[h]; y1[t]: = min(y1[h],y2[h]) - 1 ;
186 x2[t]: = 0 ; y2[t]: = 0 ;
187 end ;
188 4 : begin
189 sx[t]: = 2 ;
190 x1[t]: = x1[h] - 1 ; y1[t]: = y1[h];
191 x2[t]: = x2[h] - 1 ; y2[t]: = y2[h];
192 end ;
193 end ;
194 if (sx[t] = 1 ) and (ex = x1[t]) and (ey = y1[t])
195 then begin
196 prev[t]: = h; ans[t]: = dc[i];
197 writeln(dep[h] + 1 );
198 out(t);
199 close(input); close(output);
200 halt;
201 end ;
202 if (sx[t] = 1 ) and (ch[x1[t],y1[t]] in sep)
203 then begin
204 ch0: = ch[x1[t],y1[t]];
205 x1[t]: = sp[ch0].x1;
206 y1[t]: = sp[ch0].y1;
207 x2[t]: = sp[ch0].x2;
208 y2[t]: = sp[ch0].y2;
209 sx[t]: = 4 ;
210 f[t]: = true;
211 end ;
212 if (ch[x1[t],y1[t]] = ' * ' ) or (ch[x2[t],y2[t]] = ' * ' )
213 then begin dec(t); continue; end ;
214 move(br[h],br[t],sizeof(br[h]));
215 if (ch[x1[t],y1[t]] in but) and ((sx[t] = 1 ) or btxo[ch[x1[t],y1[t]]])
216 then change(ch[x1[t],y1[t]]);
217 if (ch[x2[t],y2[t]] in but) and ((sx[t] = 1 ) or btxo[ch[x2[t],y2[t]]])
218 then change(ch[x2[t],y2[t]]);
219 if (ch[x1[t],y1[t]] in bri) and ( not br[t][ch[x1[t],y1[t]]])
220 or (ch[x2[t],y2[t]] in bri) and ( not br[t][ch[x2[t],y2[t]]]) or BKDRhash
221 then begin dec(t); continue; end ;
222 dep[t]: = dep[h] + 1 ;
223 prev[t]: = h;
224 ans[t]: = dc[i];
225 end ;
226 end ;
227 3 : begin
228 for i: = 1 to 4 do
229 begin
230 inc(t);
231 case i of
232 1 : begin
233 sx[t]: = 3 ;
234 x1[t]: = x1[h]; y1[t]: = y1[h] + 1 ;
235 x2[t]: = x2[h]; y2[t]: = y2[h] + 1 ;
236 end ;
237 2 : begin
238 sx[t]: = 1 ;
239 x1[t]: = max(x1[h],x2[h]) + 1 ; y1[t]: = y1[h];
240 x2[t]: = 0 ; y2[t]: = 0 ;
241 end ;
242 3 : begin
243 sx[t]: = 3 ;
244 x1[t]: = x1[h]; y1[t]: = y1[h] - 1 ;
245 x2[t]: = x2[h]; y2[t]: = y2[h] - 1 ;
246 end ;
247 4 : begin
248 sx[t]: = 1 ;
249 x1[t]: = min(x1[h],x2[h]) - 1 ; y1[t]: = y1[h];
250 x2[t]: = 0 ; y2[t]: = 0 ;
251 end ;
252 end ;
253 if (sx[t] = 1 ) and (ex = x1[t]) and (ey = y1[t])
254 then begin
255 prev[t]: = h; ans[t]: = dc[i];
256 writeln(dep[h] + 1 );
257 out(t);
258 close(input); close(output);
259 halt;
260 end ;
261 if (sx[t] = 1 ) and (ch[x1[t],y1[t]] in sep)
262 then begin
263 ch0: = ch[x1[t],y1[t]];
264 x1[t]: = sp[ch0].x1;
265 y1[t]: = sp[ch0].y1;
266 x2[t]: = sp[ch0].x2;
267 y2[t]: = sp[ch0].y2;
268 sx[t]: = 4 ;
269 f[t]: = true;
270 end ;
271 if (ch[x1[t],y1[t]] = ' * ' ) or (ch[x2[t],y2[t]] = ' * ' )
272 then begin dec(t); continue; end ;
273 move(br[h],br[t],sizeof(br[h]));
274 if (ch[x1[t],y1[t]] in but) and ((sx[t] = 1 ) or btxo[ch[x1[t],y1[t]]])
275 then change(ch[x1[t],y1[t]]);
276 if (ch[x2[t],y2[t]] in but) and ((sx[t] = 1 ) or btxo[ch[x2[t],y2[t]]])
277 then change(ch[x2[t],y2[t]]);
278 if (ch[x1[t],y1[t]] in bri) and ( not br[t][ch[x1[t],y1[t]]])
279 or (ch[x2[t],y2[t]] in bri) and ( not br[t][ch[x2[t],y2[t]]]) or BKDRhash
280 then begin dec(t); continue; end ;
281 dep[t]: = dep[h] + 1 ;
282 prev[t]: = h;
283 ans[t]: = dc[i];
284 end ;
285 end ;
286 4 : begin
287 for i: = 1 to 2 do
288 case i of
289 1 : for j: = 1 to 4 do
290 begin
291 inc(t);
292 case j of
293 1 : begin x1[t]: = x1[h]; y1[t]: = y1[h] + 1 ; end ;
294 2 : begin x1[t]: = x1[h] + 1 ; y1[t]: = y1[h]; end ;
295 3 : begin x1[t]: = x1[h]; y1[t]: = y1[h] - 1 ; end ;
296 4 : begin x1[t]: = x1[h] - 1 ; y1[t]: = y1[h]; end ;
297 end ;
298 x2[t]: = x2[h]; y2[t]: = y2[h];
299 if ch[x1[t],y1[t]] = ' B '
300 then t: = t;
301 if (ch[x1[t],y1[t]] = ' * ' ) then begin dec(t); continue; end ;
302 move(br[h],br[t],sizeof(br[h]));
303 if (ch[x1[t],y1[t]] in but) and (btxo[ch[x1[t],y1[t]]])
304 then change(ch[x1[t],y1[t]]);
305 if (ch[x1[t],y1[t]] in bri) and ( not br[t][ch[x1[t],y1[t]]]) or BKDRhash
306 then begin dec(t); continue; end ;
307 sx[t]: = 4 ;
308 if (x1[t] - 1 = x2[t]) and (y1[t] = y2[t]) then sx[t]: = 3 ;
309 if (x1[t] + 1 = x2[t]) and (y1[t] = y2[t]) then sx[t]: = 3 ;
310 if (x1[t] = x2[t]) and (y1[t] - 1 = y2[t]) then sx[t]: = 2 ;
311 if (x1[t] = x2[t]) and (y1[t] + 1 = y2[t]) then sx[t]: = 2 ;
312 dep[t]: = dep[h] + 1 ;
313 prev[t]: = h;
314 ans[t]: = dc[j];
315 if not f[h] then ans[t]: = ' ' + ans[t];
316 f[t]: = true;
317 end ;
318 2 : for j: = 1 to 4 do
319 begin
320 inc(t);
321 case j of
322 1 : begin x2[t]: = x2[h]; y2[t]: = y2[h] + 1 ; end ;
323 2 : begin x2[t]: = x2[h] + 1 ; y2[t]: = y2[h]; end ;
324 3 : begin x2[t]: = x2[h]; y2[t]: = y2[h] - 1 ; end ;
325 4 : begin x2[t]: = x2[h] - 1 ; y2[t]: = y2[h]; end ;
326 end ;
327 x1[t]: = x1[h]; y1[t]: = y1[h];
328 if ch[x2[t],y2[t]] = ' B '
329 then t: = t;
330 if (ch[x2[t],y2[t]] = ' * ' ) then begin dec(t); continue; end ;
331 move(br[h],br[t],sizeof(br[h]));
332 if (ch[x2[t],y2[t]] in but) and (btxo[ch[x2[t],y2[t]]])
333 then change(ch[x2[t],y2[t]]);
334 if (ch[x2[t],y2[t]] in bri) and ( not br[t][ch[x2[t],y2[t]]]) or BKDRhash
335 then begin dec(t); continue; end ;
336 sx[t]: = 4 ;
337 if (x2[t] - 1 = x1[t]) and (y2[t] = y1[t]) then sx[t]: = 3 ;
338 if (x2[t] + 1 = x1[t]) and (y2[t] = y1[t]) then sx[t]: = 3 ;
339 if (x2[t] = x1[t]) and (y2[t] - 1 = y1[t]) then sx[t]: = 2 ;
340 if (x2[t] = x1[t]) and (y2[t] + 1 = y1[t]) then sx[t]: = 2 ;
341 dep[t]: = dep[h] + 1 ;
342 prev[t]: = h;
343 ans[t]: = dc[j];
344 if f[h] then ans[t]: = ' ' + ans[t];
345 f[t]: = false;
346 end ;
347 end ;
348 end ;
349 end ;
350 inc(h);
351 end ;
352 writeln( ' LOW LOW RP... ' );
353 close(input); close(output);
354 end .
355
<强大的搜索>到此完结 谢谢关注!
结语: 搜索十分强大 分析重于实现
BOB HAN原创 转载请注明出处