本ページはプロモーションが含まれています

Java入門

Javaプログラミング入門!自動販売機を4ステップで自作する方法

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

「学んだ知識をどう活かせばいいか分からない」「簡単なものでいいから、動くプログラムを作って達成感を味わいたい」

その中でも特に人気なのが、「自動販売機」の作成です。

なぜなら、自動販売機はオブジェクト指向の基本的な概念(クラス、オブジェクト、カプセル化など)を学ぶのに最適な題材だからです。

商品、お金、購入処理といった要素を、Javaのクラスとして表現する良い練習になります。

私自身も、Javaを学び始めた頃に自動販売機プログラムを作成し、オブジェクト指向への理解を深めた経験があります。

最初は難しく感じるかもしれませんが、ステップを踏んでいけば、必ず完成させられます。

この記事を読めば、Javaプログラミング初心者の方でも、コンソール上で動作するシンプルな自動販売機プログラムを5つのステップで作成する方法が分かります。

Javaの基本文法(変数、条件分岐、繰り返しなど)を学んだ方が、次のステップとしてオブジェクト指向を学ぶのにぴったりの内容です。

Javaで自動販売機を作るメリットとは?

Javaプログラミングで自動販売機を作ることは、単に面白いだけでなく、学習面でも多くのメリットがあります。

結論として、自動販売機の作成はオブジェクト指向プログラミングの基礎を実践的に学ぶ絶好の機会です。

その理由は、以下の点が挙げられます。

オブジェクト指向の概念を体感できる

自動販売機は、「商品」「お金」「販売機本体」といった、明確な「モノ」や「役割」で構成されています。

これらをJavaの「クラス」として設計し、それぞれの属性(データ)や振る舞い(メソッド)を定義するプロセスを通じて、オブジェクト指向の考え方が自然に身につきます。

例えば、「商品クラス」には商品名や価格、「販売機本体クラス」には商品リストや購入処理メソッドを実装する、といった具合です。

これは、教科書を読むだけでは得られない実践的な理解につながるでしょう。

あわせて読む

状態管理のプログラミングを学べる

自動販売機は、「投入されている金額」「各商品の在庫数」「お釣りの有無」など、常に変化する「状態」を持っています。

これらの状態をプログラム内で正確に管理し、変化させる方法を学ぶことができます。

変数を適切に使い、条件分岐や繰り返し処理を組み合わせる実践的な練習になります。

基本的な入出力処理に慣れる

ユーザーからの「お金の投入」や「商品選択」といった入力を受け取り、結果(購入完了メッセージやお釣りなど)を出力する処理が必要です。

Javaの標準入出力(System.out.printlnScannerクラスなど)の使い方を具体的に学ぶことができます。

Javaプログラミングで作る自動販売機の完成イメージ

この記事で作成を目指すのは、コンソール上で動作するシンプルなテキストベースの自動販売機です。

具体的には、以下のような機能を持つものを想定しています。

ポイント

  1. 商品リストの表示: 自動販売機が販売している商品名と価格の一覧を表示します。
  2. お金の投入: ユーザーが指定した金額(例えば10円、50円、100円、500円、1,000円)を投入できます。投入された合計金額を表示します。
  3. 商品の選択: ユーザーが購入したい商品を選択します。
  4. 購入処理: 投入金額が商品価格以上か、商品の在庫があるかを確認します。購入可能な場合は、投入金額から商品価格を引きます。在庫を1つ減らします。
  5. お釣りの計算と表示: 購入後、お釣りがあれば計算して表示します。
  6. エラーメッセージ: お金が足りない場合や、在庫がない場合に適切なメッセージを表示します。

Javaプログラミングで自動販売機を作るための4ステップ

それでは、実際にJavaプログラミングで自動販売機を作成していく手順を、4つのステップに分けて解説します。

自動販売機の基本的な設計(クラス設計)

プログラムを作る前に、自動販売機を構成する要素を洗い出し、それらをどのようにクラスとして表現するかを設計します。

オブジェクト指向プログラミングでは、現実世界の「モノ」や「概念」を「クラス」としてモデル化します。

自動販売機システムの場合、主要な構成要素として以下が考えられます。

以下のように、まず「何が必要か」を考え、それぞれの役割と情報(属性)、そしてどのような操作(振る舞い)ができるかを整理するのがクラス設計の第一歩です。

