大改造！リフォームを通して学ぶ初学者向け実践的プログラミング学習方法！ 

この記事は [**セゾン情報システムズ Advent Calendar 2020**](https://qiita.com/advent-calendar/2020/sisco) 22日目の記事です。

[はじめに](#はじめに)
[注意点](#注意点)
[やろうとしたこと](#やろうとしたこと)
[やったこと及びやってる時に考えたこと](#やったこと及びやってる時に考えたこと)
[上記のことを通じて思った学習方法](#上記のことを通じて思った学習方法)
[おわりに](#おわりに)

# はじめに
- とりあえず一つの言語の入門書は終えてfor文とかif文のような基本的文法はわかったけどその次に何をすればいいのかわからない
- プログラミングの学習には実践がいいと聞いたから何か作りたいけど、何から手をつけていいのかわからない（そもそも作りたいものが浮かばない）
- とりあえずサンプルプログラムを写経したけど何も身に付いた気がしない

上記のような壁にぶち当たることはプログラミング初学者あるあるだと思っています。
自分自身も大学の時に初めてプログラミングに触れてC言語やJavaの文法書を終えた後何をすればいいかわからずに途方に暮れていた時期がありました。
開発できる人に憧れるものの文法を終えた直後にいきなり開発をしだすのはハードルがとても高く感じてしまい、その間のギャップを埋めるものが何なのかわからない状態です。
自分自身上記の疑問には未だにはっきりとした答えは見つけられていません。
ただ、この記事を書くのをきっかけに現在興味はあるものの~~後回しにし続けてた~~なかなか学ぶ機会がなかったRustを用いてアウトプットをした経験を通じて、上記の疑問のヒントをわずかに見つけられたような気がしたので、こちらの記事で共有させて頂こうと思っております。
プログラミング初学者の学びの助けに少しでもなれたら幸いです。

# 注意点
- この記事は自分がRustの学習時にどういうステップで何をやったかの共有のみなので具体的なコードやコードの解説はのせません、あくまでメインはそれを通じて自分が思ったことの共有です。（コードの内容に興味がある方はGithubのリポジトリの方を参照してください）
- 上記の通りメインは思ったことの共有なので、ここに書いてあるステップをそのまま実践するといいよという趣旨の記事ではありません。
- 下記のやったことは実際にうまくいったことだけを書いてるのでスムーズに進んでいるように見えますが実際は色々迷走したり試行錯誤結構していたりしました（その様子も書こうかと思いましたが、文章が冗長になりそうなのでやめました）

# やろうとしたこと
- [こちらのリポジトリ](https://github.com/brightcat1/BlackJack)のコードをRustを使って移植（自分が過去に書いたJavaコード）
- コンテナ化もできたらやりたい（Docker勉強中のため）
- 元のコードはコンソールアプリケーションだが、できればこれをWebアプリ化したい
- 本家ブラックジャックとかなりルールが違うので（余裕があれば）少しでも近づけたい

# やったこと及びやってる時に考えたこと
- RustのWebフレームワークを調べたらRocketというのとactix-webというのが有名らしい
- どちらを使おうか悩む→最終的には前々から持っていたが積んでいた[こちら](https://www.amazon.co.jp/dp/4798061700/)の本を参考にしようと思いこちらの本のサンプルプログラムで使われているactix-webを使おうとなる
- 上記の本にTODOアプリのサンプルコードがあったがいきなりそれを写経せずにとりあえずステップ通りHello Worldからはじめて少しずつ本の誘導通りに進んでいく
- 最終的には本のTODOアプリのコードを写経して下記のようなTODOアプリができ上がりました（ここまでは写経なのでできあがったものは本に書いてあるのと同じです）
<img width="300" alt="14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/cc235dee-828f-96d2-d187-c66af4b6c1a7.png">

ここからこのアプリをブラックジャックっぽくしていきます。
いきなりコードを書こうとするとわけがわからなくなりそうなので要件をまとめます。
要件を考えるハードルを下げるために、まずは元のJavaコードのルールをベースにしたゲームを作ろうと思います。

- トランプのカードは4つの絵柄それぞれ13枚ずつ→元のコードでは二次元配列で管理していたがWebアプリにする場合データベース使う必要がありそう
- ディーラーからカードを引けるだけ引く（元のアプリでは引くか引かないかを乱数で決めていたが~~実装がめんどくさいので~~合計が17以上になったら引くのをやめるに変更）→元のコードがwhile文を使っているのでそのまま使えそう
- その時点でディーラーが21超えたら向こうの負け
- ディーラーの手が確定したら自分のターン、任意の枚数引いて数字の大きさを勝負
- 自分のターンで２１を超えたら自分の負け
- 点数はトランプの数字分をそのまま加算
- ゲーム終了後にリスタート可能
- 引いたカードはその都度何を引いたか画面に表示

結果できたのが下記のアプリになります。

スタート画面 <img width="200" alt="1.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/82b76706-9459-5781-5dd7-eb31ff24e00f.png">

引く画面 <img width="200" alt="3.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/b186fa1b-35cd-0762-55f7-98abbe86cfd9.png">

勝敗画面 <img width="200" alt="2.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/e91f26ec-56b8-999b-431c-6c850036a226.png">

現在の点数 <img width="200" alt="5.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/53f0e45d-5ed0-1e1e-8a98-27bb99f892cb.png">

ディーラーが先の関係でスタートおした時点でこちらが何もしなくてもディーラー側が勝手に負ける時があるので、向こうが21を超えなくなるまでRESTARTをおし続ければ一応遊べますね。~~めんどくさい~~
この時点で大分試行錯誤したのでやめようかと思いましたが時間にまだ余裕があったのでもう少しブラックジャックに近づけるために次の要件にしたがって改良します。

- ディーラーが最初に二枚手札を引いて一枚公開した状態で自分のターンに回る
- 自分が任意の枚数カードを引いてSTAY（勝負に出る）をおしたら再度ディーラーのターンに回ってディーラーは17以上になるまで引き続ける
- JとQとKを引いた場合10ポイント加算とする
- drawをHIT、standをSTAYに変更

その結果できたのが下記になります
ディーラー手札一枚公開 <img width="200" alt="10.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/2f041206-5561-313d-9671-adc09a380580.png">

大分遊べるようになってきましたがゲーム内通貨を賭けれるようになったらよりゲームっぽくなるなと思ったので追加します。

要件としては

- 最初にプレイヤーには1000$（単位も数も適当）与えられる
- ゲーム前に賭け額を決めてからスタートしなければいけない
- 勝ったら賭け額分増え、負けたら減る
- ゲーム終了後も所持金額をキープした状態で再度ゲームができる（データ
ベース使いそう）
- 金額入力欄に不正値が入力されたら弾く（負の数、数以外、所持金超える額等）
- 所持金が0になったらゲームオーバー、ゲームをリスタートしたら再度金額1000からスタート

以上の要件を満たすように実装したところ下記のようなアプリができました。
賭け金設定画面 <img width="200" alt="18.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/6af7f132-a4f6-8b45-2fda-4a446618e66d.png">

勝利すると増える <img width="200" alt="11.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/ed84eb90-de91-172d-c3d6-7281f6319e73.png">

ゲームオーバー画面 <img width="200" alt="12.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/364187/ba7516cb-2587-53d8-d72b-78e4b540f8ce.png">

かなり遊べるようになりました！
Aは１か１０として扱えるがこのゲームでは１としてしか扱わない等まだまだ実際のルールと違う部分はありますが、かなりブラックジャックに近づけることができたのかなと思っています。
ここらへんで~~Advent Calendarの記事の納期が近づいてきたので~~個人的に満足したので今回の開発は一旦ここで終了です。

今回の記事をきっかけに作ったRustのブラックジャックのコードは[こちらのリポジトリ](https://github.com/brightcat1/black_jack_rust)にあげてあるのでよければ遊んでみてください。
~~データベース使ってゴリ押した実装なことがコードを読むとわかります~~
Rustの環境がなくてもDocker環境があれば実行できます。
具体的には上記のリポジトリをクローンもしくはダウンロード後

```
docker build -t <任意の名前> .
docker run -p 8080:8080 <上記と同じ名前>
```

を実行後にlocalhost:8080にアクセスすると遊べます。
(docker runコマンドは色々オプションがあり--nameをつけるとコンテナに好きな名前をつけられたり等ありますがそこらへんの話はここでは割愛します。）

今後改良できるポイントとしてはパッと浮かんだのとしては

- ハイスコア機能（稼いだゲーム内通貨の金額ベスト５表示）←実装いけそう
- Aを１か１０として扱う機能←プレイヤー側はAを引くタイミングで任意選択させればよいがディーラー側で１と１０のどっちが最適かを判断させるアルゴリズム考える必要ありそう
- ゲームのブラウザ上の見栄えをよくする~~(CSSいじるのめんどくさい)~~
- 倍プッシュやスプリット等の特別ルールの追加

あたりになるでしょうか。

# 上記のことを通じて思った学習方法
今回の経験を通じて思ったことですが〇〇を開発するぞと思っても何かモヤをつかむように何から手をつけていいかわからないと思います。〇〇を開発したいというのがハッキリしている人は

- 〇〇の要件を明確にする
- 〇〇の要件をできる限り細かくする（一つ一つの要件の実装の方向性が見えるくらいに）


上記のことが大事だと改めて今回の開発で思いました。
ただそもそも〇〇を開発するぞの〇〇が思い浮かばないよという人もいると思います。
その時に有効だと思ったのが

- まずは既存のコードを写経
- その後にそのコードを少しずつ改造していく

というやり方がよいのではないかと思いました。
（僕は過去の自分のコードを使いましたが他の人のサンプルコードでもよいと思います。）
どのコードを元に改造していくかはその人によると思いますが例えば先ほどのTODOアプリでしたら

- 入力して保存してしまったのをDELETEせずに直接書き換える機能
- 入力欄を一つ増やしてみる

例えばHello Worldをコンソール上でやった後は

- Hello WorldをWebアプリにしてみる
- コンソール上に10回Hello Worldを出力して3の倍数回目の時だけ表示を変える

等些細な改造でもいいので思いついたことをやっていくといい気がします
（案外少しコードをいじっただけで動かなくなったりすることもあるので割と勉強になったりします）

あとはサンプルコードを別の言語で実装してみるとかもよい気がします。

多少自分なりの工夫をいれた改造を既存のコードに少しずついれるだけでも写経のみと比べるとかなり身につく度合いは変わるんじゃないかなと個人的には思っております。

この記事のタイトルではリフォームという表現を使っておりますが、写経のみですとどうしても受け身よりになる勉強法が写経したものを少しずつ自己流に改造していくことで

- 受動的な学習が能動的になる
- 既存のコードを使うのがスタート地点なので何かを作りたいの「何か」を浮かべる必要がない
- 既存のコードをどう変えるかは考えないといけないが０から何を作るか考えるよりはハードルは下がりそう

のように学習のハードルを下げつつ能動的に学習できるという点がとてもよいのかなと思いました。

# 終わりに
今回のAdvent Calendarの機会をきっかけに~~積んでいた~~Rustの学習を再開するきっかけになりましたのと、言語だけではなく他にも色々学びがあったのでこのような機会をくださった会社に感謝しております。
また、[こちらの本](https://www.amazon.co.jp/dp/4798061700/)にもとても助けてもらいました。
Rustの基本的文法だけでなくWebアプリ作成やコンテナ化、GUIアプリや組み込みシステム等実践的な内容が色々書かれているのでオススメの本です。
また機会がありましたらこのように学んだことを能動的にアウトプットしていきたいなと思いました。