Java はじめて3 〜コメントの書き方〜

イントロダクション

コメントの書き方をやります。プログラムが小さくてすぐに終わるようなものであれば、コメントは不要かもしれませんが。超大作になった場合、コメントがないとわけがわからなくなります。「コードを覚えてればよくね?」と思った方は書かなくても良いでしょう(笑)。あとで苦労するのも良い経験になります。

コメントの書き方

コメントは大きく2種類あります。

  1. JavaDocコメント
  2. プログラム用コメント

このコメントはそれぞれに以下のように記述します。

// プログラム用1行コメント
/*
 * プログラム用複数行コメント
 * こんな感じです。
 */

複数行に渡るコメント、最近はあまり使われないように思える。。。。

/**
 * JavaDocコメント
 * @param メソッドの引数など、IDEを使用すれば自動出力してくれるので楽チンです。
 * @return メソッドの返却値です。
 * @see 参照するものURLやURI(ファイルパスとURLを含む)
 */

最近は知多のような書き方が多いように思えます。

// JavaDocコメント
// @param メソッドの引数など、IDEを使用すれば自動出力してくれるので楽チンです。
// @return メソッドの返却値です。
// @see 参照するものURLやURI(ファイルパスとURLを含む)

JavaDocとコメント

複数行コメントとの違いは、初めのアスタリスクが2個、もしくは1個という違いです。
具体的には、次のよう違いです。

「/**」で始まる→JavaDoc
「/*」で始まる→通常コメント

簡単にはこんな感じです。
これで、クラスファイルの数が1000とか2000になっても大丈夫です(笑)。大規模開発でないとこうはなりませんが。。。

じゃんけんゲームのサンプルコード(リンクはGithubへのものです。)>

ちなみに、クラスファイルを一つでじゃんけんゲームを作成してみました。クラス内に、フィールド変数として
「勝敗判定MAP」などがあります。「final」がついているものは定数です。

今後学びますので、今のうちに軽く眺めておくと理解も早まります。

import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Scanner;

/**
 * じゃんけんゲームメインクラス。
 * オブジェクト指向プログラミングでないパターンの実装
 *
 * @author 実装者の名前
 *
 */
public class FirstJankenMain {
    /** 勝敗判定フラグ:勝ち(ユーザー) */
    private static final int YOU_WIN = 0;
    /** 勝敗判定フラグ:負け(ユーザー) */
    private static final int YOU_LOOSE = 1;
    /** 勝敗判定フラグ:あいこ(ユーザー) */
    private static final int AIKO = 2;
    /** グー */
    private static final String GU = "0";
    /** チョキ */
    private static final String CHOKI = "1";
    /** パー */
    private static final String PA = "2";

    /** 勝敗判定MAP **/
    private Map<String, Integer> judgeMap;
    /** 手のMAP(追加実装) */
    private Map<String, String> teMap;

    /**
     * メインメソッド
     * @param args プログラム引数
     */
    public static void main(String[] args) {
        // 0.じゃんけんゲーム起動
        FirstJankenMain main = new FirstJankenMain();
        // 1.勝敗判定MAP作成
        main.createJudgeMap();
        Random random = new Random();

        // 追加実装: 「じゃんけん」と「あいこ」の判定が行えてない
        boolean isJanken= true;
        // 無限ループ
        while(true) {
            // 2.「じゃんけん」or「あいこで」のメッセージ表示
            main.printJankenAiko(isJanken);
            // 3.ユーザーの入力(待ち)
            String input = main.acceptInput();
            if (main.inputCheck(input) == false) {
                System.out.println("0-2の値を入力してください。");
                continue;
            }
            // CPUの手を取得する(JavaSEのAPIを使用するのでテストしない)
            String cpuTe = String.valueOf(random.nextInt(2));
            // 4.「ポン!」or「しょ!」を表示
            main.printPonOrSho(isJanken);
            // <追加>
            main.printTe(input, cpuTe);
            // 5.勝敗判定
            int judge = main.judgeWinLoose(input, cpuTe);
            // 6.勝敗判定の表示
            if (main.printJudge(judge)) {
                // 追加実装:「じゃんけん」と「あいこ」の判定が行えてない
                isJanken = true;
                break;
            } else {
                // 追加実装:「じゃんけん」と「あいこ」の判定が行えてない
                isJanken = false;
            }
        }
        // 7.じゃんけんゲーム終了
    }

    /**
     * 1.勝敗判定MAP作成
     */
    private void createJudgeMap() {
        // 勝敗判定MAPのインスタンスを生成する
        judgeMap = new HashMap<String, Integer>();
        // プレーヤーの勝ちケース
        judgeMap.put(GU + CHOKI, YOU_WIN);
        judgeMap.put(CHOKI + PA, YOU_WIN);
        judgeMap.put(PA + GU, YOU_WIN);
        // プレーヤーの負けケース
        judgeMap.put(GU + PA, YOU_LOOSE);
        judgeMap.put(CHOKI + GU, YOU_LOOSE);
        judgeMap.put(PA + CHOKI, YOU_LOOSE);
        // あいこのケース
        judgeMap.put(GU + GU, AIKO);
        judgeMap.put(CHOKI + CHOKI, AIKO);
        judgeMap.put(PA + PA, AIKO);

        // 手のマップ
        teMap = new HashMap<String, String>();
        teMap.put(GU, "グー");
        teMap.put(CHOKI, "チョキ");
        teMap.put(PA, "パー");
    }

    /**
     * 2.「じゃんけん」or「あいこで」のメッセージ表示
     *
     * @param isJanken true: 「じゃんけん」false: 「あいこ」
     */
    private void printJankenAiko(boolean isJanken) {
        // 追加実装、各手と入力値の票を表示する
        System.out.println("****************");
        System.out.println("*グー   = 0    *");
        System.out.println("*チョキ = 1    *");
        System.out.println("*パー   = 2    *");
        System.out.println("****************");
        // isJankenがtrueの時は「じゃんけん」を表示する
        if (isJanken) {
            System.out.println("じゃんけん ...");
        } else {
            System.out.println("あいこで ...");
        }
    }

    /**
     * 3.ユーザーの入力(待ち)
     *
     * @return 0: グー, 1: チョキ 2: パー
     */
    private String acceptInput() {
        // System.in = 標準入力
        Scanner scan = new Scanner(System.in);
        String input = scan.nextLine();
        return input;
    }

    /**
     * 4.「ポン!」or「しょ!」を表示
     */
    private void printPonOrSho(boolean isJanken) {
        if (isJanken) {
            // 「じゃんけん」の場合は「ポン!」
            System.out.println("ポン!");
        } else {
            // 「あいこで」の場合は「しょ!」
            System.out.println("しょ!");
        }
    }

    /**
     * 5.勝敗判定
     *
     * @param playerTe プレーヤーの手
     * @param cpuTe CPUの手
     * @return 勝敗判定 true: プレーヤーの勝ち false: プレーヤーの負け
     */
    private int judgeWinLoose(String playerTe, String cpuTe) {
        // 勝敗判定MAPのキーはプレーヤーの手とCPUの手を連結したもの
        // 例:「01」= プレーヤー「グー」、CPU「チョキ」
        // 勝敗判定マップから勝敗判定結果を取得する。
        String key = playerTe + cpuTe;
        int result = judgeMap.get(key);
        return result;
    }

    /**
     * 6.勝敗判定の表示
     *
     * @param resultJudge 判定結果
     * @return true: 終了 false: もう一度
     */
    private boolean printJudge(int resultJudge) {
        boolean isFinish = true;
        // 勝敗判定結果を表示する
        switch(resultJudge) {
        case YOU_WIN:
            System.out.println("YOU WIN!");
            break;
        case YOU_LOOSE:
            System.out.println("YOU LOOSE!");
            break;
        case AIKO:
            isFinish = false;
            System.out.println("DRAW!");
            break;
        }
        return isFinish;
    }

    /**
     * <追加実装>
     * プレーヤーの手とCPUの手を表示する。
     *
     * @param playerTe プレーヤーの手
     * @param cpuTe CPUの手
     */
    private void printTe(String playerTe, String cpuTe) {
        System.out.println("ユーザー:" + teMap.get(playerTe));
        System.out.println("CPU:" + teMap.get(cpuTe));
    }

