[Maze.java] -- //迷路を自動生成する import java.io.*; class Maze{ //迷路の自動生成を行う static final int MAX_SIZE = 30; //サイズの最大値 static final int MAX_TH = 20; //分岐度の最大値 static final int DEFAULT_SIZE = 15; //デフォルトのサイズ static final int DEFAULT_TH = 4; //デフォルトの分岐度 public static Map map; //迷路のマップ public static void main(String args[])throws IOException{ //コマンドラインのオプションスイッチを調べる boolean isnodialogic = false; //非対話モードか? boolean isdigitoutput = false; //数値出力か? int num = 0; if(args.length > 0){ if(args[0].equals("-h")) showUsage(0); //-hの時は使用法を出力して終了 isdigitoutput = args[0].equals("-d"); isnodialogic = (args[0].equals("-n") | isdigitoutput); num = 1; } //マップの生成 Rc size = new Rc(DEFAULT_SIZE, DEFAULT_SIZE); if(args.length-num < 1){ //java Maze [-n|-d] if(!isnodialogic){ ///java Maze System.out.println("生成する迷路のサイズを入力してください。"); size.r = inNum(1, MAX_SIZE, "縦方向:"); size.c = inNum(1, MAX_SIZE, "横方向:"); } }else{ //java Maze [-n|-d] param1 ... size.r = getParam(args[num+0], 1, MAX_SIZE); if(args.length-num < 2) ///java Maze [-n|-d] size size.c = size.r; //サイズのパラメータ1つのとき横=縦 else ///java Maze [-n|-d] size1 size2 ... size.c = getParam(args[num+1], 1, MAX_SIZE); } map = new Map(size); //マップを作成する Rc start = new Rc(1, 1); if(args.length-num < 4){ //始点位置指定ないとき if(!isnodialogic){ map.show(); System.out.println("迷路の開始位置を指定してください。"); start.r = inNum(1, size.r, "行位置:"); start.c = inNum(1, size.c, "列位置:"); } }else{ //java Maze [-n|-d] h w sr sc ... start.r = getParam(args[num+2], 1, size.r); start.c = getParam(args[num+3], 1, size.c); } Rc goal = new Rc(size.r, size.c); if(args.length-num < 6){ //終点位置指定ないとき if(!isnodialogic){ if(args.length-num >= 4) map.show(); System.out.println("迷路の終了位置を指定してください。"); goal.r = inNum(1, size.r, "行位置:"); goal.c = inNum(1, size.c, "列位置:"); } }else{ //java Maze [-n|-d] h w sr sc gr gc ... goal.r = getParam(args[num+4], 1, size.r); goal.c = getParam(args[num+5], 1, size.c); } int mx = DEFAULT_TH; if(args.length-num < 7){ //分岐度指定ないとき if(!isnodialogic){ System.out.print("迷路の枝分かれの度合いを指定して下さい。"); mx = inNum(1, MAX_TH, ":"); } }else //java Maze [-n|-d] h w sr sc gr gc mx mx = getParam(args[num+6], 1, MAX_TH); //迷路の生成 createMaze(start, mx); //迷路を伸長させる for(int i=1; i<=size.r; i++){ for(int j=1; j<=size.c; j++){ if(map.isUndef(new Rc(i, j))) //マップに隙間があるうちは伸長させる createMaze(new Rc(i, j), mx); } } map.cleanUp(start, goal); //隙間をなくして迷路を仕上げる //結果を出力する map.show(isdigitoutput); } static void createMaze(Rc p, int mx){ //スレッドを起動して迷路を伸長させる map.connect(p); //(隣に'道'があればつなげて)道を配置する Thread th = new Thread(new Branch(p, mx)); //処理を行うスレッド th.start(); //処理を開始する try{ th.join(); //スレッドが終了するまで待つ }catch(InterruptedException e) { } } static int getParam(String arg, int min, int max){ //指定した範囲の整数をコマンドラインのパラメータから得る int param = 0; try{ param = Integer.parseInt(arg); //文字列->int型にする }catch(NumberFormatException e){ showUsage(1); //int型にならないときUsageを出力して終了 } param = Math.max(param, min); //数を範囲に収める param = Math.min(param, max); return param; } static int inNum(int min, int max, String str)throws IOException{ //指定した範囲内の整数をキーボード入力から得る BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); boolean flag = true; int num = min; do{ System.out.print(str + "[" + min + "-" + max + "]"); try{ num = Integer.parseInt(br.readLine()); //入力文字列->int型に変換 if ((num>=min) && (num<=max)) //数の範囲を調べる flag = false; }catch(NumberFormatException e){ } }while(flag); //範囲内の数が得られるまでループを実行 return num; } static void showUsage(int status){ //このプログラムの起動方法を表示して終了する System.err.println("Usage:"); System.err.println(" java Maze [-n | -d] [縦サイズ [横サイズ [始点行位置 始点列位置 [終点行位置 終点列位置 [分岐度]]]]]"); System.err.println(" java Maze -h"); System.err.println(); System.err.println(" -n: 非対話モード。結果の図のみ出力します。"); System.err.println(" -d: 非対話モード。結果を数値データとして出力します。"); System.err.println(" -h: このUsageを表示します。"); System.err.println(" 縦サイズ: 1 - " + MAX_SIZE + " [非対話モード デフォルト=" +DEFAULT_SIZE + "]"); System.err.println(" 横サイズ: 1 - " + MAX_SIZE + " 縦サイズ指定時 デフォルト=縦サイズ [縦サイズ]"); System.err.println(" 始点位置: [(1, 1)]"); System.err.println(" 終点位置: [(縦サイズ, 横サイズ)]"); System.err.println(" 分岐度: 1 - " + MAX_TH + " [" + DEFAULT_TH + "]"); System.exit(status); //終了する } } class Rc{ //座標(行, 列)型を扱うクラス public int r, c; //行, 列成分 static final int UP = 0; //'上' static final int RIGHT = 1; //'右' static final int DOWN = 2; //'下' static final int LEFT = 3; //'左' public Rc(int ir, int ic){ r = ir; c = ic; } public Rc next(int dirc){ //上下左右隣を求める int nr = r, nc = c; switch(dirc){ case UP: //上隣 nr--; break; case RIGHT: //右隣 nc++; break; case DOWN: //下隣 nr++; break; case LEFT: //左隣 nc--; break; } return new Rc(nr, nc); } } -- Copyright (C) Junro YOSHINO