10

前回の解答
step2 の最後に下のような注意書きがありました。
注意
このプログラムは、スタート位置が右の壁際の場合、上の壁まで移動したあと壁にぶつかってしまいます。
これを回避するにはプログラム中で判断を追加しなければなりません。どこにどのような判断を追加したらよいか考えてみてください。
これは、上の壁まで移動した後、何も判断しないで右に移動してしまうため起こります。これを回避するには次のようなプログラムを追加します（赤字が追加したところです）。こうすることで、上の壁まで来たとき右に移動できるか判断をするので右の壁にぶつからないようになります。
1819202122232425262728
2930
3132
33
34
35

/********** mode で分岐する **********/
switch (mode){case 1: /* 壁にぶつかるまで上に移動する */if(value[2] == 2){/* 上に壁があったら */if(value[6] == 2){/* 右に壁があるか判断する */value = target.walkDown( );mode = 3;}
else{value = target.walkRight( ); /* 右に移動し */mode = 2;/* mode を 2 に変更する */}}else{value = target.walkUp( );/* そうでなければ、上に移動する */}break;
case 2: /* 壁にぶつかるまで右に移動する */
・・・

11

サンプルプログラム（Sample2008_03.java）
・まず、上と右をサーチし、自分の位置を把握します
・次に、現在位置から一番近い四隅（右上、右下、左上、左下）を割り出し、そこに移動します
・その後、”Sample2008_02.java”と同じ動き（壁の内側を時計回りに移動）をします
・新たに step という変数を作り、現在実行している mode の中で順序（step）をわけて管理します
・プログラム名は”Sample2008_03.java”とします
・赤字が追加・変更したところです
123456789101112131415161718192021222324252627282930313233343536373839

public class Sample2008_03{
public static void main(String[ ] args){
int[ ] value;
value = new int[10];int mode = 5,
step = 1,
posY = 1,
posX = 1;/********** 競技サーバに接続する **********/
edu.procon.PreConnect2008 target;
target = new edu.procon.PreConnect2008( );while(true){/********** まず、getReady でサーバから戻り値を得る **********/
value = target.getReady( );if(value[0] == 0) break;/********** mode で分岐する **********/
switch (mode){case 1: /* 壁にぶつかるまで上に移動する */if(value[2] == 2){/* 上に壁があったら */if(value[6] == 2){/* 右に壁があるか判断する */value = target.walkDown( );mode = 3;}
else{value = target.walkRight( ); /* 右に移動し */mode = 2;/* mode を 2 に変更する */}}else{value = target.walkUp( );/* そうでなければ、上に移動する */}break;
case 2: /* 壁にぶつかるまで右に移動する */if(value[6] == 2){

124041424344454647
4849505152535455
5657
58
5960
616263
64
65
66
67
68
6970
71
72
73
74
75
76
77
78
79
80
80
8182
83
84
85
86
87
88
89

value = target.walkDown( );mode = 3;}
else{value = target.walkRight( );}break;
case 3: /* 壁にぶつかるまで下に移動する */if(value[8] == 2){
value = target.walkLeft( );mode = 4;}
else{value = target.walkDown( );}break;
case 4: /* 壁にぶつかるまで左に移動する */if(value[4] == 2){
value = target.walkUp( );mode = 1;}
else{
value = target.walkLeft( );}break;
case 5: /* 上と右をサーチし、一番近い四隅へ移動する */switch (step){case 1: /* step1 上をサーチする */value = target.searchUp( );for(int i=1; i<10; i++){if(value[i] == 2){
posY = i; /* 現在位置の Y 座標が決定 */break;}}
step = 2;
break;
case 2: /* step2 右をサーチする */value = target.searchRight( );for(int i=1; i<10; i++){if(value[i] == 2){
posX = 10 - i; /* 現在位置の X 座標が決定 */break;}}
step = 3;
break;
case 3: /* step3 一番近い四隅を見つける */if(posY<=5 && posX<=5){if(value[2] != 2){ /* 上に動くことができるか判断する */value = target.walkUp( );

1390
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140

mode = 6; /* 左上に移動するモードへ */step = 1;}
else if(value[4] != 2){ /* 左に動くことができるか判断する */value = target.walkLeft( );mode = 6; /* 左上に移動するモードへ */step = 2;}
else{ /* すでに左上にいるので、右に移動する */value = target.walkRight( );mode = 2; /* 右に移動するモードへ */}}else if(posY<=5 && posX>=6){if(value[2] != 2){ /* 上に動くことができるか判断する */value = target.walkUp( );mode = 7; /* 右上に移動するモードへ */step = 1;}
else if(value[6] != 2){ /* 右に動くことができるか判断する */value = target.walkRight( );mode = 7; /* 右上に移動するモードへ */step = 2;}
else{ /* すでに右上にいるので、下に移動する */value = target.walkDown( );mode = 3; /* 下に移動するモードへ */}}else if(posY>=6 && posX<=5){if(value[8] != 2){ /* 下に動くことができるか判断する */value = target.walkDown( );mode = 8; /* 左下に移動するモードへ */step = 1;}
else if(value[4] != 2){ /* 左に動くことができるか判断する */value = target.walkLeft( );mode = 8; /* 左下に移動するモードへ */step = 2;}
else{ /* すでに左下にいるので、上に移動する */value = target.walkUp( );mode = 1; /* 上に移動するモードへ */}}else{if(value[8] != 2){ /* 下に動くことができるか判断する */value = target.walkDown( );mode = 9; /* 右下に移動するモードへ */step = 1;}

14

141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191

else if(value[6] != 2){ /* 右に動くことができるか判断する */value = target.walkLeft( );mode = 9; /* 右下に移動するモードへ */step = 2;}
else{ /* すでに右下にいるので、左に移動する */value = target.walkLeft( );mode = 4; /* 左に移動するモードへ */}}break;}
break;
case 6: /* 左上に移動するモード */switch (step){case 1: /* step1 壁にぶつかるまで上に移動する */if(value[2] == 2){
if(value[4] == 2){/* 左に壁があるか判断する */value = target.walkRight( );mode = 2; /* 壁にぶつかるまで右に移動するモードへ */step = 1;}
else{
value = target.walkLeft( );step = 2;}}
else{
value = target.walkUp( );}break;
case 2: /* step2 壁にぶつかるまで左に移動する */if(value[4] == 2){
value = target.walkRight( );mode = 2; /* 壁にぶつかるまで右に移動するモードへ */step = 1;}
else{
value = target.walkLeft( );}break;}
break;
case 7: /* 右上に移動するモード */switch (step){case 1: /* step1 壁にぶつかるまで上に移動する */if(value[2] == 2){
if(value[6] == 2){
value = target.walkDown( );mode = 3; /* 壁にぶつかるまで下に移動するモードへ */step = 1;

15192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207208
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243

}
else{
value = target.walkRight( );step = 2;}}
else{
value = target.walkUp( );}break;
case 2: /* step2 壁にぶつかるまで右に移動する */if(value[6] == 2){
value = target.walkDown( );mode = 3; /* 壁にぶつかるまで下に移動するモードへ */step = 1;}
else{
value = target.walkRight( );}break;}
break;
case 8: /* 左下に移動するモード */switch (step){case 1: /* step1 壁にぶつかるまで下に移動する */if(value[8] == 2){
if(value[4] == 2){
value = target.walkUp( );mode = 1; /* 壁にぶつかるまで上に移動するモードへ */step = 1;}
else{
value = target.walkLeft( );step = 2;}}
else{
value = target.walkDown( );}break;
case 2: /* step2 壁にぶつかるまで左に移動する */if(value[4] == 2){
value = target.walkUp( );mode = 1; /* 壁にぶつかるまで上に移動するモードへ */step = 1;}
else{
value = target.walkLeft( );}break;}

16244245246247248249
250
251
252
253
254
255
256257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282283284285286※break;case 9: /* 右下に移動するモード */switch (step){case 1: /* step1 壁にぶつかるまで下に移動する */if(value[8] == 2){
if(value[6] == 2){
value = target.walkLeft( );mode = 4; /* 壁にぶつかるまで左に移動するモードへ */step = 1;}
else{
value = target.walkRight( );step = 2;}}
else{
value = target.walkDown( );}break;
case 2: /* step2 壁にぶつかるまで右に移動する */if(value[6] == 2){
value = target.walkLeft( );mode = 4; /* 壁にぶつかるまで左に移動するモードへ */step = 1;}
else{
value = target.walkRight( );}break;}
break;} /* switch(mode) *//********** 制御情報が 0 だったら終了する **********/
if(value[0] == 0) break;} /* while(true) *//********** 競技サーバから切断する **********/
target.exit( );}}長いプログラムですが、がんばりましょう！

17

プログラム説明①変数の宣言と初期値
78910int mode = 5,
step = 1,
posY = 1,
posX = 1;

mode は上と右をサーチし、一番近い四隅へ移動するモードにするので初期値は 5 になります。step は 1 から始まるので 1 とします。posY は自分の Y 座標の現在位置、posX は自分の X 座標の現在位置なので初期値はそれぞれ 1 とします。
②追加したモードとステップ
今回新たにモード 5 から 9 を追加しました。ステップはモード内の順序を表しています。例えば、モード 5 の場合、ステップ 1 は上をサーチする、ステップ 2 は右をサーチする、ステップ 3 は一番近い四隅を見つけるというようになります。
・モードとステップの種類と動作
mode

動作

1

壁にぶつかるまで上に移動する

2

壁にぶつかるまで右に移動する

3

壁にぶつかるまで下に移動する

4

壁にぶつかるまで左に移動する
上と右をサーチし、一番近い四隅へ移動する

5

step = 1

上をサーチする

step = 2

右をサーチする

step = 3

一番近い四隅を見つける

左上に移動するモード
6

step = 1

壁にぶつかるまで上に移動する

step = 2

壁にぶつかるまで左に移動する

右上に移動するモード
7

step = 1

壁にぶつかるまで上に移動する

step = 2

壁にぶつかるまで右に移動する

左下に移動するモード
8

step = 1

壁にぶつかるまで下に移動する

step = 2

壁にぶつかるまで左に移動する

右下に移動するモード
9

step = 1

壁にぶつかるまで下に移動する

step = 2

壁にぶつかるまで右に移動する

18③モード 5モード 5 はステップ 1 から 3 に分かれるので mode の switch 文の中に step の switch
文が入ります。ステップ 1 は上をサーチして Y 座標の位置を調べるので、まず serchUpメソッドを送信します。PreCHaser は 9×9 マスなので serchUp メソッドを送信すれば必ず壁を検知します。壁の値は 2 なので、69 行目の for 文で Y 座標の位置を求めることができます。
65666768697071727374
7576

case 5: /* 上と右をサーチし、一番近い四隅へ移動する */switch (step){case 1: /* step1 上をサーチする */value = target.searchUp( );for(int i=1; i<10; i++){if(value[i] == 2){
posY = i; /* 現在位置の Y 座標が決定 */break;}}
step = 2;
break;

例えば、下の画面の位置で serchUp メソッドを送信した場合、サーバからの戻り値は1003222222 となります。先頭の 1 は制御情報で、それ以降は自分のキャラクタの上方向に周囲情報になります。壁の外側はすべて壁になっています。この場合は posY は 4 になります。

2：外は壁
2：外は壁
2：外は壁
2：外は壁
2：外は壁2：壁
3：アイテム
0：床
0：床

19

ステップ 2 は右をサーチして X 座標の位置を調べるので、まず serchRight メソッドを送信します。同様に 79 行目の for 文で X 座標の位置を求めることができます。
7778
7980808182838485

case 2: /* step2 右をサーチする */value = target.searchRight( );for(int i=1; i<10; i++){if(value[i] == 2){
posX = 10 - i; /* 現在位置の X 座標が決定 */break;}}
step = 3;break;

例えば、上の画面の位置で serchRight メソッドを送信した場合、サーバからの戻り値は 1002222222 となるので posX は 10-3 で 7 になります。
ステップ 3 は posY と posX を使って現在位置から一番近い四隅を割り出します。87 行
目の if 文は posY<=5 かつ posX<=5 なので、現在位置がフィールドの左上の範囲いるかを判断しています。同様に右上、左下、右下を判断します。
86878889909192939495
9697
98
99
100101102

case 3: /* step3 一番近い四隅を見つける */if(posY<=5 && posX<=5){if(value[2] != 2){ /* 上に動くことができるか判断する */value = target.walkUp( );mode = 6; /* 左上に移動するモードへ */step = 1;}
else if(value[4] != 2){ /* 左に動くことができるか判断する */value = target.walkLeft( );mode = 6; /* 左上に移動するモードへ */step = 2;}
else{ /* すでに左上にいるので、右に移動する */value = target.walkRight( );mode = 2; /* 右に移動するモードへ */}
}

左上の範囲

右上の範囲

if(posY<=5 && posX<=5)

if(posY<=5 && posX>=6)

左下の範囲

右下の範囲

if(posy>=6 && posX<=5)

if(posy>=6 && posX>=6)

20④モード 6モード 6 は左上に移動するモードなので、ステップ 1 で上に移動し、ステップ 2 で左に移動します。
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

case 6: /* 左上に移動するモード */switch (step){case 1: /* step1 壁にぶつかるまで上に移動する */if(value[2] == 2){
if(value[4] == 2){/* 左に壁があるか判断する */value = target.walkRight( );mode = 2; /* 壁にぶつかるまで右に移動するモードへ */step = 1;}
else{
value = target.walkLeft( );step = 2;}}
else{
value = target.walkUp( );}break;
case 2: /* step2 壁にぶつかるまで左に移動する */if(value[4] == 2){
value = target.walkRight( );mode = 2; /* 壁にぶつかるまで右に移動するモードへ */step = 1;}
else{
value = target.walkLeft( );}break;}
break;

同様に、モード 7 から 9 をつくります。