商品 (Item)

  • 属性(データ): 商品名 (name), 価格 (price), 在庫数 (stock)
  • 振る舞い(メソッド): 商品情報を取得する、在庫を減らす など

お金 (Money)

今回はシンプルに、投入された合計金額を管理する変数で表現します。より詳細にするなら、硬貨や紙幣の種類と枚数を管理するクラスも考えられます。

自動販売機本体 (VendingMachine)

  • 属性(データ): 商品リスト (itemList), 投入金額 (currentAmount), 売り上げ (sales) など
  • 振る舞い(メソッド): お金を受け取る (insertMoney), 商品を表示する (displayItems), 商品を購入する (purchaseItem), お釣りを計算する (calculateChange) など

商品とお金のクラスをJavaで実装

設計に基づき、まずは「商品」を表すItemクラスを作成します。

Itemという名前の新しいクラスファイルを作成し、以下のようなコードを記述します。

public class Item {
    private String name; // 商品名 (カプセル化のためprivate)
    private int price;   // 価格 (カプセル化のためprivate)
    private int stock;   // 在庫数 (カプセル化のためprivate)
    // コンストラクタ: Itemオブジェクト生成時に名前、価格、在庫数を設定する
    public Item(String name, int price, int stock) {
        this.name = name;
        this.price = price;
        this.stock = stock;
    }
    // 商品名を取得するメソッド (getter)
    public String getName() {
        return name;
    }
    // 価格を取得するメソッド (getter)
    public int getPrice() {
        return price;
    }
    // 在庫数を取得するメソッド (getter)
    public int getStock() {
        return stock;
    }
    // 在庫があるかどうかを確認するメソッド
    public boolean isAvailable() {
        return stock > 0;
    }
    // 在庫を1つ減らすメソッド
    public void decreaseStock() {
        if (stock > 0) {
            stock--;
        }
    }
    // 商品情報を文字列で返すメソッド (表示用)
    @Override
    public String toString() {
        return name + " (" + price + "円) - 在庫: " + (stock > 0 ? stock + "個" : "売り切れ");
    }
}

今回はシンプルにするため、「お金」専用のクラスは作成せず、自動販売機クラス内で投入金額を int 型の変数で管理することにします。

ポイント

  • private String name; のように、フィールド(属性)を private にしています。これはカプセル化というオブジェクト指向の重要な考え方で、クラスの内部データを外部から直接アクセスできないように保護するためです。
  • データにアクセスするためには、public String getName() のような public なメソッド(getter)を用意します。
  • public Item(String name, int price, int stock)コンストラクタ と呼ばれ、Itemオブジェクトが作られるときに自動的に呼び出され、初期値を設定します。
  • isAvailable()decreaseStock() は、商品の状態を確認したり、操作したりするためのメソッド(振る舞い)です。
  • toString() メソッドは、オブジェクトを文字列として表現したいときに使われます。System.out.println() などで Item オブジェクトを直接表示しようとすると、このメソッドが呼び出されます。

自動販売機本体のクラスをJavaで実装

次に、自動販売機の本体機能を持つVendingMachineクラスを作成します。

