Javaで簡単なパスワードジェネレーターを作ってみた

Java初心者なので、とりあえずJavaのアルゴリズムを作成してみました。
今回の要件としては、

```
・パスワードは数字のみ
・桁数と数はユーザーが指定できる
```

といったものになります。

# 処理の内容

```
・ユーザーから入力された値(桁数・パスワードの数)
・指定された桁数×指定されたパスワードの数分の乱数を生成する。
・指定された桁数で区切る
・もしユーザーが全角・半角の数字以外のものを入力してきたら、「入力は数字のみでお願いします」
という言葉を出力し、もう一度入力させる。
繰り返し数字を入力してこなかったら、数字を入力するまでそのアナウンスを繰り返す。
```

といった処理になります。
それではやっていきましょう!!!!!

まず、パスワードを作るために必要なユーザーからの入力を受け付ける部分を作っています。

# まず、ほしいパスワードの数を求めます

まず3行目から、

```java
        System.out.println("ほしいパスワードの数を入力してください");
        String inputQuantity = passQuantity.next();
```

とすることで、パスワードの数をまずきいてその後に変数inputQuantityにユーザーが入力した数字を文字列型として格納します。
その次のWhile文で、数字かそうではないかの確認を行ってもし数字ではなかったら、何度も何度も同じアナウンスをして数字を入力させる

```java
        while (!inputQuantity.matches("[0-9０-９]{1,}")){
            System.out.println("入力は数字のみでお願いいます");
            inputQuantity = passQuantity.next();
            if(inputQuantity.matches("[0-9０-９]{1,}")){
                break;
            }
        }
```

最初のwhileの条件式に

```java
        while (!inputQuantity.matches("[0-9０-９]{1,}")){
```

とすることで、もしinputQuentityの中身が数字ではなかった場合というのが成り立ちます。
最初に!があると思うのですが、これは否定演算子というもので、条件式の内容がもしtrueならfalseで、falseだったらtrueになるというものです。
今回の場合は、
「変数inputQuentityが正規表現にマッチしない場合」
がtrueになっています。
なぜかというと、
「変数inputQuentityが正規表現にマッチする場合」
の条件式に!(否定演算子)がついているため、上記のように
「変数inputQuentityが正規表現にマッチしない場合」
がtrueになります。そして、while文なのでtrueの条件がfalseにならない限り無限ループし続けます。

### 正規表現について

正規表現からわかるかもしれませんが、
「半角と全角の一桁以上の数字を正とする」
というものです。

```
{1,}
```

とすることで、一桁以上とすることができます。
これをつけないで

```
"[0-9０-９]"
```
としてしまうと、二桁以上入力してしまうとfalseになってしまいます。
なので、

```
"[0-9０-９]{1,}"
```

とすることで対応しています。
これをしないとwhile文の中に入って入力は数字のみでお願いしますの文字が出力されてしまいます。

そして中身に

```java
            System.out.println("入力は数字のみでお願いいます");
            inputQuantity = passQuantity.next();
```

として、入力は数字のみでお願いします。
それをしてユーザーが入力した値が数字ではないと言うことを示せます。
そして変数inputQuantityを初期化することで、再入力された値を変数inputQuentityに格納します。

そうすることでinputQuentityの値があら不思議!!
前に入力された値が手放されて新しい値が入りました!!!!!

んで、while文からどうやって抜けるんだよと思うかもしれませんが、それを今から解説しします。


以下の条件にすると、入力された値が正規表現にきちんとマッチする場合は、breakとすることでwhile文から抜けられる様になっています、

```java
            if(inputQuantity.matches("[0-9０-９]{1,}")){
                break;
            }
```

変数inputQuentityの値がきちんと正規表現に沿っていた場合はtrueになって、if文の中に入ります。
そしてbreak;の処理が動きます。

その次に

```java
        Integer digits = Integer.valueOf(inputDigits);

```
とすることでString型の変数の値をInteger型に変更します。
こうしないとpasswordメソッドのなかのfor文でループカウンターで使うことができないということが置きます。

そして最後に

```java
        System.out.println(inputQuantity + "ですね。わかりました");
```

として、入力された値をユーザーに確認させます。

# 次にほしいパスワードの桁数を指定する。

いっちょ前に区切っていますがやっていることは今まで解説したことと変わりません。

```java
        System.out.println("次に、ほしい桁数をお願いします");
        String inputDigits = passQuantity.next();
```

最初にほしい桁数の数を入力させて、それを文字列型で格納します。
それでwhile文に入って変数inputDigitsの中身が数字かどうかを確認しています。

```java
while (!inputDigits.matches("[0-9０-９]{1,}")){
            System.out.println("入力は数字のみでお願いいます");
            inputDigits = passQuantity.next();
            if(inputDigits.matches("[0-9０-９]{1,}")){
                break;
            }
        }
```

そして、もしこのwhile文の条件である変数inputDigitsが一桁以上かつ全角・半角の数字ではない場合はtrueになるようにして、

```java
while (!inputDigits.matches("[0-9０-９]{1,}")){
```

このwhileの中に入っているif文の条件である変数inputDigitsの内容が全角・半角の条件になる場合はtrueになります。

```java
            if(inputDigits.matches("[0-9０-９]{1,}")){
                break;
            }
```

そしてtrueになったら、break;があるのでこのwhile文のループから抜けられる。

そしてその後に、変数inputDigitsを文字列型から数値型に変換して、変換した値を変数digitsに格納する

これでできた2つの値を、配列に格納する。

```java
        int[] result = new int[2];
        result[0] = quantity;
        result[1] = digits;
        return result;
```

数値型の配列を宣言して、0番目に最初に出したquentityを格納して、その後に求めたdigitsを格納する。