    /**
     * <追加実装>
     * じゃんけんの手として適当な値であるか判定する。
     *
     * @param input ユーザー入力
     * @return true; じゃんけんの手として適当な値 / false: じゃんけんの手として不適当な値
     */
    private boolean inputCheck(String input) {
        // 判定フラグ
        boolean isJankenTe = false;
        // 正規表現で判定する
        if (input.matches("[0-2]")) {
            isJankenTe = true;
        }
        return isJankenTe;
    }
}

これを動かすと、このような形で動きます。

でわでわ。。。

<<< 前回  次回 >>>

サイトマップ
ゲームを作りながら覚えるJavaの基本

関連ページ

  1. Java Basic Level 1 〜Hello Java〜
  2. Java Basic Level2 〜Arithmetic Calculate〜
  3. Java Basic Level3 〜About String class〜
  4. Java Basic Summary from Level1 to 5
  5. Java クラスの書き方〜ワンポイントレッスン的な〜


Java Basic 総復習編 〜基本と基本文法編〜

Java Basic 総復習

今まで、Javaを学習してきて、なんとなくはわかったけどクラスとかオブジェクトという言葉が出てきたら頭がこんがらがってきた。という事象があるかと思います。

<プログラミングのチュートリアル(説明)動画>

自分も昔そうでした。。。そうだったような気がします。

それならば、整理すれば良いのです。簡単な話です。

復習内容リスト

  1. プログラムの流れ
  2. 変数の扱い
  3. 式と演算子
  4. if文
  5. switch文
  6. while文
  7. for文

プログラムの流れ

まずは、プログラムの流れについて復習します。クラスやメソッドなどが出てきて処理があちこちに飛ぶように感じられると思いますが、そんなことはありません。順序立てて動いています。

まずは、メインメソッドが動く

どのクラスにも作成することができますが、1つのアプリケーションとして動かすときは、「必ずメインメソッドが動く」ということを忘れないでください。

例えば、下のようなコードがあったとします。

public class First {
 public static void main(String[] args) {
       System.out.println("Hello World");
       First main = new First();
       main.hello();
   }
   public void hello() {
       System.out.println("Second Hello World");
   }
}

この時に、メインメソッドの中では、クラスをnewしてやらないとメンバメソッド(インスタンスメソッド)は起動できません。
それは、「static」がついているメソッドは、特別なメソッドなので、インスタンスメソッドと区別されます。

ここでの、処理の順番は、以下のようになります。

  1. メインメソッドが動く
  2. 「Hello World」をコンソールに出力
  3. Firstクラスをインスタンス化
  4. インスタンスメソッドの「hello()」を呼び出す

このように動きます。ここでの注意ポイントは「First」クラス型の変数「main」です。

変数の扱い

変数はプログラムを動かすために必要になるものですが、あまり細かいところまで解説をすることが少ないです。
実際に、覚えることはint型は「整数」とか、「double」型は少数。。。
というように、データ型の用途に対する説明のみになってしまうからです。

変数には「プリミティブ型」と「参照型(クラス型)」がありますが、参照型に関しては自作クラスも参照型として分類されるので
プリミティブ型のように「これは整数型です」というような言い方ができません。

ただし、String型はクラス型です。他にも、int型を参照型にしたものがあります。それぞれ下のようになっています。
<プリミティブ型 -> 参照型>

  • int -> Integerクラス
  • double -> Doubleクラス
  • boolean -> Booleanクラス
  • long -> Longクラス
  • float -> Floatクラス

<リテラルに関する解説>

変数の定義方法は全て同じ

今までよく目にしている、下のような変数の宣言は理解できていると思います。

int num = 0;
String str = "はじめの一歩";

変数の宣言・初期化は必ず「データ型 変数名 = 代入する値」という形で行います。

これは変数のデータ型がどんなものになっても変わりません。

<変数の扱い方>

データ型とは

以下のものがあります。

  1. int, double, float, lognなどのプリミティブ型と呼ばれる(分類される)変数の型
  2. String, 配列(int[], double[], String[], クラス名[])などの参照型と呼ばれる(分類される)変数の型

例. 変数宣言(初期化)

int num = 0;
String str = "はじめの一歩";
First main = new  FIrst();
List<String> list = new ArrayList<String>();
Scanner scan = new Scanner(System.in);
Random rnd = new Random();

上から順に

  1. int型の変数numを0で初期化
  2. 文字列型(String型)の変数strを"はじめの一歩”で初期化
  3. First型の変数mainをFirstクラスのインスタンスを生成して初期化
  4. List\<String>型の変数listをArrayList\<String>クラスをインスタンス化して代入
  5. Scanner型の変数scanにScannerクラスをインスタンス化して代入
  6. Random型の変数rndにRandomクラスをインスタンス化して代入

式と演算子

演算子には以下のようなものがあります。
算術演算子:「+」 「-」 「*」 「/」 「%」 「^」 「++」 「--」
比較演算子:「==」 「!=」 「「<」 「>」 「<=」 「>=」
論理演算子:「&&」 「||」

そのほかの演算子
instanceof」:クラス型の比較を行います。

String st = "aa";
if (st instanceof String) {
    System.out.println("同じString型です。");
}

代入演算子:「=」値を代入します。

int num = 0; // int型の変数に0を代入
First first = new First(); // First型の変数firstにFirstクラスのインスタンスを代入
String st = "aaa"; // String型の変数stに文字列「aaa」を代入

ここで注意して欲しいのが、「1」と「"」がついていないもの、リテラル(値)は「数値」として扱われる
逆に「"」で囲われているもの、リテラル(値)は文字列としてある変われる

この「=」が、いまいち、ピンとこない人に向けて例を以下に書きます。

public static void main(String[] args) {
    String st = getString();
}
public static String getString() {
     return "String";
}

上のコードは、クラスを省略して書いていますが、メインメソッドから「getString()」というメソッドを呼び出します。
この「getString()」は返り値(戻り値)にString型(文字列型)を定義しています。

なので、「getString()」のメソッドを呼び出したらString型の値を受け取ることができます。

これに対して、クラスをnewして実行した時に関しても同じです。ちょっと長いですが。。。

public class Sample {
    /** フィールド変数 */
    private int field_int = 0;
    private String field_String = "もじれつ";
    //////// 注意(教科書の書き方はほぼ使わない) /////
    // String package_String = "使わない";

    public static void main(String[] args) {
        // Sampleクラス型の変数mainにSampleクラスをインスタンス化して代入
        Sample main = new Sample();
        // 返り値(戻り値)が「void」の場合は変数を受け取る必要がない
        main.hello();
        staticHello();

        // 返り値(戻り値)が定義されている場合(voidになっていない場合)
        // 返り値(戻り値)を受け取ることができる
        Sring result = getString();
        System.out.println("getString()の戻り値は" + result);
    }

    public static void staticHello() {
        System.out.println("Hello World");
    }
    /**
     * <コンストラクタの書き方>
     * アクセス修飾子 クラス名(引数) { ... }
     *
     * newした時の処理を書く
     */
    public Sample() {
        this.field_int = 5;
        this.field_String = "aaaa時の値";
    }

    /**
     * コンストラクタのオーバーロード
     * @param num
     * @param str
     */
    public Sample(int num, String str) {
        this.field_int = num;
        this.field_String = str;
    }

    /**
     * ハローメソッド
     */
    public void hello() {
        System.out.println(this.field_String);
        this.hello("こんにちは、フィールド変数:" + this.field_int);
        this.hello2();
    }
    /**
     * ハローメソッド
     */
    public void hello2() {
        System.out.println(this.field_String);
        this.hello("こんにちは、フィールド変数:" + this.field_int);
        String st = "aa";
        String gg = "ss";
        if (st instanceof String) {
            System.out.println("同じString型です。");
        }
    }

    public String getString() {
        return "String";
    }
}

上記のコードのうち戻り値が「void」のものは以下になります。

  • helllo()
  • hello2()
  • staticHello()

