2024/12/10
話題その1 Game_over関数が働いてない問題
先日のテストで問題になったのがGameover関数が機能してないということ。単純に最上段にXが来た場合に設定してたけど駄目だった。
そこで、新たにブロックを発生させる際のIndexに既にXがあった場合にゲームオーバーを発生させるようにしてみる・・
が!
実行する前から動かないのが分かった。返り値の型をVec<String>にしてるから、型のない?else {game_over()}は弾かれるであろう。あ~困ったな・・こういう時、関数内から関数を呼び出してとりあえず実行出来るRacketは物わかりが良かったな・・と。
予想だけど、Result型にして別の型を返すように出来たりしないかなぁ?と、Claude先生に相談
先生いわく・・
・返り値の型がVecなんだからVec::new()でカラベクター返したら?
・もしくは意図的にPanic起こさせたら?
とのこと。やっぱり直接Gameoverを呼び出すことは出来ないっぽい。
ま、まあ考えてみればMain内の次の手続きでCellsの内容をチェックしてカラだったらGameoverを呼び出すようにすれば良いのか・・なるほど!
と、突然バイト先でスマホに甥っ子から電話がかかってくる。21時過ぎに・・?内容は・・
「オトンが酔っ払ってズッコけ、玄関扉に頭から激突。ガラスが割れて頭から出血してるので救急車で病院へ行った」
との連絡が・・!ウゲー!
まあ、聞けば意識もしっかりしてるし弟嫁が一緒に行ったということで大事ではないと思われるが・・後のことを考えると気分が萎えて今日はココまで。ガラスの修理どうすっかなぁ・・
話題その2 Basic Gamesの動物当てゲームに衝撃を受ける
例のGithubに上がってるBasic GamesのRust移植版、我流のコードばっかりじゃイカンと思って適当に選んだコードを読み始めたんですけど・・
えっ!?なんだコレは・・質問に答えて、ハッシュテーブルに入ってない場合は質問と答えを新たなデータとして溜め込んで成長していくプログラムだと!?こんなのを当時のBasicで作ってたのか!ちょっとこれは研究してみないといかんサンプルやでぇ・・てっきりもっとしょーもないゲーム集だと思ってたけど全く油断出来んな!
話題その3 気になるテトリスブロック発生部分をカッコよく書き換えてもらうと?
まあ、これが気になってるわけですわ。構造体とか作らずに直接Cellsにぶち込むってコレはコレで気に入ってるんだけど、本来ならばどう書くべきなのか?Claude先生!
列挙型(よく分かってないけどw)の構造体を作って・・
うーん・・まあこうなるか~・・補助関数を1つ書いたら田和式の方がすっきり書けるかな
明日はいよいよ揃った行を判定してテトリス現象を起こす部分を書こう。それで完成のはず!
2024/12/09 RustでCLIテトリス、基本動作が完成する
Donw_blocksが完成したので例によってClaude先生に添削願い
あと、添削されたコードを見てて気になったのだけど、IterでCollectしてるのに、最後.to_vec()せずに返してるのはなぜか・・?
あ、Collectってそうなんだ!便利じゃないか!
添削は・・ふーん、まあケアレスミス程度だったな。
あとはMainのLoop部分。ElseでLoopを再帰呼び出しするのかな?と思って最後にelse{loop}としてたけど、そーゆーんじゃなくてLoop内はBreakするまで勝手にループするらしい、なるほど
おや・・気づいたら基本的な動作に必要な部分は書き終わってるような?
ということでClaude先生にまるごと添削を頼んでみる。文法部分と論理部分を分けて頼むぜ!
ふーん・・まあ、大したことはないな
うーん、気になるのはIs_outの条件式が不自然ってところか?なんかもう面倒になって来たし致命的な間違いは無さそうなので、Claude先生に「とりあえず修正したコードを出してよ」と頼んでみる。
ところがClaude先生のコードを実際にRustPlayGroundで実行してみると何か所かエラーが。For_eachでのVecの書き換えの部分に.to_string()が必要だった。なるほどね・・というか、最初からVec<char>にしておくべきだったんだよな~。
あとはブロックの種類を追加して・・実行
出たーっ!
うむ、ちゃんとmで右移動、nで左移動、回転も出来てるし最下段で移動不能になると固定化されてるな
次のターン、ブロックが結合して固定化されるはずだが・・
オッケー!
あとは
・ゲームオーバー処理がちゃんと行われるのかの確認
・1行揃った時にブロックを消す部分の実装
で完成だな!間違いなくプレイしていて面白くはないゲームであろうがw
2024/12/08 Rustでテトリスブロックの左右移動
まだRustのCLI版テトリス書いてます!いや〜こんなに長くなるとは・・
というわけでブロックの左右移動関数を書いてるんですが・・お前、何回同じ処理を書くんだと!しかも1つの関数内でだぞ!?と。これは自分で見てても笑ってしまうんだけど、自作から気をつけます!や〜ひどい
では書き上がったブロック左右移動のクソ長関数をClaude先生に渡して添削してもらうか〜。ちなみに、無理を言って敢えて構造はそのままで文法だけ直してもらってます
狙いとしては、可動ブロックのIndexを取得して、それを左右のキー入力で分けて座標をプラマイ修正、それをIs_out述語で移動可能か場合分けしようと
。あ、Orは || なのか
上でまとめてIndexを取得したくせに、また雑魚ブロックのみでIndexを取得する羽目にw
あと、Map().Mapの場合ってCollectを挟まなくて良いのか・・そらそうか
あと、Charはシングルクォートじゃないといかんのだな
ここもシングルクォート。
あとはUnwrapはエラー処理を入れろとしつこいClaude先生
可動ブロックを排除したCellsを作る・・
あ、最後にTo_vecしてない
Map内で参照するかAs_str()しないといけないのにしてない
この述語のために可動ブロック二種のIndexをまとめて取得しないといけないと思ったのだ・・バラで取得して合わせれば良いのに
引数のNew_indexを参照でもらうべし
Vec()して返すべし
場合分けはMatchじゃなくてIfなのか・・いつもはMatch推しなのに・・理由を知りたい
えっ?やっぱりMatchで書くべきなのか・・
それと僕の書き方で駄目な理由(ガードを使わないといけない理由)を知りたい
は〜ん・・ただ単に真偽値が返ってくるなら良いのかと思ったら、定数とか静的な値しか許されてないとのこと。なるほどね!
続いて間違ってるだろうけど書き方が分からないのでエイヤッ!と書いた部分。そもそもAs_char()なんてものは存在しないとのこと。
標準入力の時には1文字でもTrimを忘れぬこと
文字リテラル使用と参照渡しの意味がわからん・・
なるほど、文字リテラル=Char 文字列リテラル=&strなのか。うーん、ではコメントで参照渡しにするとあったのがよく分からん。DirectはCharで渡してるから値渡しでは?
む、やっぱりな。ところで、このCellsは参照で、DirectはCharで渡すってのは効率とか作法的にはどうなのかな?なし崩し的にこれでやってるけど・・
驚いたことにたまたま渡し方は合ってた模様
あ、なるほどそういうことか〜!じゃあ関数型言語的に使うならばずっと不変参照で良いよな?ほんで、IterとかCloneとかTo_vecとかで更新した新たなデータを作って返すと
今回のテトリスで散々やったのでようやく理解した
一応、それでも可変参照で行うべき時を聞いてみた。
なるほど、これは思った。ベクターの変更で毎回コピーとかMapで走査とかしてたら遅くなりそうだもんなぁ
よう分からんけど、そもそも破壊的変更する仕様で避けられない仕組みもあるんだろうなと
ハッシュテーブルは仕組み的にそういうもんなんだろうなと。ところで添削の中で出てくる?って何だろ?
???
は~ん・・返り値がResultかOptionの時に限り、?を使うことでMatchとErr、もしくはNoneの記述を省けると。なるほどね・・まあ、慣れないうちは教科書通りに書いておくとしよう。それよりも問題はResult型とOption型ですわ・・。ちょうど自作のコードを提出してるわけだから、それを使ってもらったら機能がわかり易いと思うのでお願いする
まず<T, E>が分からないのだが?TはTrueでEはエラーと見た。つまり、Okの時に返す型、エラーで返す型の指定をしてるわけか?
やっぱりそういう事か・・今までドキュメントも読んだし何度も見てたけど、ようやく理解できたわ~
ここで疑問。ErrとNone、これってNoneもエラーの一部だったりしないのかな?単にエラー処理をしたい場合にエラーとしてるだけ?
なんと、ErrとNoneは明確に違うという。
ではどういう時にNoneなのか?はーん・・でも、こう言う時にエラーは出ないって事?
違う概念だったのか!
パニックの方が深刻な問題なんですね。はぇ~・・知らなんだ
今日も色々と勉強になったなぁ~