IT・技術研修ならCTC教育サービス

サイト内検索 企業情報 サイトマップ

研修コース検索

コラム

ゼロから歩くPythonの道

CTC 教育サービス

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  Microsoft Azure  Docker  Kubernetes 

第18回 ヒット&ブローがついに完成をむかえる(ただし中身だけ) (菱沼佑香) 2021年3月

吉政創成 アシスタントの菱沼です。

今回も「いちばんやさしいPython入門教室(大澤 文孝氏著) 」を片手に勉強していきます。

さて、前回に引き続き、今回もヒット&ブローという数字当てゲームを作っていきます。

前回は回答者が答えを入力した値が4桁であるか、数字であるかを確認するためエラーチェックを学びました。その中には正規表現が使われていたこともあり、正規表現についてもまとめました。

今回はようやく数字が当たっているかどうかを判定するところに入ります。

まずは前回のおさらい

fig01

右も左も、最終的には同じ処理を行いますが、左は一つずつ確認をしていく方法で、右は正規表現を使って一気に桁数と数字のチェックを行う方法です。

左側の処理では、まず入力された値が4桁であるかをチェックした後に問題がなければ、値が数字であるかのチェックに移るという方式が取られています。

b[i]が4つ分の値が数字であるかをチェックする部分です。変数iには0~3までの数字が入ることになります。ここでは4桁の数字を扱うことになるので、リストで管理されているインデックス番号は3が最大値ですが、5桁なら4、7桁なら6となります。(リストとインデックス番号についてはこちらの記事をご参照ください。)

一つの桁に入る数字は0~9で、それが4桁分あります。 if len(b) ! =4 の部分で「ちゃんと4桁なのかしら!?」で、そのあとに続く(b[i]<”0”)or(b[i]>”9”)は、「4桁なのね!じゃあ次なのだけれど、[i]桁目の数字には0以上9以下の数字が入っているわよね!?入ってなかったら承知しないわよ!」となり、4桁分ループして数字化を確認するということになります。

そしてここからがきっとPythonのいいところなのでしょう。

reモジュールを使えば正規表現がつかえるようになります。「\d」は正規表現で0~9の数字を意味するので、文字列が一致しているかを確認するためにre.matchを使い、正規表現の「\d」を4つつなげると、さきほどの長ったらしい説明が「入力された値は4つの数字かしら?あらそう。」という短文になります。

数字が当たっているかを判断する

さてここからがヒットとブローを判定するところです。まずはヒットから。

引用-----

P.146

ヒットは位置も数も一緒という状況を示します。これは変数aと変数bを、0から3まで4つの要素に対してそれぞれ比較していく形を取ります。そんなプログラムを普通に書くと下記のようになります。(中略)

ここではヒット数をカウントするのに「hit」という名前の変数を使いましたが、他の変数名でも、もちろんかまいません。

fig02

------

一つずつ書くのはやっぱり長いので、こちらもループに置き換えることができます。すっきり。

そしてつづけてブローの部分です。

引用-----

P.147

ブローは「位置は正しくないが、その数字が含まれている」という状況です。これを判定するには、変数bの各桁の値が変数aの各桁の値と合致するかを確かめる操作となります。

ここではコンピュータが考えた値(変数a)は「4119」、ユーザーが入力した値(変数b)が「1439」とします。

このとき、bの一番左の桁(b[0])のブロー判定は、aの各桁と比較する作業となり、次のような判定の流れを取ります。

① b[0]がa[0]と合致しているかを調べる→していない
② b[0]がa[1]と合致しているかを調べる→している→ブロー
③ すでに②でブローと分かっているから判定不要
④ すでに②でブローと分かっているから判定不要

ということになり、一番左の桁は「ブローしている」ということになります。

実際のこの判定をプログラムで記述すると、b[0]に対して、a[0]、a[1]、a[2]、a[3]を比較すればよく、次のように書くことができます。

fig03

ブローだとわかったときにbreakして、そこで判定をやめているのは、ブローを重複して数えないためです。breakしないと、③でもう一度合致してしまうので、ブローの数が2になってしまいます。

------

上で書かれているものは一桁目のチェックのみです。4桁分をチェックするには同じ文章を4つ書くことになりますが、それもまたループ処理が可能です。

が、その前に、「ブロー」であり、「ヒット」でもあるという数字が出てくることもあるので、その場合には除外するように記述を変えてあげなくてはいけないようです。

引用-----

P.149

図(略。aには「4119」が入っています。)のように、ユーザーが入力した値が「9439」であるとします。このとき、b[0]の9はa[3]の「9」に合致するのでブローと思いきや、a[3]はb[3]に合致しており「ヒット」です。このままだと、ヒットとブローで重複して数えてしまうので除外する必要があります。

そこで、これを除外するよう、ブロー判定のifの条件を次のように変更します。

fig04

------

この処理を実際には4桁分繰り返します。が、これもまたループで簡潔にすることができます。

それがこちら…。

fig05

ちょっと頭がこんがらがってきたので、自分の整理のために図で書いてみました。

fig06

ひとつ目の判定では、bの一桁目とaの4つの数字を比べていくことになります。

b[0]と合致したのはa[3]だけです。合致したので、ふたつ目の条件であるa[i] != b[i]を判定します。この時点でiに入っているのは [3]です。

aとbの[3]に入っている数字は9と9なので、「==(等しい)」です。そのためこの判定結果は×になりますので、3つ目の判定条件であるa[0] != int(b[0])の判定は行いません。

結果、blowに1は加算されません。こんな具合で4桁分が確認されていく、ということになります。

最終形態。ヒット&ブローがようやく完成…。

さて、これでようやくヒット&ブローが完成します。これまでやってきたことをくっつけるのです…!

fig07

こうやって改めてみてみると、なんだか感慨深いものを感じますが…。

上の図は学んだままですが、せっかくなので前回学んだ正規表現を使用する方法に書き換えてもやってみました。書き換えた部分とその内容は赤枠の部分です。しっかり動きました。

また、上の図のままだと答えが丸見え状態なので、print(str(a[0]) + str(a[1]) + str(a[2]) + str(a[3]))の部分を削除するか、コメントアウト(行の頭に#を付けるとコメント扱いになります。)して、表示されないようにします。

該当部分を削除(非表示に)してプログラムを実行した場合の削除前後はこんな感じ。

fig08

これでヒット&ブローのプログラムの部分は終了になりました。

次の章からはゲームの見た目をつくっていくようです。

それでは今回はこちらで終了です。お付き合いいただきありがとうございました。

 


 

 [IT研修]注目キーワード   Python  UiPath(RPA)  最新技術動向  Microsoft Azure  Docker  Kubernetes