そして。返却値(戻り値)の指定があるもの(voidではないもの)は以下の通りです。

  • getString()

このgetString()メソッドはString型の値を返しますので、呼び出し元(メインメソッド)ではString型の変数resultで受け取っています。
当然受け取らなくても良いので、下のように書いてもエラーは出ません。

getString();

上記の場合は、String型の値を受け取っても、変数に代入していないのでメインメソッドでは使用することができません。
使用する必要がなければ、このようなメソッドの呼び出しもOKです。

if文

条件分岐処理の構文です。

if (論理式) {
   // trueの場合の処理
} else {
  // falseの場合の処理
}

実際に使用するときは下のように書く

String st = "aa";
if (st instanceof String) {
    System.out.println("同じString型です。");
}
if ("aa".equals(st)) {
    System.out.println("stはaaです。");
} else if ("bb".equals(st) ) {
    System.out.println("stはbbです。");
} else {
    System.out.println("stはその他の値です。");
}

それぞれif (論理式) { ... }の「論理式」の部分で値が「true / false」が帰ってきたところで処理の流れが変わります。

論理式

返り値としてbooleanが返される式のことです。以下の指揮がそれにあたります。

boolean isTrue = "aaa".equals("aaa");
boolean isFalse = "aAb".equals("aaa");
isTrue = 1 == 1;
isFalse = 2 == 1;
isTrue = 1 < 2;
isFalse = 1 != 2;

「返る」というのは「=」の反対側に値を渡すという意味です。

switch文

上記のif文と同じ処理がかけます。下のようになります。

switch(st) {
case "aa": 
    System.out.println("stはaaです。");
    break;
case "bb":
    System.out.println("stはbbです。");
    break;
default:
    System.out.println("stはその他の値です。");
}

while文

繰り返し処理の最もシンプルなものです。
下のように論理式の結果が「true」の間繰り返し処理を行います。

int num = 0;
while (num < 10) {
     System.out.println("num = " + num);
     num++;
}

上のコードは「num = 0」〜「num = 9」までを表示します。

for文

繰り返し処理の最もおポピュラーなものです。

for (int i = 0; i < 10; i++) {
     System.out.println("num = " + num);
}

上のコードは「num = 0」〜「num = 9」までを表示します。

大まかに基本文法と変数の扱い方などを記載しました。

Java じゃんけんゲームを作ってみる ~基本文法をマスターする~

じゃんけんゲーム

Javaプログラミングの基本文法を理解するためにも、実際にアプリケーションを作ってみるのが手っ取り早い方法です。

教科書などを眺めても、実践に勝る学習はありません。つまりは。。。

経験に勝る知識なし!

ということです。ちなみに、

サイトマップはこちらです。

Javaプログラム作成時の(推奨する)ルール

  1. クラスの名前ははじめを大文字にして、アルファベットを使用しましょう。キャメルケースといいます

    Ex: SampleClass, FirstClass, MySample ...

  2. メソッドの名前ははじめを小文字にして、アルファベットを使用しましょう。メソッドの場合は、うしろに「()」を付けます。

    Ex: myMethod(), firstMethod(), firstTest(), handleRequest() ...
    クラス名+メソッド名で書きたい場合は「クラス名#メソッド名()」のように書きます。
    例:MyClass#myMethod()

  3. 「{」を一つ入力したら、TAB(インデント)をいれましょう。「}」を入力したらTAB(インデント)を減らしましょう。

    public class FirstTest {
    public static void main(String[] args) {
        // 「{」が2個あるのでTABが2つあります。
        System.out.println("Hello World");
    }
    // 「}」が一つ出てきたので、TABが1つあります。
    }

    これらのルールは、Javaプログラミングの基本的なコーディングルールになるので、ほとんどの会社さんでも使用しているルールです。
    早い話が、現場でも使えるということです。※現場により使えないこともあります。

じゃんけんゲームの処理内容

本来は、自分で考えて仕様を考えるべきですが、初めの一歩ということで仕様を提示します。

仕様とは、「〇〇はXXのように動く」ということを一つ一つ決めて(定義して)、どう動くのか決めることです。

作成するクラスは「JankenPon」クラスにします。

じゃんけんゲームの仕様

  1. 標準入力での、0:グー、1:チョキ、2:パーと定義する。つまり、0が入力されたら「グー」1ならば「チョキ」、2ならば「パー」と判断する
  2. ユーザーの手(入力)とCPUの手(乱数)を表示する
  3. 勝敗判定を行い、「YOU_WIN」、「YOU_LOSE」「DRAW」を表示する

この様に使用を決めたらそれぞれの項目(要件)を満たすようにプログラムを作ります。

0:グー、1:チョキ、2:パーと定義する

標準入力を受け取り、グー~パーを判定します。
どのように実装したらよいでしょうか?

今回は、試しに以下のような実装をしてみましょう。

if文をマスターする

マスターするといっても、普通に使うだけですが。。。
ポイント
次のプログラムは、標準入力を受け付けて、1行分のデータ(入力)を取得します。

Scanner scan = new Scanner(System.in);
scan.nextLine();

ちなみに、下のコードでは、数字以外の入力を行うとエラーが出ます。

public class FirstSample {
    public static void main(String[] args) {
        Scanner scan = new Scanner(System.in);
        int input = Integer.parseInt(scan.nextLine());
        String jankenTe = null;
        if (input == 0) {
            jankenTe = "グー";
        } else if (input == 1) {
            jankenTe = "チョキ";
        } else if (input == 2) {
            jankenTe = "パー";
        } else {
            System.out.println("想定外の値です。" + input);
        }
    }
}

じゃんけんの手をString型の変数JankenTeに設定(代入)します。
0, 1, 2以外の値が入力されたときは想定外の値です。

IF文を使用したときの動画

ユーザーの手(入力)とCPUの手(乱数)を表示する

CPUの手を乱数を使って表示します。これはもう説明する必要はないと思います。

public class SecondSample {
    public static void main(String[] args) {
        // 0-2の乱数を生成する
        cpuTe = String.valueOf(new Random().nextInt(2));

        if (cpuTe.equals("0")) {
            jankenCpu = "グー";
        } else if (cpuTe.equals("1")) {
            jankenCpu = "チョキ";
        } else if (cpuTe.equals("2")) {
            jankenCpu = "パー";
        }
    }
}

これも、if文で実装することができます。もちろん、より良いアイディアがあればそちらの実装を行うのが正しい判断です。検証するのを忘れないようにしてください。

勝敗判定を行い、「YOU_WIN」か「YOU_LOSE」「DRAW」を表示する

勝敗判定は、ちょっと良いアイディアが出ず。。。そのまま判定処理を作りました。
はっきり言ってダメダメなコードです。

public class ThirdSample {
    public static void main(String[] args) {
        String hantei = input + cpuTe;
        String result = null;
        if (hantei.equals("01")) {
            result = "YOU_WIN";
        } else if (hantei.equals("12")) {
            result = "YOU_WIN";
        } else if (hantei.equals("20")) {
            result = "YOU_WIN";
        } else if (hantei.equals("00")) {
            result = "DRAW";
        } else if (hantei.equals("11")) {
            result = "DRAW";
        } else if (hantei.equals("22")) {
            result = "DRAW";
        } else if (hantei.equals("02")) {
            result = "YOU_LOSE";
        } else if (hantei.equals("10")) {
            result = "YOU_LOSE";
        } else if (hantei.equals("21")) {
            result = "YOU_LOSE";
        } else {
            System.out.println("想定外の値です。" + hantei);
        }
    }
}

何とかじゃんけんゲームができました。しかし、このようなプログラムは美しくありません。

別に「アーティスチックでないからダメ」といっているわけではなく、見ずらいし、わかりずらい。

人にやさしくないプログラムが「ダメダメ」だということです。

人にやさしく

ズバリ、読みやすく、理解しやすいコードが良いブログラムです。もちろん、余計なメモリを使わないとかいろいろありますが。。。

ちなみに、上のようなコードで作成したじゃんけんゲームは以下のようなコードになりました。

