Java | ユーザー入力で3D配列を作るミニアプリ

Java Java
スポンサーリンク

ユーザー入力で 3D 配列(層 × 行 × 列) を作り、いくつかの集計(層ごとの合計・平均、全体の合計・平均)と可視化(層ごとの表表示)を行う 完全なコンソールアプリ(Scanner 使用) を用意しました。
このプログラムは 「全ての層が同じサイズにする(uniform)」「行や列を層ごとに自由に決める(jagged)」 を選べます。初心者向けに入力チェック、ヘルプコメント、出力の見やすさも配慮しています。


完全コード(Java)

import java.util.InputMismatchException;
import java.util.Scanner;

public class ThreeDArrayApp {

    public static void main(String[] args) {
        try (Scanner sc = new Scanner(System.in)) {
            System.out.println("=== 3D 配列ミニアプリ ===");
            System.out.println("使い方: 層(layer)ごとに数値を入力して、集計・表示します。");

            // 1) ユーザーが uniform (同じサイズ) か jagged (行/列可変) か選ぶ
            boolean uniform = askYesNo(sc, "全ての層で同じ行数・列数にしますか? (y/n): ");

            int layers = readInt(sc, "層 (layers) の数を入力してください(正の整数): ", 1, Integer.MAX_VALUE);

            int[][][] arr;
            if (uniform) {
                int rows = readInt(sc, "各層の行数 (rows) を入力してください(正の整数): ", 1, Integer.MAX_VALUE);
                int cols = readInt(sc, "各行の列数 (cols) を入力してください(正の整数): ", 1, Integer.MAX_VALUE);
                arr = new int[layers][rows][cols];

                // 値の入力(層・行・列ごと)
                System.out.println("--- 値を入力してください(整数) ---");
                for (int l = 0; l < layers; l++) {
                    System.out.println("Layer " + l + " の入力:");
                    for (int r = 0; r < rows; r++) {
                        for (int c = 0; c < cols; c++) {
                            arr[l][r][c] = readInt(sc, "  a[" + l + "][" + r + "][" + c + "] = ", Integer.MIN_VALUE, Integer.MAX_VALUE);
                        }
                    }
                }
            } else {
                // jagged: 各層ごとに行数・各行ごとに列数を指定
                arr = new int[layers][][];
                System.out.println("--- 各層のサイズを入力してください(ジャグ配列) ---");
                for (int l = 0; l < layers; l++) {
                    System.out.println("Layer " + l + " の設定:");
                    int rows = readInt(sc, "  行数 (rows) を入力(正の整数): ", 1, Integer.MAX_VALUE);
                    arr[l] = new int[rows][];
                    for (int r = 0; r < rows; r++) {
                        int cols = readInt(sc, "    row " + r + " の列数 (cols) を入力(正の整数): ", 1, Integer.MAX_VALUE);
                        arr[l][r] = new int[cols];
                    }
                }
                // 値の入力
                System.out.println("--- 値を入力してください(整数) ---");
                for (int l = 0; l < layers; l++) {
                    System.out.println("Layer " + l + " の入力:");
                    for (int r = 0; r < arr[l].length; r++) {
                        for (int c = 0; c < arr[l][r].length; c++) {
                            arr[l][r][c] = readInt(sc, "  a[" + l + "][" + r + "][" + c + "] = ", Integer.MIN_VALUE, Integer.MAX_VALUE);
                        }
                    }
                }
            }

            // データ入力完了 -> 集計・表示
            System.out.println("\n=== 入力完了:集計と表示 ===");
            printAllLayersAscii(arr);
            computeAndPrintSummaries(arr);
            System.out.println("=== 終了 ===");
        } catch (Exception e) {
            System.err.println("予期せぬエラーが発生しました: " + e.getMessage());
            e.printStackTrace();
        }
    }

    // ユーティリティ: 整数入力(範囲チェック付き)
    private static int readInt(Scanner sc, String prompt, int min, int max) {
        while (true) {
            try {
                System.out.print(prompt);
                int v = sc.nextInt();
                sc.nextLine(); // consume end-of-line
                if (v < min || v > max) {
                    System.out.println("入力が範囲外です。 " + min + " ~ " + max + " の値を入力してください。");
                    continue;
                }
                return v;
            } catch (InputMismatchException ime) {
                System.out.println("整数を入力してください。");
                sc.nextLine(); // consume bad token
            }
        }
    }

    // 簡単な yes/no 入力
    private static boolean askYesNo(Scanner sc, String prompt) {
        while (true) {
            System.out.print(prompt);
            String line = sc.nextLine().trim().toLowerCase();
            if (line.equals("y") || line.equals("yes") || line.equals("はい") || line.equals("y\n")) return true;
            if (line.equals("n") || line.equals("no") || line.equals("いいえ") || line.equals("n\n")) return false;
            System.out.println("y/yes/はい または n/no/いいえ で答えてください。");
        }
    }