VendingMachine という名前で新しいクラスファイルを作成し、以下のコードを記述します。

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner; // ユーザー入力を受け取るために必要
public class VendingMachine {
    private List<Item> items; // 商品リスト (Itemオブジェクトを格納)
    private int currentAmount; // 現在の投入金額
    private int sales;         // 総売上
    // コンストラクタ
    public VendingMachine() {
        items = new ArrayList<>(); // 空の商品リストを作成
        currentAmount = 0;
        sales = 0;
        // 初期商品をいくつか追加しておく
        initializeItems();
    }
    // 初期商品を設定するメソッド
    private void initializeItems() {
        items.add(new Item("お茶", 120, 5));
        items.add(new Item("コーヒー", 130, 3));
        items.add(new Item("コーラ", 150, 0)); // 在庫切れの商品
        items.add(new Item("水", 100, 10));
    }
    // お金を投入するメソッド
    public void insertMoney(int amount) {
        // 対応する金種かチェック (例: 10, 50, 100, 500, 1000円のみ受け付ける)
        if (amount == 10 || amount == 50 || amount == 100 || amount == 500 || amount == 1000) {
            currentAmount += amount;
            System.out.println(amount + "円投入されました。現在の投入金額: " + currentAmount + "円");
        } else {
            System.out.println(amount + "円は投入できません。10円、50円、100円、500円、1,000円のみ利用可能です。");
        }
    }
    // 現在の投入金額を取得するメソッド
    public int getCurrentAmount() {
        return currentAmount;
    }
    // 商品リストを表示するメソッド
    public void displayItems() {
        System.out.println("--- 商品リスト ---");
        if (items.isEmpty()) {
            System.out.println("現在、販売中の商品はありません。");
            return;
        }
        for (int i = 0; i < items.size(); i++) {
            System.out.println((i + 1) + ". " + items.get(i).toString()); // ItemクラスのtoString()が呼ばれる
        }
        System.out.println("------------------");
    }
    // 商品を購入するメソッド
    public void purchaseItem(int itemIndex) {
        // ユーザーが入力するのは1から始まる番号なので、リストのインデックスに変換 (0から始まる)
        int actualIndex = itemIndex - 1;
        // 有効な商品番号かチェック
        if (actualIndex < 0 || actualIndex >= items.size()) {
            System.out.println("無効な商品番号です。");
            return;
        }
        Item selectedItem = items.get(actualIndex);
        // 在庫チェック
        if (!selectedItem.isAvailable()) {
            System.out.println("申し訳ありません。" + selectedItem.getName() + "は売り切れです。");
            return;
        }
        // 金額チェック
        if (currentAmount < selectedItem.getPrice()) {
            System.out.println("投入金額が不足しています。" + selectedItem.getName() + "の価格は" + selectedItem.getPrice() + "円です。");
            return;
        }
        // 購入処理
        currentAmount -= selectedItem.getPrice(); // 金額を減らす
        selectedItem.decreaseStock();           // 在庫を減らす
        sales += selectedItem.getPrice();         // 売上を計上する
        System.out.println(selectedItem.getName() + "を購入しました。");
        // お釣り処理
        returnChange();
    }
    // お釣りを返すメソッド
    public void returnChange() {
        if (currentAmount > 0) {
            System.out.println("お釣り " + currentAmount + "円をお返しします。");
            currentAmount = 0; // 投入金額をリセット
        } else {
             System.out.println("お釣りはありません。");
        }
         System.out.println("ご利用ありがとうございました。");
    }
     // 自動販売機を操作するメインのロジック (例)
    public void run() {
        Scanner scanner = new Scanner(System.in); // ユーザー入力用
        int choice = -1;
        while (choice != 0) {
            System.out.println("\n現在の投入金額: " + currentAmount + "円");
            displayItems();
            System.out.println("操作を選んでください:");
            System.out.println("1: お金を投入する");
            System.out.println("2: 商品を購入する");
            System.out.println("3: お釣りを返却して終了する");
            System.out.print("番号を入力: ");
            // 入力が数値でない場合の対策
            if (scanner.hasNextInt()) {
                 choice = scanner.nextInt();
            } else {
                System.out.println("無効な入力です。数字を入力してください。");
                scanner.next(); // 不正な入力を読み飛ばす
                continue; // ループの先頭に戻る
            }
            switch (choice) {
                case 1:
                    System.out.print("投入する金額を入力してください (10, 50, 100, 500, 1000): ");
                     if (scanner.hasNextInt()) {
                         int amount = scanner.nextInt();
                         insertMoney(amount);
                     } else {
                         System.out.println("無効な入力です。数字を入力してください。");
                         scanner.next(); // 不正な入力を読み飛ばす
                     }
                    break;
                case 2:
                    if (currentAmount <= 0) {
                        System.out.println("先にお金を投入してください。");
                        break;
                    }
                    System.out.print("購入したい商品の番号を入力してください: ");
                     if (scanner.hasNextInt()) {
                         int itemNumber = scanner.nextInt();
                         purchaseItem(itemNumber);
                     } else {
                         System.out.println("無効な入力です。数字を入力してください。");
                         scanner.next(); // 不正な入力を読み飛ばす
                     }
                    break;
                case 3:
                    returnChange();
                    choice = 0; // ループを抜けるためにchoiceを0にする
                    break;
                default:
                    System.out.println("無効な選択です。1から3の番号を入力してください。");
            }
        }
        scanner.close(); // Scannerを閉じる
        System.out.println("自動販売機プログラムを終了します。総売上: " + sales + "円");
    }
}