public static void main(String[] args) {
    // 1.初めの処理
    System.out.println("じゃんけん ...");
    Scanner scan = new Scanner(System.in);

    // 2.標準入力受付
    String input = scan.nextLine();
    String jankenTe = null;

    // 3.ユーザーの手を判定する
    if (input.equals("0")) {
        jankenTe = "グー";
    } else if (input.equals("1")) {
        jankenTe = "チョキ";
    } else if (input.equals("2")) {
        jankenTe = "パー";
    } else {
        System.out.println("想定外の値です。" + input);
    }

    String cpuTe = null;
    String jankenCpu = null;
    if (jankenTe == null) {
        // 強制終了
        System.exit(-1);
    } else {
        // 4.CPUの手を判定する
        cpuTe = String.valueOf(new Random().nextInt(2));

        if (cpuTe.equals("0")) {
            jankenCpu = "グー";
        } else if (cpuTe.equals("1")) {
            jankenCpu = "チョキ";
        } else if (cpuTe.equals("2")) {
            jankenCpu = "パー";
        }
    }
    System.out.println("ポン");
    System.out.println("あなた: " + jankenTe + " CPU; " + jankenCpu);

    // 5.勝敗判定を行う
    String hantei = input + cpuTe;
    String result = null;
    if (hantei.equals("01")) {
        result = "YOU_WIN";
    } else if (hantei.equals("12")) {
        result = "YOU_WIN";
    } else if (hantei.equals("20")) {
        result = "YOU_WIN";
    } else if (hantei.equals("00")) {
        result = "DRAW";
    } else if (hantei.equals("11")) {
        result = "DRAW";
    } else if (hantei.equals("22")) {
        result = "DRAW";
    } else if (hantei.equals("02")) {
        result = "YOU_LOSE";
    } else if (hantei.equals("10")) {
        result = "YOU_LOSE";
    } else if (hantei.equals("21")) {
        result = "YOU_LOSE";
    } else {
        System.out.println("想定外の値です。" + hantei);
    }
    // 6. 結果の表示
    System.out.println(hantei);
    System.out.println(result);
}

別の記事になりますが、「じゃんけんゲーム in コンソール」の記事になります。

しかし、やはりだめなコード(個人的にそのように思う)なので、これをまともなコードに直します。

この様な行為のことをリファクタリングといいます。

リファクタリング

まずは、読みずらいところを洗い出します。
以下の部分が読みずらいと思いました。

if文のネスト(階層化しているところ)が無駄なネストになっている

String cpuTe = null;
String jankenCpu = null;
if (jankenTe == null) {
    // 強制終了
    System.exit(-1);
} else {
    // 4.CPUの手を判定する
    cpuTe = String.valueOf(new Random().nextInt(2));

    if (cpuTe.equals("0")) {
        jankenCpu = "グー";
    } else if (cpuTe.equals("1")) {
        jankenCpu = "チョキ";
    } else if (cpuTe.equals("2")) {
        jankenCpu = "パー";
    }
}

どこが、無駄かというとelse~の部分です。もしjannkenTeがnullになっているのならば、プログラムを強制終了するので、if-elseでわける意味がありません。無駄なコードになっているのです。

ではどのようになおすか?ズバリ下のように直します。elseが丸まる必要ないのです。

String cpuTe = null;
String jankenCpu = null;
if (jankenTe == null) {
    // 強制終了
    System.exit(-1);
}

// 4.CPUの手を判定する
cpuTe = String.valueOf(new Random().nextInt(2));

if (cpuTe.equals("0")) {
    jankenCpu = "グー";
} else if (cpuTe.equals("1")) {
    jankenCpu = "チョキ";
} else if (cpuTe.equals("2")) {
    jankenCpu = "パー";
}

処理の内容を考えてみれば、不要ですよね?なぜなら

System.exit(-1);

でプログラムは強制終了(引数に「-1」を与えているので『異常終了』)するからです。

つまり、if文の中の処理を行うとき=jankenTeがnullの時は「CPUの手を判定」より後の処理が行われません。

メソッドを利用する

その他にも、イケていないところがあります。それは、似たような処理がたくさんあるというところです。
特にif文の処理が同じような処理を行っています。

なので、メソッドを作成して同じコードを書かないようにします。

今までに、ちょこっと書いたりしました。改めて理解しましょう。

具体的には、以下のif文です。2か所、同じコードがあります。

String jankenTe = null;
if (input.equals("0")) {
    jankenTe = "グー";
} else if (input.equals("1")) {
    jankenTe = "チョキ";
} else if (input.equals("2")) {
    jankenTe = "パー";
} else {
    System.out.println("想定外の値です。" + input);
}

これをメソッドとして切り出します。具体的には下のように切り出します。staticがついているのはメインメソッドから呼び出すためです。

public static String jankenHantei(String input) {
    String jankenTe = null;
    if (input.equals("0")) {
        jankenTe = "グー";
    } else if (input.equals("1")) {
        jankenTe = "チョキ";
    } else if (input.equals("2")) {
        jankenTe = "パー";
    } else {
        System.out.println("想定外の値です。" + input);
    }
    return jankenTe;
}

そして、このコードと同じ部分を書き換えます。下のようなコードになりました。

public class JankenPon {
    public static void main(String[] args) {
        // 1.初めの処理
        System.out.println("じゃんけん ...");
        Scanner scan = new Scanner(System.in);

        // 2.標準入力受付
        String input = scan.nextLine();
        // 3.ユーザーの手を判定する
        String jankenTe = jankenHantei(input);

        String cpuTe = null;
        String jankenCpu = null;
        if (jankenTe == null) {
            // 強制終了
            System.exit(-1);
        }
        // 4.CPUの手を判定する
        cpuTe = String.valueOf(new Random().nextInt(2));
        jankenCpu = jankenHantei(cpuTe);

        System.out.println("ポン");
        System.out.println("あなた: " + jankenTe + " CPU; " + jankenCpu);

        // 5.勝敗判定を行う
        String hantei = input + cpuTe;
        String result = null;
        if (hantei.equals("01")) {
            result = "YOU_WIN";
        } else if (hantei.equals("12")) {
            result = "YOU_WIN";
        } else if (hantei.equals("20")) {
            result = "YOU_WIN";
        } else if (hantei.equals("00")) {
            result = "DRAW";
        } else if (hantei.equals("11")) {
            result = "DRAW";
        } else if (hantei.equals("22")) {
            result = "DRAW";
        } else if (hantei.equals("02")) {
            result = "YOU_LOSE";
        } else if (hantei.equals("10")) {
            result = "YOU_LOSE";
        } else if (hantei.equals("21")) {
            result = "YOU_LOSE";
        } else {
            System.out.println("想定外の値です。" + hantei);
        }
        // 6. 結果の表示
        System.out.println(hantei);
        System.out.println(result);
    }

    public static String jankenHantei(String input) {
        String jankenTe = null;
        if (input.equals("0")) {
            jankenTe = "グー";
        } else if (input.equals("1")) {
            jankenTe = "チョキ";
        } else if (input.equals("2")) {
            jankenTe = "パー";
        } else {
            System.out.println("想定外の値です。" + input);
        }
        return jankenTe;
    }
}

これで、多少はよくなりました。しかし、まだです。

Mapインターフェースを使用する

じゃんけんの判定方法ですが、すごく頭の悪いやり方です。しかし、これから見せるコードも頭の良いやり方ではありません。なぜかというと、何の工夫もないからです。

頭の良いやり方ではない方法
まずは下のような、フィールド変数(定数)とメソッドを作成します。

<フィールド変数とは>
Javaクラスの持つことのできる要素の一つです。
具体的には、フィールド変数は、変数であり、クラスの中であればどこでも使用することができます。
UMLという表現方法では、下のように書きます。
Diagram1

同時に、クラスが持つ要素を表します。「属性」はフィールド変数、「操作」はメソッドを示します。
例えば、ボタンを押したらカウンターをカウントアップするアプリケーションを考えてみましょう。
「ボタンを押す」という操作(メソッド)を使用すると、「カウンター」という属性を1カウントアップ(プラス1)するという具合に、各要素を使用します。

