[Bloxorz] 强大的搜索(下)

{

承上篇

介绍一下对于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原创 转载请注明出处

posted on 2010-09-23 10:20  Master_Chivu  阅读(2002)  评论(10编辑  收藏  举报

导航