diff --git a/ykoiso/src/A055_EscapeGame.java b/ykoiso/src/A055_EscapeGame.java new file mode 100644 index 0000000000000000000000000000000000000000..f3fa79f7383b2eebeb927d1cdbe45411462f5e3b --- /dev/null +++ b/ykoiso/src/A055_EscapeGame.java @@ -0,0 +1,119 @@ +import java.util.Map; +import java.util.Scanner; + +public class A055_EscapeGame { + // マップ記号のenum、Mapのほうが良かったかも + public enum STR { + START("S"), WALL("#"), ROAD("."); + + private String chr; + + STR(String chr) { + this.chr = chr; + } + + public String getChr() { + return chr; + } + } + + public static void main(String[] args) { + Scanner scan = new Scanner(System.in); + // 定数の読み込み + final int HEIGHT = scan.nextInt(); + final int WIDTH = scan.nextInt(); + final String[][] MAP = new String[HEIGHT][WIDTH]; + int startH = 0; + int startW = 0; + // マップの生成 + // 1列分読み込んでから1文字に分けて格納 + for (int H = 0; H < HEIGHT; H++) { + String str = scan.next(); + for (int W = 0; W < WIDTH; W++) { + MAP[H][W] = str.substring(W); + if (MAP[H][W] == STR.START.getChr()) { + startH = H; + startW = W; + } + } + } + // マップ探索クラスの生成 + A055_EscapeGame cls = new A055_EscapeGame(); + SearchMap searchMap = cls.new SearchMap(MAP, startH, startW, HEIGHT, WIDTH); + // 探索開始 + searchMap.search(); + scan.close(); + } + + class SearchMap { + // マップ + private String[][] map; + // スタート座標 + private int startH; + private int startW; + // 探索したかの判定 + private boolean[][] isSearch; + // マップの縦横 + private int height; + private int width; + // 脱出可能かの判定 + private boolean isEscape = false; + + // テスト用 + public boolean isEscape() { + return isEscape; + } + + // コンストラクタ + SearchMap(final String[][] map, final int startH, final int startW, final int height, + final int width) { + this.map = map; + this.startH = startH; + this.startW = startW; + this.height = height; + this.width = width; + isSearch = new boolean[height][width]; + } + + // 探索関数 + public void search() { + searchAdjacent(startH, startW); + System.out.println(makeAnswer()); + } + + // 答えの出力 + public String makeAnswer() { + if (isEscape == true) { + return "YES"; + } else { + return "NO"; + } + } + + // 目標座標の縦横の探索 + public void searchAdjacent(final int height, final int width) { + // 外壁まで来てたら探索終了 + if (height == 0 || width == 0 || height == this.height - 1 || width == this.width - 1) { + isEscape = true; + } + // 探索中なら探索を進める + if (isEscape == false) { + checkRoad(height - 1, width); + checkRoad(height + 1, width); + checkRoad(height, width - 1); + checkRoad(height, width + 1); + } + } + + // 目的座標が移動できるかの判定 + // 移動出来たら再帰的に探索を進める + public void checkRoad(final int height, final int width) { + // 目的座標が道かつ未探索なら探索済みにして再帰 + STR str = STR.valueOf(map[height][width]); + if (str == STR.ROAD && isSearch[height][width] == false) { + isSearch[height][width] = true; + searchAdjacent(height, width); + } + } + } +} diff --git a/ykoiso/test/A055_EscapeGameTest.java b/ykoiso/test/A055_EscapeGameTest.java new file mode 100644 index 0000000000000000000000000000000000000000..0a1fd3b0166a9280814d4cb20eff43092a14ca40 --- /dev/null +++ b/ykoiso/test/A055_EscapeGameTest.java @@ -0,0 +1,72 @@ +import static org.junit.Assert.assertThat; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.junit.Test; + +import static org.hamcrest.CoreMatchers.*; + +public class A055_EscapeGameTest { + A055_EscapeGame cls = new A055_EscapeGame(); + A055_EscapeGame.SearchMap sut; + int startH; + int startW; + + @Test + public void 道があると判断できる() { + String[][] map = {{"#", ".", "#"}, {"#", "S", "#"}, {"#", "#", "#"}}; + startH = 1; + startW = 1; + sut = cls.new SearchMap(map, startH, startW, 3, 3); + sut.searchAdjacent(startH, startW); + boolean actual = sut.isEscape(); + assertThat(actual, is(true)); + } + + @Test + public void 道がないと判断できる() { + String[][] map = {{"#", "#", "#"}, {"#", "S", "#"}, {"#", "#", "#"}}; + startH = 1; + startW = 1; + sut = cls.new SearchMap(map, startH, startW, 3, 3); + sut.searchAdjacent(startH, startW); + boolean actual = sut.isEscape(); + assertThat(actual, is(false)); + } + + @Test + public void 縦横5マスでも再帰的に探索できる() { + String[][] map = {{"#", "#", "#", "#", "#"}, {"#", "#", "#", "#", "#"}, + {"#", "#", "S", "#", "#"}, {"#", "#", ".", ".", "#"}, {"#", "#", "#", ".", "#"}}; + startH = 3; + startW = 3; + sut = cls.new SearchMap(map, startH, startW, 5, 5); + sut.searchAdjacent(startH, startW); + boolean actual = sut.isEscape(); + assertThat(actual, is(true)); + } + + // makeAnswerテスト + @Test + public void 道があるときYESを返す() { + String[][] map = {{"#", "#", "#"}, {"#", "S", "#"}, {"#", ".", "#"}}; + startH = 1; + startW = 1; + sut = cls.new SearchMap(map, startH, startW, 3, 3); + sut.searchAdjacent(startH, startW); + String actual = sut.makeAnswer(); + String expected = "YES"; + assertThat(actual, is(expected)); + } + + @Test + public void 道がないときNOを返す() { + String[][] map = {{"#", "#", "#"}, {"#", "S", "#"}, {"#", "#", "#"}}; + startH = 1; + startW = 1; + sut = cls.new SearchMap(map, startH, startW, 3, 3); + String actual = sut.makeAnswer(); + String expected = "NO"; + assertThat(actual, is(expected)); + } +}