つまりは、以下のような特徴があります。

  • フィールド変数はデータの管理、他のクラスを保持する変数。
  • メソッドは何かしらの処理(操作)を行うためのプログラムをまとめたもの。

<実際のコード>

public class SampleClass {
    /** フィールド変数(定数) */
    public static final String YOU_WIN = "YOU_WIN";
    public static final String YOU_LOSE = "YOU_LOSE";
    public static final String DRAW = "DRAW";</pre>

    // そして、次のメソッドを追加します。
    public static String jankenHantei(String input) {
        String jankenTe = null;
        if (input.equals("0")) {
            jankenTe = "グー";
        } else if (input.equals("1")) {
            jankenTe = "チョキ";
        } else if (input.equals("2")) {
            jankenTe = "パー";
        } else {
            System.out.println("想定外の値です。" + input);
        }
        return jankenTe;
    }
}

作成したメソッドを使用して、メインメソッドを書き直します。

そうすると下のようになりました。

public class Chap0 {
    public static final String YOU_WIN = "YOU_WIN";
    public static final String YOU_LOSE = "YOU_LOSE";
    public static final String DRAW = "DRAW";

    public static void main(String[] args) {
        // 1.初めの処理
        Map<String, String> hanteiMap = createMap();
        System.out.println("じゃんけん ...");
        Scanner scan = new Scanner(System.in);

        // 2.標準入力受付
        String input = scan.nextLine();
        // 3.ユーザーの手を判定する
        String jankenTe = jankenHantei(input);

        String cpuTe = null;
        String jankenCpu = null;
        if (jankenTe == null) {
            // 強制終了
            System.exit(-1);
        }
        // 4.CPUの手を判定する
        cpuTe = String.valueOf(new Random().nextInt(2));
        jankenCpu = jankenHantei(cpuTe);

        System.out.println("ポン");
        System.out.println("あなた: " + jankenTe + " CPU: " + jankenCpu);

        // 5.勝敗判定を行う
        String hantei = input + cpuTe;
        String result = hanteiMap.get(hantei);
        // 6. 結果の表示
        System.out.println(hantei);
        System.out.println(result);
    }

    public static String jankenHantei(String input) {
        String jankenTe = null;
        if (input.equals("0")) {
            jankenTe = "グー";
        } else if (input.equals("1")) {
            jankenTe = "チョキ";
        } else if (input.equals("2")) {
            jankenTe = "パー";
        } else {
            System.out.println("想定外の値です。" + input);
        }
        return jankenTe;
    }

    public static Map<String, String> createMap() {
        Map<String, String> hanteiMap = new HashMap<String, String>();
        hanteiMap.put("01", YOU_WIN);
        hanteiMap.put("12", YOU_WIN);
        hanteiMap.put("20", YOU_WIN);
        hanteiMap.put("00", DRAW);
        hanteiMap.put("11", DRAW);
        hanteiMap.put("22", DRAW);
        hanteiMap.put("02", YOU_LOSE);
        hanteiMap.put("10", YOU_LOSE);
        hanteiMap.put("21", YOU_LOSE);

        return hanteiMap;
    }
}

実行結果は下のような形で出力されました。

じゃんけん ...
1
ポン
あなた: チョキ CPU; チョキ
11
DRAW

如何でしょうか?だいぶすっきりしたように見えると思います。プログラムの処理内容が理解できていれば、無図解ことではありません。「このような方法もある」というのを知っておくと後々にカッコよいコードが書けるようになります。※自分も努力いたします。。。

<スマホアプリ版じゃんけんゲーム>※GLUONを使用

でわでわ。。。

Java Basic 実践学習編 〜変数の使用とデータ型、条件分岐、コードブロック〜

イントロダクション

前回は「Java Basic 実践学習編 〜ハローワールドから変数の宣言・初期化〜」を行いました。

今回は、表題の通りです。

変数の使用

前回も行いましたが、下のように、変数を宣言、初期化して使用します。

変数の宣言と初期化

<Code.09>

public class HelloWorld {
    public static void main(String[] args) {
        // 変数の宣言
        int seisu;
        // 変数の初期化
        double shosu = 0.0;
        // 変数の初期化
        String moji = "文字列";
    }
}
九九の二の段

<Code.10>

public static void main(String[] args) {
    int a = 2;
    int x = 1;
    System.out.println("2 x 1 = " + a * x);
    x++;
    System.out.println("2 x 2 = " + a * x);
    x++;
    System.out.println("2 x 3 = " + a * x);
    x++;
    System.out.println("2 x 4 = " + a * x);
    x++;
    System.out.println("2 x 5 = " + a * x);
    x++;
    System.out.println("2 x 6 = " + a * x);
    x++;
    System.out.println("2 x 7 = " + a * x);
    x++;
    System.out.println("2 x 8 = " + a * x);
    x++;
    System.out.println("2 x 9 = " + a * x);
}

上のコードは、九九の二の段を表示するプログラムです。ここでは変数xの値をインクリメントすることで、二の段の計算結果を表示しています。

変数の宣言と初期化を確認したところで次のコードに行きます。

コードブロック

一旦立ち止まって振り返ります。今まで動かしていた「メインメソッド」は下のように書きます。
この時に「{」から「}」までの間がメインメソッドの範囲、コードブロックになります。

<Code.11>

public static void main(String[] args) {
    // 何かしらの処理
}

これは決まっている部分ですので、そのまま覚えても問題ありません。と言うか自分は覚えました。

ポイント

「{}」は「中かっこ」、「波かっこ」など色々な言い方がありますが、「{}」の括弧で囲まれた部分が「ブロック」になります。
具体的には<Code.11>の「{」から「}」までの間が「(コード)ブロック」にあたります。

これは、スコープともいい「{」から「}」までの間だけ変数が機能します。
具体的には、下のように書くと変数「num」はエラーになると言うところです。

変数の有効範囲

<Code.12>

public static void main(String[] args) { // ここからメインメソッドのブロック
    int a = 0;
    if (a == 1) { // ここからIFのブロック
        int num = 0;
        num++;
    } else { // ここからelseのブロック
        num = 10; // ここでエラー
    }
}

「{」から「}」までの間が、変数のスコープ、機能する範囲なのでif() { ... }の中で宣言(初期化)された変数「num」はelse { ... }の範囲では機能しないのです。

詳細は以下のようになります。

  1. 1行目はメインメソッドの定義、メソッドの宣言
  2. 2行目でint型(整数型)の変数「a」の初期化
  3. if文で「aの値が1のときIFブロックに処理が進む」
  4. 同様に「if文の条件以外のばあいelseのブロックに進む」

この様に、メインメソッドのブロックの中に、ifのぶろっくとelseのブロックがあります。

そして、これを次のように書き換えるとエラーは出ません。

<Code.13>

public static void main(String[] args) {
    int a = 0;
    int num = 0;
    if (a == 1) {
        num++;
    } else {
        num = 10;
    }
}

変数「num」がメインメソッドのスコープ内で宣言されているので、その中にあるif() { ... }の中でもelse { ... }でも両方で機能することができます。

なので、次のようなコードでは、メソッドの中で宣言していてもエラーになります。別のメソッドだから、スコープの範囲が違うためです。

<Code.14>

public static void main(String[] args) {
    int a = 0;
    int num = 0;
    if (a == 1) {
        num++;
    } else {
        num = 10;
    }
}

/** メンバメソッド */
public void test1() {
    num; // ここでエラー
    System.out.println("test1");
    System.out.println("2 / 2 = " + 2 / 2);
}

ポイント

変数のスコープと言うのがありそれは「{」から「}」までの間がその範囲になります。
なので変数の宣言が、「{」から「}」までの間の外にあればそれはそれはエラーになります。

クラスとメソッドについて

今までプログラムを何個か作成してきましたが、Javaのプログラムを動かすための単位は「クラス」になります。
このクラスは下のように書き、フィールドとメソッドを持っています。

<Code.15>

public class HelloWorld {
    /** フィールド */
    private int field;

    /** メソッド */
    public void method(String hikisu) {
        int a = 0;
        int num = 0;
        if (a == 1) {
            num++;
        } else {
            num = 10;
        }
    }
}