    // 層ごとに ASCII 表示する(2次元表示を層ごとに出す)
    private static void printAllLayersAscii(int[][][] arr) {
        for (int l = 0; l < arr.length; l++) {
            System.out.println("\n--- Layer " + l + " ---");
            if (arr[l] == null || arr[l].length == 0) {
                System.out.println("(この層は空です)");
                continue;
            }
            // 列幅自動調整:各列ごとの最大桁数を求める(ジャグ対応でまず最大列数を取得)
            int maxCols = 0;
            for (int r = 0; r < arr[l].length; r++) {
                if (arr[l][r] != null && arr[l][r].length > maxCols) maxCols = arr[l][r].length;
            }
            int[] colWidths = new int[maxCols];
            // 各列 j に対して行 r を走査して最大幅を求める(その行に列がなければ無視)
            for (int j = 0; j < maxCols; j++) {
                int w = 0;
                for (int r = 0; r < arr[l].length; r++) {
                    if (arr[l][r] != null && arr[l][r].length > j) {
                        int len = String.valueOf(arr[l][r][j]).length();
                        if (len > w) w = len;
                    }
                }
                colWidths[j] = w;
            }

            // 横線出力
            Runnable printLine = () -> {
                for (int j = 0; j < maxCols; j++) {
                    System.out.print("+");
                    int w = colWidths[j];
                    for (int k = 0; k < w + 2; k++) System.out.print("-");
                }
                System.out.println("+");
            };

            // 表示
            for (int r = 0; r < arr[l].length; r++) {
                printLine.run();
                if (arr[l][r] == null || arr[l][r].length == 0) {
                    // 空行扱い
                    System.out.print("| ");
                    System.out.print("(empty)");
                    System.out.println();
                    continue;
                }
                for (int j = 0; j < arr[l][r].length; j++) {
                    String val = String.valueOf(arr[l][r][j]);
                    System.out.print("| " + padRight(val, colWidths[j]) + " ");
                }
                // if this row has fewer cols than maxCols, print empty cells
                for (int j = arr[l][r].length; j < maxCols; j++) {
                    System.out.print("| " + padRight("", colWidths[j]) + " ");
                }
                System.out.println("|");
            }
            printLine.run();
        }
    }

    // 右パディング
    private static String padRight(String s, int width) {
        StringBuilder sb = new StringBuilder(s == null ? "" : s);
        while (sb.length() < width) sb.append(' ');
        return sb.toString();
    }

    // 各種集計(層ごとの合計/平均・全体の合計/平均)
    private static void computeAndPrintSummaries(int[][][] arr) {
        long grandTotal = 0;
        long grandCount = 0;

        System.out.println("\n--- Summaries ---");
        for (int l = 0; l < arr.length; l++) {
            long layerTotal = 0;
            long layerCount = 0;
            if (arr[l] != null) {
                for (int r = 0; r < arr[l].length; r++) {
                    if (arr[l][r] != null) {
                        for (int c = 0; c < arr[l][r].length; c++) {
                            layerTotal += arr[l][r][c];
                            layerCount++;
                        }
                    }
                }
            }
            grandTotal += layerTotal;
            grandCount += layerCount;
            double layerAvg = layerCount == 0 ? Double.NaN : (double) layerTotal / layerCount;
            System.out.printf("Layer %d: total = %d, count = %d, average = %s%n",
                    l, layerTotal, layerCount,
                    layerCount == 0 ? "(n/a)" : String.format("%.4f", layerAvg));
        }

        double grandAvg = grandCount == 0 ? Double.NaN : (double) grandTotal / grandCount;
        System.out.println();
        System.out.printf("All layers: total = %d, count = %d, average = %s%n",
                grandTotal, grandCount,
                grandCount == 0 ? "(n/a)" : String.format("%.4f", grandAvg));
    }
}
Java

使い方メモ

  1. 上のコードを ThreeDArrayApp.java として保存します。
  2. ターミナル(コマンドプロンプト)でコンパイル: javac ThreeDArrayApp.java
  3. 実行: java ThreeDArrayApp
  4. プロンプトに従って y/n や整数を入力してください。

プログラムのポイント(初心者向け補足)

  • uniform を選ぶと全層が同じ rows×cols になります。
  • jagged を選ぶと、各層ごとに行数・各行ごとに列数を自由に設定できます(配列の列数がばらばらな「ジャグ配列」を扱える)。
  • 入力チェックを入れているので、整数以外を入れても再入力を促します。
  • printAllLayersAscii メソッドは層ごとに2次元表を ASCII で整形して表示します。見やすさのため各列の幅を自動調整します。
  • computeAndPrintSummaries では層ごとの合計・平均と、全体の合計・平均を出します。
Java
スポンサーリンク
シェアする
@lifehackerをフォローする
スポンサーリンク
タイトルとURLをコピーしました