Problem:
Problem D:バトルタウン

あなたは友人たちとゲームを開発することにした．
ゲームのタイトルは「バトルタウン」．
戦車による市街戦をテーマにしたゲームだ．
ゲーム開発の第一歩として，次のようなプロトタイプを開発することにした．

このプロトタイプでは，登場する戦車はプレイヤーの戦車のみであり，
敵の戦車は登場しない．
プレイヤーの戦車はプレイヤーの入力に従ってマップ上で様々な動作をする．
以下に，戦車の動作に関する仕様を述べる．

マップの構成要素は表1の通りである．
戦車が移動できるのはマップ内の平地の上だけである．

表1: マップの構成要素

文字

要素

.

平地

*

レンガの壁

#

鉄の壁

-

水

^

戦車（上向き）

v

戦車（下向き）

<

戦車（左向き）

>

戦車（右向き）

プレイヤーの入力は文字の列で与えられる．
各文字に対応する動作は表2の通りである．

表2: プレイヤーの入力に対する動作

文字

動作

U

Up: 戦車を上向きに方向転換し，さらに一つ上のマスが平地ならばそのマスに移動する

D

Down: 戦車を下向きに方向転換し，さらに一つ下のマスが平地ならばそのマスに移動する

L

Left: 戦車を左向きに方向転換し，さらに一つ左のマスが平地ならばそのマスに移動する

R

Right: 戦車を右向きに方向転換し，さらに一つ右のマスが平地ならばそのマスに移動する

S

Shoot: 戦車が現在向いている方向に砲弾を発射する

砲弾はレンガの壁あるいは鉄の壁にぶつかるか，マップの外に出るまで直進する．
レンガの壁にぶつかった場合は，砲弾は消滅し，レンガの壁は平地に変化する．
鉄の壁にぶつかった場合は，砲弾は消滅するが，鉄の壁は変化しない．
マップの外に出たときは砲弾はそのまま消滅する．

あなたの仕事は，初期マップとプレイヤーの入力操作列が与えられたときに，
最終的なマップの状態を出力するプログラムを作成することである．

Input

入力の1行目にはデータセット数を表す数 T
(0 < T ≤ 100) が与えられる．
この行に引き続き T 個のデータセットが与えられる．

各データセットの1行目にはマップの高さと幅を表す整数
H と W が
1つの空白文字で区切られて与えられる．
これらの整数は 2 ≤ H ≤ 20,
2 ≤ W ≤ 20 を満たす．
続く H 行はマップの初期状態を表す．
各行は長さ W の文字列である．
マップに含まれる文字はすべて表1で定義されたものであり，
全体でちょうど1つの戦車を含む．
マップに続く行には入力操作列の長さ N
(0 < N ≤ 100) が与えられ，
次の行には入力操作列を表す長さ N の文字列が与えられる．
入力操作列は表2で定義された文字のみからなる文字列である．

Output

各データセットに対し，すべての入力操作を終えた後のマップを，
入力マップと同じ形式で出力せよ．
データセットの間には1行の空行を出力せよ．
最後のデータセットの後に余計な空行を出力しないよう注意すること．

Sample Input

4
4 6
*.*..*
*.....
..-...
^.*#..
10
SRSSRRUSSR
2 2
<.
..
12
DDSRRSUUSLLS
3 5
>-#**
.-*#*
.-**#
15
SSSDRSSSDRSSSUU
5 5
v****
*****
*****
*****
*****
44
SSSSDDRSDRSRDSULUURSSSSRRRRDSSSSDDLSDLSDLSSD

Output for the Sample Input

*....*
......
..-...
..>#..

<.
..

^-#**
.-.#*
.-..#

.....
.***.
..*..
..*..
....v

Solution in JAVA (judge verdict: Accepted)


import java.util.Scanner;

class Main {