このルールで、作成したクラスに「メインメソッド」を追加しているのです。今までに作成したものはメインメソッドのみでしたが。。。クラスとしては成り立つのです。ちょっと極端ですが、空クラスも、作成すればあります。

public class Kara {
}

Javaの実装ルールに違反していないのでOKなのです。まぁ作成する意味もないですが。。。

条件分岐

if文

次は、<Code.13>で出てきたif文に関して学習します。
俗にいう条件分岐です。これは、プログラムを実行するときに「~の場合の処理」と条件を付けて処理を分けたいときに使用します。具体的に以下のようなコードです。

<Code.16>

public static void main(String[] args) {
    int num = 10;
    if (num == 10) {
        System.out.println("No10");
    } else {
        System.out.println("Not No10");
    }
}

int型(整数型)の変数numが10の時「No10」とコンソールに表示します。それ以外の時は「Not No10」と表示します。
この場合は、プログラムを書き換えて変数numの値を変更してやる必要があります。

なので、プログラム引数を使用してプログラムを書き換えなくてもよいように修正します。

プログラム引数

プログラム引数は、Javaプログラムを実行するときに渡せる引数のことで、引数はString型の値になります。
ただし、文字列を複数渡すことができるのでString[](String型の配列)になっています。

具体的には下のように使用します。

コードとしては、動画のものと違いますが、下のように使います。

public static void main(String[] args) {
    // プログラム引数を取得する
    int num = Integer.parseInt(args[0]);
    if (num == 10) {
        System.out.println("No10");
    } else {
        System.out.println("Not No10");
    }
}

しかし、このコードでは、プログラム引数が渡されてないい場合はエラーになります。

なので次のように書き換えます。
<Code.17>

public static void main(String[] args) {
    // プログラム引数を取得する
    int num;
    if (args[0] != null && args[0].matches("[0-9]{1}")) {
        num = Integer.parseInt(args[0]);
    } else {
        num = 10;
    }

    if (num == 10) {
        System.out.println("No10");
    } else {
        System.out.println("Not No10");
    }
}

このように、想定外の入力があったときを考慮してプログラムを作成するとエラーが出ない、安全なプログラムができます。リアルでもプログラムでも安全第一です

処理の内容に関して
初めの

if (args[0] != null && args[0].matches("[0-9]{1}")) {

を分解して説明します。
if文に関しては後に説明しますが、

args[0].matches("[0-9]{1}") {

の部分に関して
この部分はString型のメソッドを使用しています。実はString型はJavaAPIで定義されているクラスなのです。
String[]はString型の配列ですので、配列の中身はString型の変数です、

String[0]

String[] hako = {"もじ", "123", "aaa"};

と初期化したときの「"もじ"」に当たります。
つまり

String[0] => "もじ", String[1] => "123", String[2] => "aaa"

となります。

なので、Stringクラスのメソッド「matches」を使用することができます。

このメソッドの処理は引数に「正規表現」を渡し返り値に正規表現にマッチするかどうか?を返す処理になります。

具体的には下のようになります。
<Code.18>

public static void main(String[] args) {
    String aa = "12345";
    boolean isNumber = aa.matches("[0-9]{1,}");
    System.out.println("入力値: " + aa + "は、正規表現「[0-9]{1,}」にマッチするか?: " + isNumber);

    boolean isAtoZ = aa.matches("[A-Z]{1,}");
    System.out.println("入力値: " + aa + "は、正規表現「[0-9]{1,}」にマッチするか?: " + isAtoZ);
}

実行結果は以下の通りです。

条件分岐本題

if文になれてきたところで、プログラムを理解していきましょう。

<Code.13>を見てください。初めのif文で変数aaの値が10の時...と処理が書いてあります。

public static void main(String[] args) {
    int num = 10;
    if (num == 10) {
        System.out.println("No10");
    } else {
        System.out.println("Not No10");
    }
}

ここでのnum == 10の部分が論理式になります。論理式とは返却値に真偽値(trueもしくはfalse)を返します。
コードで書くと下のようになります。

boolean is10 = num == 10;

何度も記載しますが、booleanは真偽値のデータ型です。true, falseどちらかの値しか持ちません。
なので、変数「num」が10の場合は、true, そうでない場合はflaseが変数「is10」に代入されます。

ちょっと座学臭い感じですが、「=」演算子は式の値を代入します。
初めの方に実装しましたが、変数の初期化を行った時には「=」で宣言と同時に値を代入します。

int num = 10;

同様に、初期化でなくても値は代入する事ができます。

num = 9;

下のように、プログラムを書いたときは変数「num」の値が変わって聞きます。そして、プログラムは必ず上から下に流れます。
<Code.19>

public static void main(String[] args) {
    int num = 10;
    if (num == 10) {
        num = 20;
    } else {
        num = 3;
    }
    if (num == 20) {
        System.out.println("Hello");
    } else {
        System.out.println("Bye");
    }
}

このコードは、「Hello」が表示されます。以下のように処理が進みます。

  1. int型の変数numを10で初期化
  2. もしnumが10であれば、numに20を代入
    3.それ以外ならnumに3を代入
  3. もしnumが20であれば、「Hello」を表示
  4. それ以外なら「Bye」を標示

条件分岐のバリエーション

if-elseを理解できたと思います。これに追加してelse-ifがあります。具体的には下のように書きます。
<Code.20>

public static void main(String[] args) {
    int num = 10;
    if (num == 10) {
        num = 20;
    } else if (num == 20){
        num = 3;
    } else {
        num = 2;
    }
    if (num == 20) {
        System.out.println("Hello");
    } else if (num == 3) {
        System.out.println("Else if");
    } else {
        System.out.println("Bye");
    }
}

今までの条件に「そのほかに、もしnumが20の時」という文言が加わりました。
作り方はif文の時と同じです。

文章をつなげると「もじnumが10ならば~その他にもし、numが20ならば~、それ以外なら~」というような文章、プログラムができました。

switch文

switch文はif文と同じです。ただ書き方が違います。
if文は以下のように書きます。

if (論理式A) {
    // 論理式Aがtrueときの処理
} else if (論理式B) {
    // 論理式Bがtrueときの処理
} else {
    // 何かしらの処理
}

switch文は以下の通りです。

switch (変数) {
case XX:
    // 変数がXの時のケース
    break;
case YY:
    // 変数がYの時のケース
    break;
default:
    // 変数が上記以外のとき
}

<Code.20>をswitch文に書き換えると下のようになります。

public static void main(String[] args) {
    int num = 10;
    switch (num) {
    case 10:
        System.out.println("No8");
        break;
    case 20:
        System.out.println("No9");
        break;
    default:
        System.out.println("それ以外");
    }
}
ポイント

このプログラムの

break;

に注目して下さい。この分がないとどうなるでしょうか?
<Code.21>

switch (num) {
case 8:
    System.out.println("No8");
case 9:
    System.out.println("No9");
default:
    System.out.println("それ以外");
}
if (num == 0) {
    break;
}

出力結果はいかのようになりました。入力値は「8」です。

8
No8
No9
それ以外

入力値が「9」の場合は

9
No9
それ以外

同様に上記以外の入力、「5」を入力しました。

5
それ以外

つまるところは、breakがないとそれ以降の処理がすべて動いてしまうということです。

ループ文

while文

やって来ました。ループ文です。ここまで来た方おめでとうおございます。
プログラミングで遊ぶ材料がそろいました。

まずは下のループ文を見てください。

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);

    while(true) {
        int num = scan.nextInt();

        switch (num) {
        case 8:
            System.out.println("No8");
            break;
        case 9:
            System.out.println("No9");
            break;
        default:
            System.out.println("それ以外");
        }
    }
}
while(true) { ... }

これは無限ループのプログラムの型です。
「{}」の間(スコープ)を無限ループします。

このままだとプログラムが終了しません。

では、どのようにプログラムを終了するか?

特定の入力があった場合にプログラムを終了するようにプログラムを作ります。

今回利用しているJavaAPIは、java.util.Scannerです。
そして、使用しているメソッドはnextInt()です。

