Javaで解いてみた！！ Paiza練習問題「長テーブルのうなぎ屋」 〜オブジェクト指向編〜

#はじめに
この記事は、プログラミング初心者が書いています。
間違っていること、もっとこうした方がいいよ！！等ございましたら、
コメントお願いします。

また、この問題はpaizaの練習問題になります。
ランクの上下には全く関係のないものですので、ご安心ください。

<img width="575" alt="スクリーンショット 2018-10-29 22.17.03.png" src="https://qiita-image-store.s3.amazonaws.com/0/296668/9426424a-59a0-5250-42b4-49d002bc2f77.png">

#非オブジェクト指向で書いたやつ
[Javaで解いてみた！！ Paiza練習問題「長テーブルのうなぎ屋」](https://qiita.com/koukun1985/items/896b5fe4f2c72cff9c02)

こちらは手続き型（あってる？）で解いています。
この記事を投稿した際に、オブジェクト指向で書いたコードがあったため、
自分なりに消化させていただきました。

問題の具体的な内容などもこちらでご確認ください。



#オブジェクト指向で考える

非オブジェクト指向で書いたコード

```Java
import java.util.*;

public class unagiya {

    public static void main(String[] args) {
        /*
         * 店の総席数、来店するグループ数をString型で取得しlineに格納
         * lineに格納したデータをsplitで分けてString配列のlineArrayに格納
         */
        Scanner scanner = new Scanner(System.in);
        String line = scanner.nextLine();
        String[] lineArray = line.split(" ");
        /*
         * lineArrayに格納したデータをキャストして各変数に格納
         * 
         * seatNum:座席の数
         * totalGuest:来店するグループの数
        */
        int seatNum = castString(lineArray[0]);
        int totalGuest = castString(lineArray[1]);

        /*
         * seats:座席数をhashMapで作成
         * Integerが席番号
         * Booleanが人の有無(trueなら座れる,)
         */
        Map<Integer,Boolean> seats = new HashMap<>();
        for(int i = 1; i <= seatNum; i++){
            seats.put(i,true);
        }
        /*
         *isSitCustomer:客が選んだ席に人がいるかいないか確認
         *いなければtrueを投げる
         *
         * choiceSeat:来た客が選ぶ基点となる席番号
         *menberNum:来た客の数
         */

        int choiceSeat = 0;
        int memberNum = 0;

        for(int i = 0; i < totalGuest; i++){
            //コンソールの入力値を受け取り、
            //memberNumとchoiceSeatに代入
            line = scanner.nextLine();
            lineArray = line.split(" ");

            memberNum = castString(lineArray[0]);
            choiceSeat = castString(lineArray[1]);

            //isSitGuestがtrueなら、客の選んだ席、人数の座席情報をfalseに書き換える
            if(isSitGuest(seats,choiceSeat,memberNum)){
                for(int j = 0,index = 1 ; j < memberNum; j++){
                    if(seats.size() < choiceSeat + j){
                        seats.put(index, false);
                        index++;
                    } else {
                        seats.put(choiceSeat + j,false);
                    }
                }
            }
        }

        //座席情報のfalseの数を調べてリザルトに代入
        int result = 0;

        for(int i = 1; i <= seats.size(); i++){
            if(seats.get(i).equals(false)){
                result++;
            }
        }
        System.out.println(result);
    }

    //String型の数値をint型にキャスト
    public static int castString(String strNum){
        int num = Integer.parseInt(strNum);
        return num;
    }

    /*
     * Map座席の情報、客が選んだ席、客の人数を受け取り、
     * 客が選んだ席から、客の人数分、falseがあるかチェック
     * 
     * 条件
     * 客の人数が席より多ければfalseを返す
     * 座席情報に一つでもfalseがあればfalseを返す
     */
    public static boolean isSitGuest(Map seats, int choiceSeat, int menberNum){
        if(menberNum > seats.size()){
            return false;    
        }

        boolean flag = true;

        for(int i = 0,index = 1; i < menberNum; i++){

            //index:座席情報の一番最初の1を指定
            //客の数が座席番号を超えたら１から数える時に使用

            if(seats.size() < choiceSeat + i){
                if(seats.get(index).equals(false)){
                    flag = false;
                    index++;
                } else {
                    index++;
                }
            } else if(seats.get(choiceSeat + i).equals(false)){
                flag = false;
            }

            }
        if(flag){
            return true;
        } else {
            return false;
        }
    }
}

```

#だ、誰が書いたんだこのコード・・・

2週間ほど経って読み返してみたのですが、まあ見難い。
Mapで座席を作って色々やってますね・・・。
（途中で読むのをやめた）

この時の自分は「まあまあいいコード書けたぜｗ」なんて調子乗ってました。

しかし、流星のように現れたshiracamusさんの一言
「せっかくなのでオブジェクト指向しましょ」

その言葉と一緒に残していったコードがこちら
（shiracamusさんからコード掲載の許可をいただいております）

#＠shiracamusさんのコード
```java
import java.util.*;

enum Seat { AVAILABLE, TAKEN };

class LongTable {
    private Seat seat[];

    LongTable(int seatNum) {
        seat = new Seat[seatNum];
        for (int i = 0; i < seatNum; i++) {
            seat[i] = Seat.AVAILABLE;
        }
    }

    boolean sit(int position, int num) {
        for (int i = position; i < position + num; i++) {
            if (seat[i % seat.length] != Seat.AVAILABLE) {
                return false;
            }
        }
        for (int i = position; i < position + num; i++) {
            seat[i % seat.length] = Seat.TAKEN;
        }
        return true;
    }
}

public class Unagiya {

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String[] input = scanner.nextLine().split(" ");
        int seatNum = Integer.parseInt(input[0]);
        int groupNum = Integer.parseInt(input[1]);

        LongTable table = new LongTable(seatNum);

        int sitCount = 0;
        for (int i = 0; i < groupNum; i++){
            input = scanner.nextLine().split(" ");
            int memberNum = Integer.parseInt(input[0]);
            int seatNumber = Integer.parseInt(input[1]);

            if (table.sit(seatNumber, memberNum)) {
                sitCount += memberNum;
            }
        }

        System.out.println(sitCount);
    }
}
```

#オブジェクト指向ってなんだっけ？？？
このコードを見た瞬間、体に電撃が流れました。

おそらく僕のコードをベースに書き直したのでしょう。

ならば僕はもっと時間を掛けて、
僕なりの「オブジェクト指向」で書いてみようと思います。

#うなぎ屋の登場オブジェクト
僕はまず登場人物から考え始めます。

以前書いたフローチャートを参考に考えてみます。
<img width="673" alt="スクリーンショット 2018-10-27 23.01.49.png" src="https://qiita-image-store.s3.amazonaws.com/0/296668/8ec95b07-7e6c-a70b-f3ef-8df5b9a204e7.png">

まずは
・長テーブル

```Java
enum Seat {AVAILABLE,UNAVAILABLE}
```
TAKENから
対象的なUNAVAILABLEに変更しました。

そしてテーブル。
テーブルはテーブルなので、メソッド(動作）はありません。そこにただ存在するだけです。

```java

class LongTable {
	Seat[] seats;
	/**
	 * テーブルを作成するコンストラクタ
	 * 初期値はAVAILABLE
	 * @param tableNum
	 */
	LongTable(Integer tableNum) {
		this.seats = new Seat[tableNum];
		for (int i = 0; i < tableNum; i++) {
			seats[i] = Seat.AVAILABLE;
		}
	}
}
```

次に江戸っ子のお客さん。今回は少し気が早いとのことです。

席に人がいなかったら（isSit）座る(sitting)
席に人がいたら（isSit）帰る

```java
class Guest {
	/**
	 * 客が選んだ席に人がいなかったらtrueを投げるメソッド
	 * @param guestNum
	 * @param choiceNum
	 * @param table
	 * @return
	 */
	public static Boolean isSit(Integer guestNum, Integer choiceNum, LongTable table) {
		Boolean seatConfirmation = true;
		for (int i = choiceNum; i < choiceNum + guestNum; i++) {
			if (table.seats[i % table.seats.length] == Seat.UNAVAILABLE) {
				seatConfirmation = false;
			}
		}
		return seatConfirmation;
	}
	/**
	 * 客が座り、その席をUNAVAILABLEにするメソッド
	 * @param guestNum
	 * @param choiceNum
	 * @param table
	 */
	public static void sitting(Integer guestNum, Integer choiceNum, LongTable table) {
		for (int i = choiceNum; i < choiceNum + guestNum; i++) {
			table.seats[i % table.seats.length] = Seat.UNAVAILABLE; 
		}
	}
}
```

では、席に座っている人の数を数えるのは・・・
多分お店のスタッフさんになりますね。

```Java
class Staff {
	/**
	 * 座っている人の数を数えるメソッド
	 * @param table
	 * @return count(SeatのUNAVAILABLEの数を数える)
	 */
	public static Integer sitCount(LongTable table) {
		Integer count = 0;
		for (int i = 0; i < table.seats.length; i++) {
			if (table.seats[i] == Seat.UNAVAILABLE) {
				count++;
			}
		}
		return count;
	}
}
```

これで登場人物は揃いました。
あとはストーリーが進んでいくのを見守るだけです。

#Mainメソッドの記述

ストーリーはmainメソッドに記述していきます。

```Java
public class Unagiya {
	public static void main(String[] args) throws Exception{
		//input：コンソールからの入力値を１行取得
		//inpuArray：１行の数値を分けて配列に格納
		Scanner scanner = new Scanner(System.in);
		String input = scanner.nextLine();
		String[] inputArray = input.split(" ");
		
		//tableNum：うなぎ屋の座席の数
		//toDayGuest：本日ゲストが全部で何グループ来るか
		Integer tableNum = toCastString(inputArray[0]);
		Integer toDayGuest = toCastString(inputArray[1]);
		
		LongTable table = new LongTable(tableNum);
		
		//guestNum：１グループの人数
		//choiceNum：ゲストが選んだ席
		Integer guestNum = 0;
		Integer choiceNum = 0;
		for (int i = 0; i < toDayGuest; i++) {
			
			input = scanner.nextLine();
			inputArray = input.split(" ");
			
			guestNum = toCastString(inputArray[0]);
			choiceNum = toCastString(inputArray[1]);
			
			if (Guest.isSit(guestNum, choiceNum, table)) {
				Guest.sitting(guestNum, choiceNum, table);
			}
		}
		Integer count = Staff.sitCount(table);
		System.out.println(count);
	}
	/**
	 * String型のアラビア数字をInteger型に変換するメソッド
	 * @param strNum
	 * @return　num
	 */
	public static Integer toCastString(String strNum) {
		Integer num = Integer.parseInt(strNum);
		return num;
	}
	
}
```

#結果
![スクリーンショット 2018-11-13 0.18.25.png](https://qiita-image-store.s3.amazonaws.com/0/296668/f68860c7-8294-ccc1-92aa-4ba09e519cae.png)

問題なく通りました。

#参考
https://www.slideshare.net/masuda220/ss-14263541
こちらのスライドは非常に参考になるのですが、
縛りが非常に厳しいため、少し緩めにやっていますｗｗ

[Paiza](https://paiza.jp/)

#意見、感想、改善点、僕の悪口、募集中です
僭越ながら２回目の記事投稿になりました。

Qiitaの暗黙の了解などおそらくガン無視して書いてます。

上記の件含め、読んでくださった方は、何か記録を残していただけるとありがたいです。
最後まで読んでくれた方、ありがとうございました。