	public static void main(String[] args) {

		Scanner scanner = new Scanner(System.in);


		int T=scanner.nextInt();

		for(int i=0;i<T;i++){

			Tank tank=new Tank();

			int H=scanner.nextInt();
			int W=scanner.nextInt();
			tank.H=H;
			tank.W=W;//マップの最大値をTankクラスに引き渡す

			
			//マップを作ると同時に戦車の向きと現在地をTankクラスに渡す
			
			for(int p=0;p<H;p++){
				
				String st=scanner.next();

				for(int k=0;k<W;k++){

					tank.map[p][k]=st.charAt(k);
					

					switch(tank.map[p][k]){
					case '^':
						tank.positionH=p;
						tank.positionW=k;
						tank.direction='^';
						break;

					case 'v':
						tank.positionH=p;
						tank.positionW=k;
						tank.direction='v';
						break;

					case '<':
						tank.positionH=p;
						tank.positionW=k;
						tank.direction='<';
						break;

					case '>':
						tank.positionH=p;
						tank.positionW=k;
						tank.direction='>';
						break;
					}

				}

			}



			int N=scanner.nextInt();

			String order=scanner.next();

			//各命令をtankクラスのメソッドに渡す
			for(int k=0;k<N;k++){
				switch(order.charAt(k)){
				case'U':
					tank.Up();
					break;

				case'D':
					tank.Down();
					break;

				case'L':
					tank.Left();
					break;

				case'R':
					tank.Right();
					break;

				case'S':
					tank.Shot();
					break;

				}

			}

			for(int k=0;k<tank.H;k++){
				for(int q=0;q<tank.W;q++){
					System.out.print(String.valueOf(tank.map[k][q]));
				}
				System.out.println("");
			}
			if(!(i==(T-1))){
				System.out.println("");
			}
			
		}
	}

}



class Tank{


	int H=0;//マップの大きさ
	int W=0;

	int positionH=0;//戦車の現在地
	int positionW=0;
	char direction='0';//戦車の向き
	char map[][];//マップ
	
	Tank(){map=new char[20][20];}

	

//戦車の移動したい場所を判別して処理をする
	public void Up(){



		if((positionH>0)&&(map[positionH-1][positionW]=='.')){

			map[positionH][positionW]='.';
			map[positionH-1][positionW]='^';
			positionH=positionH-1;
			direction='^';
		}

		map[positionH][positionW]='^';
		direction='^';

	}


	public void Down(){


		if((positionH<H-1)&&(map[positionH+1][positionW]=='.')){

			map[positionH][positionW]='.';
			map[positionH+1][positionW]='v';
			positionH=positionH+1;
			direction='v';

		}

		map[positionH][positionW]='v';
		direction='v';
	}


	public void Left(){

		if((positionW>0)&&(map[positionH][positionW-1]=='.')){

			map[positionH][positionW]='.';
			map[positionH][positionW-1]='<';
			positionW=positionW-1;
			direction='<';

		}

		map[positionH][positionW]='<';
		direction='<';
	}


	public void Right(){

		if((positionW<W-1)&&(map[positionH][positionW+1]=='.')){

			map[positionH][positionW]='.';
			map[positionH][positionW+1]='>';
			positionW=positionW+1;
			direction='>';

		}
		map[positionH][positionW]='>';
		direction='>';
	}


	//戦車の向きと砲弾のぶつかる先を処理、壁でなければ砲弾を移動させてループする

	public void Shot(){
		int shot=0;
		switch(direction){

		case '^':
			shot=positionH;

			while(true){

				if(shot==0){
					break;
				}
				else if((map[shot-1][positionW]=='.')||(map[shot-1][positionW]=='-')){

					shot=shot-1;

				}

				else if(map[shot-1][positionW]=='#'){
					break;
				}
				else if(map[shot-1][positionW]=='*'){
					map[shot-1][positionW]='.';
					break;
				}
			}
			break;


		case 'v':
			shot=positionH;


			while(true){

				if(shot==H-1){
					break;
				}
				else if((map[shot+1][positionW]=='.')||(map[shot+1][positionW]=='-')){

					shot=shot+1;

				}

				else if(map[shot+1][positionW]=='#'){
					break;
				}
				else if(map[shot+1][positionW]=='*'){
					map[shot+1][positionW]='.';
					break;
				}
			}
			break;

		case '<':
			shot=positionW;


			while(true){

				if(shot==0){
					break;
				}
				else if((map[positionH][shot-1]=='.')||(map[positionH][shot-1]=='-')){

					shot=shot-1;

				}

				else if(map[positionH][shot-1]=='#'){
					break;
				}
				else if(map[positionH][shot-1]=='*'){
					map[positionH][shot-1]='.';
					break;
				}
			}
			break;


		case '>':
			shot=positionW;


			while(true){

				if(shot==W-1){
					break;
				}
				else if((map[positionH][shot+1]=='.')||(map[positionH][shot+1]=='-')){

					shot=shot+1;

				}

				else if(map[positionH][shot+1]=='#'){
					break;
				}
				else if(map[positionH][shot+1]=='*'){
					map[positionH][shot+1]='.';
					break;
				}
			}
			break;
		}

	}
}