終了するための処理は下のコードです。

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);

    while(true) {
        int num = scan.nextInt();

        switch (num) {
        case 8:
            System.out.println("No8");
            break;
        case 9:
            System.out.println("No9");
            break;
        default:
            System.out.println("それ以外");
        }
        if (num == 0) {
            break;
        }
    }
}

上のコードを説明すると。。。

  1. Scanner scan = new Scanner(System.in);で標準入力の受付クラスをインスタンス化
    標準入力を受け付けられるようにします。
  2. while(true) {で無限ループを開始します。
  3. int num = scan.nextInt();で標準入力を待ち受けます。
  4. あとはswitch文で受け取った値の判定をしてそれぞれの処理を行います。
  5. if (num == 0) {入力値を代入した変数「num」が0の場合「{}」内の処理を行います。
  6. break;無限ループを抜けます。

for文

この無限ループは、ゲームを作成するときの基本的なプログラムになります。
そして、今回は回数制限のある「おみくじゲーム」を作成します。

占い回数を入力して、今日の運勢を%で算出します。

public static void main(String[] args) {
    Scanner scan = new Scanner(System.in);

    System.out.println("今日の運勢を占います。占う回数を入力してください。");
    int num = 0;
    while(true) {
        num = scan.nextInt();
        if (num > 3) {
            System.out.println("3以下の値を入力してください");
            continue;
        }
        break;
    }
    System.out.println(num + "回占います。");

    int sisu = 0;
    for (int i = 0; i < num; i++) {
        int unsei = new Random().nextInt(3);
        if (unsei == 0) {
            System.out.println((i + 1) + "回目: 大吉");
            sisu += 4;
        } else if (unsei == 1) {
            System.out.println((i + 1) + "回目: 中吉");
            sisu += 3;
        } else if (unsei == 2) {
            System.out.println((i + 1) + "回目: 吉");
            sisu += 2;
        } else {
            System.out.println((i + 1) + "回目: 凶");
            sisu += 1;
        }
    }
    System.out.println("sisu: " + sisu);
    int un = new BigDecimal(sisu).divide(new BigDecimal(num * 4), 2, RoundingMode.DOWN).multiply(new BigDecimal(100)).intValue();
    System.out.println("un: " + un);
    System.out.println("今日の運勢は、" + un + "%好調です。");
}

これを改造するもよし、アイディアを出して別のものにするもよし、
遊んでみてください。

ポイント

今回使用したループ文はfor文といって下のように書きます。

for (カウンタの初期化; ループする論理式; ループした後の処理) {
    // 何かしらの処理
}

これは、どのような意味かというとfor int i = 0; i < 10; i++) { .. }<code>とコードを書いたときの場合は、int(整数)型の変数を0で初期化(</code>int i = 0<code>)して、この変数が10よりも小さい(i < 10)間、ループするたびにあとの処理(</code>i++)を行います。

ループ文の練習です、下のような問題があります。

問題1「4回ループするfor文を作ってください」

<for文の場合>

for (int i = 0; i < 5; i++) {
    System.out.pprintln("Hello" + i);
}

処理の順序は下のようになります。

  1. int型(整数型)の変数iを0で初期化
  2. i = 0なので論理式「i < 5」の評価後の値は「0 < 5」でtrue
  3. 論理式の値がtrueなので「{}」の中の処理を行う
  4. 「Hello0」を表示した後に
    i++

    の処理を行う

  5. iが1になったので、論理式
    i < 5

    の評価の値は「1 < 5」でtrue

  6. 「Hello1」を表示した後に
    i++

    の処理を行う

  7. iが2になったので、論理式
    i < 5

    の評価の値は「2 < 5」でtrue

  8. 「Hello2」を表示した後に
    i++

    の処理を行う

  9. iが3になったので、論理式
    i < 5

    の評価の値は「3 < 5」でtrue

  10. 「Hello3」を表示した後に
    i++

    の処理を行う

  11. iが4になったので、論理式
    i < 5

    の評価の値は「4 < 5」でtrue

  12. 「Hello4」を表示した後に
    i++

    の処理を行う

  13. iが5になったので、論理式
    i < 5

    の評価の値は「5 < 5」でfalse

  14. 論理式の値がfalseになったのでループを終了する

<while文の場合>

int i = 0;
while(i < 5) {
    System.out.println("Hello" + i);
    i++;
}
  1. int型(整数型)の変数iを0で初期化
  2. i = 0なので論理式「i < 5」の評価後の値は「0 < 5」でtrue
  3. 論理式の値がtrueなので「{}」の中の処理を行う
  4. 「Hello0」を表示した後に
    i++

    の処理を行う

  5. iが1になったので、論理式
    i < 5

    の評価の値は「1 < 5」でtrue

  6. 「Hello1」を表示した後に
    i++

    の処理を行う

  7. iが2になったので、論理式
    i < 5

    の評価の値は「2 < 5」でtrue

  8. 「Hello2」を表示した後に
    i++

    の処理を行う

  9. iが3になったので、論理式
    i < 5

    の評価の値は「3 < 5」でtrue

  10. 「Hello3」を表示した後に
    i++

    の処理を行う

  11. iが4になったので、論理式
    i < 5

    の評価の値は「4 < 5」でtrue

  12. 「Hello4」を表示した後に
    i++

    の処理を行う

  13. iが5になったので、論理式
    i < 5

    の評価の値は「5 < 5」でfalse

  14. 論理式の値がfalseになったのでループを終了する

こんな風に作成します。

今までに学習してきたことは大まかに下のようなことです。

  • リテラルの理解
  • 変数・データ型の理解
  • 条件分岐の理解
  • ループ文、繰り返し処理の理解

これらの処理、文法がプログラミングの基本になります。この基本は「初めの一歩」にして「奥義」たりえます。
基本を極めればどんなプログラムでも対応する事ができます。

そして、楽しく学習するのが一番学習効果が高いので「楽しく」プログラミングできるように想像力を働かせましょう。

具体的には「~出来たら面白そうだ」などと考えてみましょう。もしかしたらものすごい発見があるかもしれません。

でわでわ。。。

<<<前回

Java Basic 実践学習編1 〜ハローワールドから変数の宣言・初期化〜

Javaの実践学習

今までに、色々と学習してきましたが、効率と理解度を考慮に入れるとズバリ下のような学習方法が一番だと思いました。

  1. コードを書く
  2. コードを動かす
  3. コードを書き換えて動かしてみる
  4. コードを理解する

この順序でいろんな書き方、プログラムの組み方を理解していくのが最もわかり易く、実践で使えると思いました。

この手順を使用してJavaの基本をやり直したいと思います。

初めてのJava

以前書いた記事はこちらです。

Lv1.ハローワールド

初めてのプログラムとして有名なものですが、これはJava言語に限ったことではありません。C言語、Python, C#, java script etc ...でも同じことです。
プログラムを起動して、「Hello World」と表示するだけのプログラムです。

このプログラムは、大きなアプリケーションに新たに取り組む、もしくはフレームワークを使用するなどの時に「プログラムが動くよね?」という確認のために使用することが多いです。

そして、自分はJava屋なので、Java言語で実装を行います。

下のコードは、「Hello クラス」を作成し、そこにメインメソッドを作成しました。とりあえずこれを書き写して動かしてみましょう

<Code.01>

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
    }
}

Eclipse(開発ツール(IDE))での実行した時の動画は以下になります。

シンプルに、コンソール(標準出力)への文字列出力になります。

ポイント1

プログラムが動くことを確認するというところです。

Lv2.適当な文字の出力

上のコードを書き換えて、出力内容を変更します。

<Code.02>

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("I am Takunoji. It's verry hard.");
    }
}

出力した文言の言っていることは、意味がわかりませんが、とりあえずは、出力内容が変わります。

コードの実行確認は、読者の皆さんが行ってください。
※コピペしないほうが、理解も早いです。

ポイント2

"(ダブルクォーテーション)で囲った部分が文字列としてJVM(Javaを起動する機械、java.exeのこと)に、認識されます。
まとめると下のようなイメージになります。

