FlutterとFirebaseでオセロの対戦アプリをつくってみる　～UI作成を通してウィジェットについて学習編～

## 雑談
簡単に自己紹介します。どうも！生産技術部の筋肉系FXオセロプログラマーです。
プログラムは初心者ですが、Advent Calenderのテーマが「オセロ」という事で、今回イベントに初参加してみました。

私は中部オセロクラブに所属し、子供の頃からオセロを競技としてプレイしています。現在は、あまり大会には参加せず、大須定例会の運営を主に行っています。大須定例会には、オセロ好きが集まるのはもちろんですが、様々な分野で活躍するエンジニアが集まります。その代表として、[ScoreNow][link-scorenow]の開発者が所属しています。また、[Orca][link-orca]の開発者も在籍していました。

こんな素晴らしきエンジニア達が集う定例会は毎月第２日曜日に大須コミュニティセンターで開催されます。ぜひ遊びにきてください。詳細はこちら → [大須定例会](http://nagoyaothello.mystrikingly.com/)

[link-scorenow]:http://scorenow.mystrikingly.com/
[link-orca]:https://apps.apple.com/jp/app/%E8%A9%B0%E3%82%81%E3%82%AA%E3%82%BB%E3%83%AD-orca/id1308323178
## 本題
さて、今回は表題の通りflutterとfirebaseでオセロの対戦アプリをつくってみました。Flutter、Firebaseの学習を目的に作り始め、学習と実装期間を含めて約２週間程度でオセロの対戦ができるところまで完成しました。早速、出来上がったものがこちらです。
![画面収録.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451049/f136d447-3638-4f7a-d1d8-75ba9edfb7d7.gif)


難しい技術紹介は優秀な方達にお任せし、プログラムの初心者向けに、Flutter、Firebaseの学習手順や学習した内容を紹介したいと思います。本稿では、実装開始から3日目までに学習したFlutterウィジェットを取り上げます。

ソースコードは雑ですが、一応載せておきます。 → [othelloNet][link-othelloNet]
**注：Firebaseの構成ファイルはアップロードしていませんので、そのままでは動きません。**

[link-othelloNet]:https://gitlab.com/iyama_yuki/othellonet

## 実装の流れと学んだ事

実装のポリシーは、

* オセロが出来て、
* 2人で交互に打てる、

だけが出来る事とし、細かいことは無視して作りました。初心者の自分は早く動かないと面白くないからですｗ
完成まではこんな感じに実装を進めました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451049/55cfbdbe-90f2-4895-0de2-306bc60890e2.png)

### アプリ作成から学んだ事
* 1日目 - **Flutterの導入**  
[Flutterの公式チュートリアル](https://flutter.dev/docs/get-started/install)に従ってすすめ、便利な[Hot Reload][link-hotreload]を学びました。
* 2日目 - **Firebaseの導入**  
[Firebaseの公式チュートリアル](https://firebase.google.com/docs/flutter/setup?hl=ja)に従ってすすめ、[Google Codelabs][link-codelabs]でFirestoreの使い方を学習しました。短時間で効率的に使い方を学習出来ましたのでおススメです。
* 3日目 - **オセロ盤のUIを作成**  
UI作成を通して、ウィジェットの使い方を学習しました。 ←　[次の章](#オセロ盤をウィジェットで作ってみる)以降で紹介する内容です。
* 4日目 - **オセロ盤にタップイベントを追加**  
イベントリスナーの使い方を学習しました。
* 5日目 - **オセロのロジックを作成**  
Dart言語の書き方を学習しました。
* 6日目 - **Firestoreから棋譜読み出し**  
2日目のCodelabsから学んだ事を実際に使って理解度を深めました。
* 7日目 - **Firestoreに棋譜書き込み**  
2日目のCodelabsから学んだ事を実際に使って理解度を深めました。
* 8日目 - **ロビー追加**  
Flutterでの画面遷移の仕方を学びました。
* 9-11日目 - **バグ修正**  
デバッガの使い方、iOSシミュレータ、Androidエミュレータを使ったデバッグについて学びました。

他にも、FlutterのHot Reloadやdartdocを使ったドキュメントの作成について学びました。

[link-hotreload]:https://flutter.dev/docs/development/tools/hot-reload
[link-codelabs]:https://codelabs.developers.google.com/codelabs/flutter-firebase/#0

## オセロ盤をウィジェットで作ってみる
Flutterは、ウィジェットと呼ばれる様々なテンプレートのデザインを提供します。これらの予め用意されたテンプレートを組み合わせアプリケーションを作成します。オセロ盤は、画像で作成すれば簡単にできてしまいますが、折角なのでウィジェットのみで表現してみます。まずは、オセロ盤っぽい形をつくります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451049/0e9120ec-e318-0930-08d0-d5b8577fb8ba.png)


Row、Column、Container、Expandedウィジェットでつくりました。Flutterで実装する上で各ウィジェットの役割を知っている必要があります。

| Widget | 役割 |
| ---- | ---- |
| Row | 子ウィジェットを水平方向に並べる |
| Column | 子ウィジェットを垂直方向に並べる |
| Container | 描画や、位置・サイズの調整に用いる |
| Expanded | RowやColumnの子を引き延ばし、空間を埋める |

これらを使ったレイアウトのイメージはこんな感じになります。Rowを使ってExpandedされたContainerを水平方向に8個並べます。作成した一行の盤をColumnを使って垂直方向に8個並べて完成です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451049/d07c2e09-bfdb-2298-359c-911e287dea9e.png)

プログラムは全部書くだけでダサい感じになりましたｗ
`List.genetate`を使えばもっとすっきりまとまります。


```dart
return Container(
      margin: const EdgeInsets.all(10.0),
      color: Colors.blue,
      width: 320,
      height: 320,
      child: Column(children: <Widget>[
        // Containerは不要？？
        Expanded(child:Container(
          child:drawOneLine()
        ),),
        Expanded(child:Container(
          child:drawOneLine()
        ),),
        Expanded(child:Container(
          child:drawOneLine()
        ),),
        Expanded(child:Container(
          child:drawOneLine()
        ),),
        Expanded(child:Container(
          child:drawOneLine()
        ),),
        Expanded(child:Container(
          child:drawOneLine()
        ),),
        Expanded(child:Container(
          child:drawOneLine()
        ),),
        Expanded(child:Container(
          child:drawOneLine()
        ),),
      ]),
    );
```

```dart
Widget drawOneLine(){
  return Row(children: <Widget>[
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
        Expanded(child:Container(
          margin: EdgeInsets.all(1.0),
          color: Colors.white,
        ),),
      ]);
}
```

## オセロっぽくしてみる
色をオセロっぽく緑、黒、白に変更します。打てるマスを灰色にしてみます。円形のコマ(オセロ では、コマじゃなく石って呼びます笑)を追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/451049/bd7d6ae4-7b5e-efce-01d6-81324a30e20a.png)

コマを円形にするには、`BoxDecoration`を使って円を作ります。これで、オセロ盤のUIが完成になります。(タップした時のイベントはまだついてないですけど、、、)

```dart
Container(
            margin: EdgeInsets.all(1.0),
            decoration: BoxDecoration(
              borderRadius: BorderRadius.circular(20.0),
              color: Colors.black,
            ),
          )
```

## 最後に
Flutterの一部の基本的なウィジェットについて学びました。Flutterのイベントリスナ、画面遷移、Firestoreについては今後記事にしたいと思います。
## ご参考
* [Flutter](https://flutter.dev/)
* [Firebase](https://firebase.google.com/?hl=ja)