ポイント

  • import java.util.ArrayList; など:他のクラス(ここではリストやスキャナー)を利用するために import 文が必要です。
  • private List<Item> items;: Itemオブジェクトを複数格納するために List(具体的には ArrayList)を使っています。これにより、商品の追加や削除が容易になります。
  • initializeItems(): 最初にいくつかの商品をリストに追加しています。
  • insertMoney(): 投入された金額を currentAmount に加算します。ここでは簡単な金種チェックも入れています。
  • displayItems(): itemsリストの中身を順番に表示します。items.get(i).toString() で、各 Item オブジェクトの toString() メソッドが呼び出され、整形された文字列が表示されます。
  • purchaseItem(): 商品番号を受け取り、在庫と投入金額をチェックして購入処理を行います。問題なければ金額と在庫を更新し、returnChange() を呼び出します。
  • returnChange(): 残っている currentAmount をお釣りとして表示し、0にリセットします。
  • run(): ユーザーとの対話(メニュー表示、入力受付、メソッド呼び出し)を行う中心的なメソッドです。Scanner を使ってコンソールからの入力を受け取ります。while ループと switch 文を使って、ユーザーが終了を選ぶまで操作を繰り返せるようにしています。入力が数値でない場合のエラー処理も簡単に追加しました。

動作テストとデバッグ

最後に、作成したVendingMachineクラスを実際に動かしてみるための実行用クラスを作成し、動作を確認します。

Main (または VendingMachineTest など分かりやすい名前) という名前で新しいクラスファイルを作成し、main メソッドを記述します。

main メソッドは、Javaプログラムの実行開始点となる特別なメソッドです。

public class Main {
    public static void main(String[] args) {
        // VendingMachineクラスのインスタンス(実体)を作成
        VendingMachine myVendingMachine = new VendingMachine();
        // 自動販売機を実行
        myVendingMachine.run();
    }
}

ポイント

  • public static void main(String[] args): この定型文が main メソッドの定義です。プログラムはここから実行が始まります。
  • VendingMachine myVendingMachine = new VendingMachine();: VendingMachine クラスの設計図をもとに、myVendingMachine という名前の実際の自動販売機オブジェクト(インスタンス)を作成しています。new VendingMachine() でコンストラクタが呼び出され、初期化が行われます。
  • myVendingMachine.run();: 作成した自動販売機オブジェクトの run() メソッドを呼び出し、ユーザーが操作できる状態にします。

実行とデバッグ:

  1. 表示される指示に従って、お金を投入したり、商品を選択したりしてみてください。
  2. 意図した通りに動作するか確認します。
    • お金は正しく加算されるか?
    • 商品は正しく表示されるか?
    • 購入処理は正しく行われるか?(金額、在庫)
    • お釣りは正しいか?
    • 在庫切れの商品を買おうとしたらどうなるか?
    • お金が足りない場合はどうなるか?
    • 不正な金額や商品番号を入力したらどうなるか?

これでJavaプログラミングによる基本的な自動販売機が完成しました。

まとめ:Javaプログラミングで自動販売機作成に挑戦しよう

Javaプログラミングで自動販売機を作ることは、オブジェクト指向や状態管理、入出力処理など、実践的なスキルを一通り学べる絶好の学習テーマです。

実際のクラス設計やコンソール操作を通じて、抽象的な概念を具体的に体験できるため、初心者から中級者へのステップアップに最適な題材といえます。

【要点まとめ】

  • 自動販売機はオブジェクト指向の理解に最適な題材である
  • クラス分割で現実の「モノ」をプログラムで再現できる
  • 状態管理の考え方を変数とロジックで学べる
  • 条件分岐や繰り返し処理の応用力が鍛えられる
  • Javaの入出力処理(ScannerやSystem.out)に慣れる
  • エラー処理やユーザー入力への対応力が身につく
  • 完成したプログラムで動作確認・デバッグ力が向上する
  • オブジェクト同士の連携や責務分担の理解が深まる

このまとめを読むことで、Javaでの自動販売機開発が単なるコード練習にとどまらず、体系的な学習のステップであることが理解できたはずです。

  • この記事を書いた人
  • 最新記事

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

-Java入門