System.out.println(「文字列」);

この「文字列」の部分を引数と呼びます。<Code.02>のコードを説明すると
printlnメソッドの引数に文字列「I am Takunoji. It's verry hard.」を渡している」と説明できます。

よくあるミス

下のコードはエラーになります。

<Code.03>

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("I am Takunoji. It's verry hard.);
    }
}

すぐに気がつく人は気がつくのですが、気がつかない人はなかなか気がつきません。
自分がそうです。苦労しました、今でも、汚いコードとかにある、このような「小さなミス」を見つけるのに一苦労します。

コードは綺麗に書きましょう

一言で言うと自分があとで苦労します。。。

余談:綺麗なコードとは

単純に、以下の部分がポイントです。

  1. インデントが揃っている
  2. 余計な変数宣言がない
  3. 同じ名前の変数を別の用途に使いまわさない
  4. 処理が整理されていて、どの処理がどこにあるのかわかるようになっている

大まかに上のようなコードです。詳細に関しては、今後理解して行けば良いと思います。とりあえず書いて動かしてみましょう。

Lv3.計算をしてみる

単純な足し算と引き算をコンソールに出力します。

<Code.04>

public class HelloWorld {
    public static void main(String[] args) {
        // 足し算
        System.out.println("1 + 1 = " + (1 + 1));
        // ひき算
        System.out.println("1 - 1 = " + (1 - 1));
    }
}

上のコードは、文字列「1 + 1 = 」に「1 + 1」の計算結果を文字列として連結して、出力しています。
次の行では、同様に、文字列「1 - 1 = 」に「1 - 1」の計算結果を文字列として連結して、出力しています。

ポイント3

ポイント2でも説明しましたが、System.out.println("1 + 1 = " + (1 + 1));<code>の</code>"1 + 1 = " + (1 + 1)の部分が引数になります。
この引数は"1 + 1 = "<code>が文字列を示し、</code>(1 + 1)が計算処理でその結果は2になります。
最後に、"1 + 1 = " + (1 + 1)にある真ん中の「+」が文字列の連結処理を行っているところです。

文字列の隣に来る「+」は文字連結を示します。

では、次のコードを見て見ましょう、掛け算と割り算です。

<Code.05>

public class HelloWorld {
    public static void main(String[] args) {
        // かけ算
        System.out.println("2 * 2 = " + 2 * 2);
        // わり算
        System.out.println("2 / 2 = " + 2 / 2);
    }
}

ポイント4

このコードは、掛け算と割り算を行なっています。しかし、<Code.04>と比べてみるとかっこが足りません。
具体的に"1 + 1 = " + (1 + 1)<code>と</code>"2 * 2 = " + 2 * 2の部分です。

この部分は暗黙的なルールがあり、中学生くらいに習ったと思いますが、「足し算と掛け算」があったら「掛け算」の方を先に計算すると言うルールがあったと思います。

プログラムでも同じなんです。

つまるところは以下のような理由で、上のような違いがあります。

<足し算と引き算の場合>

public static void main(String[] args) {
    // 足し算
    System.out.println("1 + 1 = " + (1 + 1));
    // ひき算
    System.out.println("1 - 1 = " + (1 - 1));
}

足し算と引き算の場合は、()かっこが必要です。それは「文字を連結する」と言う処理と、「計算をする」と言う処理にしようする演算子(「+」のこと)が同じなため

"1 + 1 = " + 1 + 1

のように書くと文字連結か、計算するかJavaコンパイラが判別できないためエラーになります。

<掛け算と割り算の場合>

public static void main(String[] args) {
    // かけ算
    System.out.println("2 * 2 = " + 2 * 2);
    // わり算
    System.out.println("2 / 2 = " + 2 / 2);
}

見た目にも、「+」と「*」で演算子が違うので「文字列の連結」と「計算」の区別がつきます。なのでかっこがなくてもビルドエラーになりません。

ついでにもう1つサンプルコード
<Code.06>

public class HelloWorld {
    public static void main(String[] args) {
        // かけ算と割り算
        System.out.println("2 * 2 = " + 2 * 2 / 2);
    }
}

この場合はどうのような処理結果が出るでしょうか?それは実行して見てからのお楽しみ。

変数を使う

プログラミングを行なっていると「変数」と言う言葉が出てきます。
プログラミングは、中学校くらいに習った(習う)数学と似たところがあります。

演算子 意味 サンプルコード
+ 足し算、文字列の連結 1 + 1, "文字" + "1"
- 引き算 1 - 1
* かけ算 1 * 1
/ わり算 1 / 1
% 剰余算 1 % 1
剰余算について

<Code.07>

public class HelloWorld {
    public static void main(String[] args) {
        System.out.println("Hello World");
        System.out.println("3 % 2 = " + 3 % 2);
    }
}

上のように割った後の余りを算出します。「3 / 2 = 1 あまり1」と言うふうになります。なので「3 % 2」の計算結果は「1」になります。

実際に使用するときは「変数Xが偶数か奇数か?」と調べるときに、下のような形で使用します。

<Code.08>

public class HelloWorld {
    public static void main(String[] args) {
        int X = 32;
        boolean isKisu =  X % 2 == 1;
    }
}

このときに変数Xを2で割った時の余りが1になる数は「奇数」です。逆に「0」になるものは偶数です。

このような「法則のようなもの?」を見つけてそれをプログラムに落とし込むと言うところもプログラミングの面白いところです。

変数を学ぶ

プリミティブ型の変数としては以下のようなものがあります。

[プリミティブ型]と呼ばれるデータ型の種類

データ型          読み      用途
byte            バイト        8ビットの整数(-127から127) を示すが実際はファイル入出力時にこのデータ型で扱うことが多い
int               イント        整数として使用する(四則計算など)、整数の計算で使用する事が多い
long              ロング      intよりも大きい数値を使用する時に使用する、日付計算などで使用する事が多い。
double          ダブル        小数点をつける数値として使用する
float            フロート    あまり使わない
char           キャラ          一文字を示す、またintでも扱うことができる 'a'(シングルクォーテーション使用)
boolean        ブーリアン 真(true)か偽(false)を示す、intではtrue=1, false=0

これは全てではないですが、大まかに変数の一覧になっています。

そして、よく使用するのが、以下の4つです。

  1. int型: 整数用の変数
  2. double型: 少数用の変数
  3. boolean型: 真偽値
  4. String型:文字列として使用する

今までにも使用しているコードですが、改めて眺めて見ましょう

<Code.09>

public class HelloWorld {
    public static void main(String[] args) {
        // 変数の宣言
        int seisu;
        // 変数の初期化
        double shosu = 0.0;
        // 変数の初期化
        String moji = "文字列";
    }
}

変数の宣言は値を代入しません。

int seisu;

、そして、初期化は値を代入します

int double shosu = 0.0;

上記ひと通りの内容を説明した動画が、以下になります。

四則計算の実装

次は、四則計算をプログラムで行います。上記の計算でも行いましたが、今回は変数を使用して実行します。

九九(2の段)を算出、表示する

サンプルコードは以下になります。

ポイント5

<Code.10>

public static void main(String[] args) {
    int a = 2;
    int x = 1;
    System.out.println("2 x 1 = " + a * x);
    x++;
    System.out.println("2 x 2 = " + a * x);
    x++;
    System.out.println("2 x 3 = " + a * x);
    x++;
    System.out.println("2 x 4 = " + a * x);
    x++;
    System.out.println("2 x 5 = " + a * x);
    x++;
    System.out.println("2 x 6 = " + a * x);
    x++;
    System.out.println("2 x 7 = " + a * x);
    x++;
    System.out.println("2 x 8 = " + a * x);
    x++;
    System.out.println("2 x 9 = " + a * x);
}

表示結果は以下になります。

ポイント

変数「a」と「x」を初期化して、掛け算した結果を表示しています。そして表示処理

System.out.println("XXXX");

)の間にある

x++;

の処理は「インクリメント」と言って変数の値に「プラス1」します。
なので、これは2の段を表示できているのです。

今回は、ここまでです。次は、変数を使用して、簡単なプログラムを作成します。