下記動画を参考に作りました。
【Flutterの教科書】③ じゃんけんを作ろう。変数と関数と条件分岐。
https://youtu.be/uDoDwKNOX3E?si=V6ZrB4h_6tZCO69h
このチャプターで学べること
StatefulWidget を使うことで変数や関数を作ることができる
変数という入れ物を用意することで状態を持つことができる
変数を作るときは型と名前と初期値を決める
コンソールに表示させるために print が使える
変数が書き変わっても画面は変化しない
画面を更新するには setState((){}) を呼ぶ
処理をまとめるための関数という仕組みがある
関数は引数を受け取り、 返り値を返すものである
関数は作っただけでは実行されない。 どこかで呼び出す必要がある
条件分岐には switch文 と if文 が使える
目次に沿ってメモを残します。
■目次
00:30 VSCodeで新規プロジェクト作成
作成中の画面から、新規Projectの立ち上げ方は、shift + ctrl + p でコマンドパレットが打てる状態になるから、
ここからFlutter new Projectを選んで、新規に立ち上げる
そこに作るかを聞かれるから、任意の場所選択→好きなProject名に変更して新規に立ち上げる
02:25 StatefulWidgetを作成して初回ビルド
main.dartのvoid main のしたのコンテンツは全削除して、stlからStatelessWidgetを作成してMaterialAppを書いていきます
MyAppクラスの下にStatefulWidgetを作成。名前をMyWidgetからJankenPageと変更する。
これでJankenPageというStatefulWidgetが出来上がりました。
StatelessWidgetとすごく似ている。UIは@override下にある中に入れていくのは変わらない
まずは上記のStatelessWidgetのMaterialAppの中にhomeを追加→home: JankenPage(),
これでアプリを立ち上げると、runAppが呼び出されて→MyApp→MaterialApp→home: JankenPageが呼び出されるようになる
05:49 グー、チョキ、パーボタンを作成
まずは、グー、チョキ、パーボタンを用意。各ElevatedButtonにグーとか用意。今回はセンターに横並びにした
mainAxisAlignment: MainAxisAlignment.spaceAround,で均等に置く
09:38 print文でコンソールに出力
ElevatedButtonの中のonPressedの{}の中に、print('グー');を入れて、アプリ上のそのボタンを押してコンソールで確認できるかやってみる
コンソールで確認したいときはprintを使うのだな。
11:40 変数を用意して選んだ手を表示
次は、アプリ上でボタンを押したときに表示されるようにする
表示させたいものは、押したときに変化したものにしたい。そういう場合は変数に入れて
同クラス内の@overrideの上に変数の記述を書いていく
ちなみにこの中に変数を作ることができるのが、StatefulWidgetの強みになります
ちなみに変数名はmyHandというように、最初を小文字もう一つの意味ある文章の頭文字を大文字にするのか推奨らしい。多分変数と認識しやすくするためか
変数を用意したら、body内の固定表示のところを今書いた変数名に置き換える
ちなみに変数を書くところなどの変更はホッとリロードが効かない
アプリ上で変更するには
ElevatedButton(
onPressed: () {
print('グー');
}
のところのonPressedの最初にmyHand = 'グー';を追加することにより、グーボタンを押すとmyHandにグーをいれることができる
よって表示上もグーに変わる
なぜ再描画されないのか、Flutterは勝手に画面は変わっていないことがよくある。
これもソース上で命令しなければならない、それはsetState(() {});を置くことで、再描画してくれと指示を出すことができる
今回は各ボタン内に置く
なので、変わらないなとハマらないで、変わらないときはsetStateを指示していないんだなと思い出せばいい
20:41 関数を作って処理をまとめる
繰り返しているところというか、似たような処理は関数にまとめることができる
関数の中身について
voidは返り値の型。これは何も返さない型
その後ろに関数(関数名は自由に変えることができる)
何かこの関数に入ってきて、その関数上で処理をして、返してあげることができる、1つのまとまりという感覚
voidはなにも返さない。
なにか値を与えるときは、引数に(引数は関数名の後ろにある()に書いていくことになります)
書き方は
void selectHand(String selectHand) {//引数(String)の型と名前(selectHand)。
myHand = selectHand;
print(selectHand);
setState(() {});
}
ElevatedButton内で書かれてた同じような書き方をしていたものをコピーして、その関数上にコピペする
グーとか固定の指示をその関数名に置き換える
void selectHand(String selectHand) {
myHand = selectHand;
print(selectHand);
setState(() {});
}
同じ処理をこれで1つなる、1つの関数として作ることができる。同じ処理が複数ある場合は、1つにしよう。
関数を作ったら、各ボタンに関数を呼び出す記述に置き換える
onPressed: () {
myHand = 'グー';
print('グー');
setState(() {});
},
↓変更
onPressed: () {
selectHand('グー');
},
25:27 ランダムな数字を生成する
次はコンピューターの手を決めます。
0~9をランダムに出すことができる関数があります。そのランダムの数字に当てはめていけば、こう考えるとできそうな気がしませんか
関数を作る際、今回は引数がなくて大丈夫
ランダムで出す関数はRandom(). 右はintの乱数 nextInt(3)
nextInt(3)は0~2までのint型の乱数を(ランダムで)出す指定をしている
void generateComputerHand() {
print(Random().nextInt(3));
}
これだけだと、ただこの関数があるだけで、このままじゃ使われないので
selectHand関数の中に入れることでselectHandを使用する際に使われるようになる
この中で、print(selectHand);の処理が書いてあるので、コンソールで処理結果が確認できる
void selectHand(String selectHand) {
myHand = selectHand;
print(selectHand);
generateComputerHand();//ここ
setState(() {});
}
28:05 Switch文で数字をグー、チョキ、パーに変換する
0~2をぐー。ちょき、ぱーに変換したいこれも関数を作る必要があります
いったんvoidと書いていく。関数名は意味が通じる名前にしたいからrandomNumberTohandとかにする
これの引数がどうなるかというとintが型で、randomNumberが引数になります。(int randomNumber)この引数名も自由に決めることができます
最初に書いたvoidは、何を返却するのか?型になるので、結局文字列に変換するので、Stringの返り値の型にする
String(返り値) randomNumberTohand(関数名)(int(引数の型) randomNumber(引数名))
randomNumberで、0だったら、ぐーにしたい、1だったらちょきにしたい
switch文にrandomNumberを入れて実現する
String randomNumberTohand(int randomNumber) { //何を返却するかの型.文字列を返すのでString。引数は数字を扱うのでint型
//条件分岐 ランダムな数字がswitchに入ったら、ランダムで返す。
switch (randomNumber) {
case 0://0が来たらの意味合いになる
return 'ぐー';//0が来たら「ぐー」を返す
case 1:
return 'ちょき';
case 2:
return 'ぱー';
default: //0-2以外も出てくるので、それ以外が来たときの処理
return 'ぐー';
}
}
それでは実際にこの関数を呼んでみましょう。先程書いたgenerateComputerHandに入れていきます
まずは受け止める必要があるので、一時的にrandomNumberという変数を作ってあげて、Random().nextInt(3)を入れる
final randomNumber = Random().nextInt(3);こうゆう感じで一時変数で受けてあげる
randomNumberTohandという関数に与える。これ(randomNumber)を引数として与えると
randomNumberTohand(randomNumber)
これがぐーかちょきかぱーに変換されて返ってくると。
これを確認するのにprint文で囲って書いてみる
void generateComputerHand() {
final randomNumber = Random().nextInt(3);
print(randomNumberTohand(randomNumber));
}
これでランダムな手が出てくるようになる(コンソール上で)
32:40 コンピューターの手を画面に表示する
表示手の上に、コンピューター手を表示するようにWidget部分を編集する
コンピュターも一時的に保持する関数を作っていきます。
まずはString computerHand = 'ぐー';とmyhandを定義した上に。
generateComputerHandが走ったタイミングで、randomNumberTohandでランダムな整数が生成されるので、
computerHandもこのタイミングで書きかえて上げましょう
void generateComputerHand() {
final randomNumber = Random().nextInt(3);
computerHand = randomNumberTohand(randomNumber);//ここに
}
randomNumberTohand(randomNumber)で処理した内容をcomputerHandという変数に代入しますよという内容
print(randomNumberTohand(randomNumber));はもういらないのでここで削除(コンソール確認する必要がなくなったので
35:30 勝敗を表示する
手の一番上に表示するようにする
まずは変数を用意する 初期値の状態 String result = '引き分け';
またWidget上の上の方にコピペなどで見た目を用意する
36:20 if文で引き分けを判定する
この引き分けという文字列を、勝ちであったり、負けであったり変更するには、
この場合は戻り値はないのでvoidとする。勝敗なので関数名はjudgeとする。引数はmyhandとかresultとか既に用意されているので、なしでOK
まずはいちばん簡単なので「引き分け」の判定をやっていこうと思います。
ifという条件分岐を書いてきます
void judge(){
if (条件){//この条件には本当か嘘かの真偽が入ってきますtrueかfalse。ここがもしtrueだったらこの囲った中身を処理するよとなっています
}
}
computerHand == myHandと条件書くことで、引き分けと判定できる。
39:08 else if で勝ちを判定する
if文は複数条件を増やせるので、次はelse ifで増やしていける
次に勝つ判定にするときは、少し複雑というか複数あるので、大変
まずは1つのパータンとしてmyHand == 'ぐー' && computerHand== 'ちょき'(&&とは「かつ」という意味
else ifは増やせるので、この調子で残りの判定も書いていく
} else if (myHand == 'ぐー' && computerHand == 'ちょき') {
result = '勝ち';
} else if (myHand == 'ちょき' && computerHand == 'ぱー') {
result = '勝ち';
} else if (myHand == 'ぱー' && computerHand == 'ぐー') {
result = '勝ち';
同じような処理が増えてきて気持ち悪いというかきれいじゃなく感じてきたと思います。これをもう少しスッキリ書く書き方があります
下記の様にelse if は同じ意味の同じ結果を出すなら「||(または)」でつなげることができる
} else if (myHand == 'ぐー' && computerHand == 'ちょき' ||
myHand == 'ちょき' && computerHand == 'ぱー' ||
myHand == 'ぱー' && computerHand == 'ぐー') {
result = '勝ち';
}
43:43 else で負けを判定する
最後に負けの書き方。elseを使う。これは条件いらない。
引き分けでも勝ちでもなければ負けだろうということで、上記のどちらでもtrueでない場合(どちらもfalseの場合)実行されるコードを書きたい場合、
単に
}else{
result = '負け';
}
と書けばいい。上記で条件が揃っているので条件いらない。
現状ではjudge関数はどこにも呼ばれていないので、どこかで呼び出さなければならない
呼ぶ箇所は、selectHand関数内の自分の手と、コンピューターの手を出す処理の次に出すのが良さそう
void selectHand(String selectHand) {
myHand = selectHand;
generateComputerHand();
judge();//ここ
setState(() {});
}
これで出来上がり