[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) 编辑 收藏 举报