# ユーザーからの入力を受け取るためのメソッドの全体のコード

```java
    public static int[] operater(){
        Scanner passQuantity = new Scanner(System.in);
        System.out.println("ほしいパスワードの数を入力してください");
        String inputQuantity = passQuantity.next();

        while (!inputQuantity.matches("[0-9０-９]{1,}")){
            System.out.println("入力は数字のみでお願いいます");
            inputQuantity = passQuantity.next();
            if(inputQuantity.matches("[0-9０-９]{1,}")){
                break;
            }
        }
        Integer quantity = Integer.valueOf(inputQuantity);
        System.out.println(inputQuantity + "ですね。わかりました");

        System.out.println("次に、ほしい桁数をお願いします");
        String inputDigits = passQuantity.next();
        while (!inputDigits.matches("[0-9０-９]{1,}")){
            System.out.println("入力は数字のみでお願いいます");
            inputDigits = passQuantity.next();
            if(inputDigits.matches("[0-9０-９]{1,}")){
                break;
            }
        }
        Integer digits = Integer.valueOf(inputDigits);
        System.out.println(digits + "桁ですね。わかりました");

        //ユーザーから入力された値を配列に格納して返す。
        int[] result = new int[2];
        result[0] = quantity;
        result[1] = digits;
        return result;
    }
```


#そして、これから返り値を用いてパスワードを生成していきます。

まず、これらを用いてユーザーの要望を聞いていた部分を呼び出します。
上で説明したoperaterメソッドは配列で帰ってきているので、配列としてoperaterメソッドを呼び出します。
そして、operaterメソッドを変数resultに格納します。

```java
    int[] result;
    result = operater();
```
これで、operaterメソッドで作成した値を今回のpasswordメソッドでも使うことができます。

次に、パスワードを実際に作成している処理について書いていきます。


for文をネストさせて書いていますね。
result[0]に入っているのはほしいパスワードの数です。外側のfor文でほしいパスワードの数分ループさせています。
そこで、StringBuilderを用いてパスワードの数のタイミングで改行が挟まるようになっています。
これをしないと、出力されたパスワードが横一列にずっと並んでしまいます。
例として、5桁のパスワードを3つ作るとしたら生成される数字の数は15個です。ですが、StringBuilderを用い無いで出力をさせると、

```
908715434533456
```
のように5桁ごとに区切られないで表示されてしまいます。正しく表示させるなら、

```
90871
54345
33456
```
と表示させないと非常に使いにくいですよね。

なので、StringBuilder型の変数sbを定義する必要があるわけです。
それを、一つのパスワードが生成されるタイミング(外側のループが一周するタイミングで)StringBuilderオブジェクトを生成することで区切っているわけです。

```java
        StringBuilder sb;

        for (int i = 0; i < result[0]; i++){
            sb = new StringBuilder();
            for (int j = 0; j < result[1]; j++){
                sb.append((int)Math.ceil(Math.random() * 9));
            }
            System.out.println(sb);
        }
```

更に、内側のresult[1]を使っているfor分で、変数sbの中に入る値を作っています。
このfor文で、sbに対して0以上９以下の乱数(小数点切り捨て)をほしい桁数分生成して、それを変数sbの中に格納しています。

# 返り値を用いてパスワードを生成するメソッドの全体のコード

```java
    public static void main(String args[]){
        password();
    }

    public static void password() {
        int[] result;
        result = operater();
        StringBuilder sb;

        for (int i = 0; i < result[0]; i++){
            sb = new StringBuilder();
            for (int j = 0; j < result[1]; j++){
                sb.append((int)Math.ceil(Math.random() * 9));
            }
            System.out.println(sb);
        }
    }

```


# 説明は以上になります
最後に、今回作成舌コード全文を載せます。

```java
import java.util.Random;
import java.util.Scanner;

class makePassword {

    public static void main(String args[]){
        password();
    }

    public static void password() {
        int[] result;
        result = operater();
        StringBuilder sb;

        for (int i = 0; i < result[0]; i++){
            sb = new StringBuilder();
            for (int j = 0; j < result[1]; j++){
                sb.append((int)Math.ceil(Math.random() * 9));
            }
            System.out.println(sb);
        }
    }

    /**
    ユーザーの入力値を受け取るメソッド。
     * ただ、while文では、数値以外の入力があった場合(a,b、顔文字など)は、もう一度ユーザーに入力させるためのコードである。

     */
    public static int[] operater(){
        Scanner passQuantity = new Scanner(System.in);
        System.out.println("ほしいパスワードの数を入力してください");
        String inputQuantity = passQuantity.next();

        while (!inputQuantity.matches("[0-9０-９]{1,}")){
            System.out.println("入力は数字のみでお願いいます");
            inputQuantity = passQuantity.next();
            if(inputQuantity.matches("[0-9０-９]{1,}")){
                break;
            }
        }
        Integer quantity = Integer.valueOf(inputQuantity);
        System.out.println(inputQuantity + "ですね。わかりました");

        System.out.println("次に、ほしい桁数をお願いします");
        String inputDigits = passQuantity.next();
        while (!inputDigits.matches("[0-9０-９]{1,}")){
            System.out.println("入力は数字のみでお願いいます");
            inputDigits = passQuantity.next();
            if(inputDigits.matches("[0-9０-９]{1,}")){
                break;
            }
        }
        Integer digits = Integer.valueOf(inputDigits);
        System.out.println(digits + "桁ですね。わかりました");

        //ユーザーから入力された値を配列に格納して返す。
        int[] result = new int[2];
        result[0] = quantity;
        result[1] = digits;
        return result;
    }
}

```

もし何か、質問・指摘灯ありましたらよろしくおねがいします。