【擬似言語②】ジャンケン | 論理演算と数式化(基本情報技術者, 科目B, アルゴリズム)
このNoteでは、ジャンケンを題材に「複雑なif文」を作ります。>前回のNote のif文を”多層化””論理演算による複合条件”に応用し、>前回のNote のコード化を数式化に昇華させます。
テキストの基礎を生かして、プログラム的な考察/工夫を学んでいきます。基礎と実用にギャップを感じる方のために作りました。
>【FEB】擬似言語の教科書Note
ぜひ一緒に学習を進めていきましょう!
このNoteは、私がIT専門学校で授業したことを基に作成しています。IT専門学校でFEは第一目標として、カリキュラムが構築されています。何も知らずに入学しても、1年生10月にはFE合格していきますよ。実績ある教育ノウハウを詰め込んだので、少しでも信頼して頂けたら嬉しいです。
>全Noteへのリンク(FE節)
※科目Aのテーマ別/科目B/旧FE午後など沢山作りました!
if文を多層にしてみる
「自分の手・相手の手を入力したら、勝敗あいこを判定する関数」を作ります。
ジャンケンはパターンが多いですね。3×3=9通り。
1個1個、自分と相手の手を考えて勝敗を判定せねばなりません。自分がグーの時、相手がグーだったら、チョキだったら、パーだったら。自分がチョキの時…。自分がパーの時…。
〇judgeRPS(文字列型: myHand, 文字列型: oppHand)
/ 自分の手が「グー」のとき */
if (myHandが"グー"と等しい)
if (oppHandが"グー"と等しい)
「あいこ」と表示する
elseif (oppHandが"チョキ"と等しい)
「勝ち」と表示する
elseif (oppHandが"パー"と等しい)
「負け」と表示する
endif
/ 自分の手が「チョキ」のとき */
elseif (myHandが"チョキ"と等しい)
if (oppHandが"グー"と等しい)
「負け」と表示する
elseif (oppHandが"チョキ"と等しい)
「あいこ」と表示する
elseif (oppHandが"パー"と等しい)
「勝ち」と表示する
endif
/ 自分の手が「パー」のとき */
elseif (myHandが"パー"と等しい)
if (oppHandが"グー"と等しい)
「勝ち」と表示する
elseif (oppHandが"チョキ"と等しい)
「負け」と表示する
elseif (oppHandが"パー"と等しい)
「あいこ」と表示する
endif
endifif文を2層にして、自分の手・相手の手としました。あまり階層が深くなると見にくいけど。個人的には2層3層ぐらいならまぁ許容かな。
パターン数と云えば。併せて「順列P」「組合せC」も復習しても良い機会かも。今回は不要ですが、後に擬似言語でも使います。
>【擬似言語⑩】階乗のNote
>【FEA計算⑧】パターンと組合わせのNote
>【AP計算③】組合せCのNote
論理演算で複数条件をif文1層に
if文を階層にするのが嫌なら、if条件に複数条件を書きます。論理演算(and, or, not)で条件を繋げられます。
階層を浅くなるけど、条件文を長くります。今回は好みで選ぶかなぁ。どっちもどっちですよね(後で数式にするし😅)。
〇judgeRPS(文字列型: myHand, 文字列型: oppHand)
if (myHandが"グー"と等しい かつ oppHandが"グー"と等しい)
「あいこ」と表示する
elseif (myHandが"グー"と等しい かつ oppHandが"チョキ"と等しい)
「勝ち」と表示する
elseif (myHandが"グー"と等しい かつ oppHandが"パー"と等しい)
「負け」と表示する
elseif (myHandが"チョキ"と等しい かつ oppHandが"グー"と等しい)
「負け」と表示する
elseif (myHandが"チョキ"と等しい かつ oppHandが"チョキ"と等しい)
「あいこ」と表示する
elseif (myHandが"チョキ"と等しい かつ oppHandが"パー"と等しい)
「勝ち」と表示する
elseif (myHandが"パー"と等しい かつ oppHandが"グー"と等しい)
「勝ち」と表示する
elseif (myHandが"パー"と等しい かつ oppHandが"チョキ"と等しい)
「負け」と表示する
elseif (myHandが"パー"と等しい かつ oppHandが"パー"と等しい)
「あいこ」と表示する
else
「ジャンケンの手にエラーが出ました」と表示する
endif最後にelseでエラー検知も追加。if/elseifで想定条件を拾って、想定外に備えてelseでエラー(考え落とし, ミス)を拾います。「if文には必ずelseをつけると良い」でしたね。>前回のNote
else文は、前節”if文2層"では、敢えて書きませんでした。
以下は、グーの場合のelse追加版。
/ 自分の手が「グー」のとき */
if (myHandが"グー"と等しい)
if (oppHandが"グー"と等しい)
「あいこ」と表示する
elseif (oppHandが"チョキ"と等しい)
「勝ち」と表示する
elseif (oppHandが"パー"と等しい)
「負け」と表示する
else
「ジャンケンの手にエラーが出ました」と表示する
endif他にチョキとパーにもelse追加が必要。else3個で解説的にゴチャつくので、前節ではスルーしてました。
問題文が”曖昧な書き方”をする理由
※余談なので次節にスキップしてOK。
if (myHandが"グー"と等しい かつ oppHandが"グー"と等しい)「かつ」は、問題文注意書きにある「and」でも構いません(、むしろ書くべき)。
ですが、>【FEB】サンプル問題1問02のNote では「numが3と5で割り切れる」って書いてました。
問題文注意書きに掲載されてる「and」を使って、「numが3で割り切れる and 5で割り切れる」と書くべきですよね。さらに「mod」も載ってるので、「num mod 3 = 0 and num mod 5 = 0」と書くべき。でもゴチャってきました。=とandの区切りが分かりにくいかも。
「()」も載ってるので、「(num mod 3 = 0) and (num mod 5 = 0)」で少しは見やすくなるかも。私はプログラムでもSQL文でも「()」で分かり易く書いてます。
なお実際のプログラムでは「(num % 3 == 0) and (num % 5==0)」。
「mod」は「%」。
プログラムでは 「=」が「代入」を指すので、「==」に「等しいか」を意味させて、区別してるんですね。だから「等しい」で誤魔化してるんかと。
さらに文字列を「==」で判定できるかも、プログラム言語的に諸事情あり…。
「等しい」と書いてる深めの事情があるかなと推察できます。
話戻して、もう一度載せます。作問者の意図が見えます。「=」と「and」を避けてるなぁって。
if (myHandが"グー"と等しい かつ oppHandが"グー"と等しい)「and」ぐらい書いても良さそうかな、と個人的には。
if (myHandが"グー"と等しい and oppHandが"グー"と等しい)文字列をコード化(数値)に
「グー」とか「チョキ」とかで、ゴチャって見えます。偏見ですが、カッコ悪いし、なんかプログラムっぽくない。でもそんな感覚大事かも(伝われ!💦)。
>前回Note のホテル部屋にて「シングルルームに1」「スイートルームに2」って「コード」を割り当てました。同様に「グーに1」「チョキに2」「パーに3」を割りててみます。
〇judgeRPS(整数型: myHand, 整数型: oppHand)
/ グー:1, チョキ:2, パー:3 */
if (myHand = 1 かつ oppHand = 1)
「あいこ」と表示する
elseif (myHand = 1 かつ oppHand = 2)
「勝ち」と表示する
elseif (myHand = 1 かつ oppHand = 3)
「負け」と表示する
elseif (myHand = 2 かつ oppHand = 1)
「負け」と表示する
elseif (myHand = 2 かつ oppHand = 2)
「あいこ」と表示する
elseif (myHand = 2 かつ oppHand = 3)
「勝ち」と表示する
elseif (myHand = 3 かつ oppHand = 1)
「勝ち」と表示する
elseif (myHand = 3 かつ oppHand = 2)
「負け」と表示する
elseif (myHand = 3 かつ oppHand = 3)
「あいこ」と表示する
else
「ジャンケンの手にエラーが出ました」と表示する
endifif条件が短くなって、ちょっとすっきりしたかも。
コード(1, 2, 3)の意味は関数名直後にコメントで。後で自分ですら分からなくなりますからね。関数を使う人も分かりません。
「"あいこ"と表示する」が3個、各勝敗メッセージが3個ずつ重複してます。
もし勝敗メッセージを変えたい時は、全部変えねばなりませんね。「負け」を「相手の勝ち」にしたいなら3か所変更が必要。
メンテナンス性悪すぎ。次節で改良します。
判定と表示を分離
勝利もコード化すると、便利になりますよ。全てのif判定が終わった後に勝敗メッセージ。
重複した処理を一つにまとめ、メンテナンスし易くなりました。
〇judgeRPS(整数型: myHand, 整数型: oppHand)
/ グー:1, チョキ:2, パー:3 */
整数型: resultCode
if (myHand = 1 かつ oppHand = 1)
resultCode ← 1
elseif (myHand = 1 かつ oppHand = 2)
resultCode ← 2
elseif (myHand = 1 かつ oppHand = 3)
resultCode ← 3
elseif (myHand = 2 かつ oppHand = 1)
resultCode ← 3
elseif (myHand = 2 かつ oppHand = 2)
resultCode ← 1
elseif (myHand = 2 かつ oppHand = 3)
resultCode ← 2
elseif (myHand = 3 かつ oppHand = 1)
resultCode ← 2
elseif (myHand = 3 かつ oppHand = 2)
resultCode ← 3
elseif (myHand = 3 かつ oppHand = 3)
resultCode ← 1
else
resultCode ← 99
endif
/ 最後にまとめてメッセージを表示する */
if (resultCode = 1)
「あいこ」と表示する
elseif (resultCode = 2)
「勝ち」と表示する
elseif (resultCode = 3)
「負け」と表示する
elseif (resultCode = 99)
「ジャンケンの手にエラー出ました」と表示する
endifエラー時は「99」で表現。前回「エラー時には-1を返す」でしたけどね。>前回のNote
今回「エラー時に99を返す」にした理由は後節で。要は、今後「-1」を使うんです。
コードの改良 | イメージ/用途に合わせる
前節では勝敗コードを「1, 2, 3」としました。正直何となく。「1番からで良いかなぁ」と。
「負けを-1、勝ちを+1、あいこを0」に変えてみました。数値と勝敗イメージがうまく対応して分かり易いかなと。
〇judgeRPS(整数型: myHand, 整数型: oppHand)
/ グー:1, チョキ:2, パー:3 */
整数型: resultCode
if (myHand = 1 かつ oppHand = 1)
resultCode ← 0
elseif (myHand = 1 かつ oppHand = 2)
resultCode ← 1
elseif (myHand = 1 かつ oppHand = 3)
resultCode ← -1
elseif (myHand = 2 かつ oppHand = 1)
resultCode ← -1
elseif (myHand = 2 かつ oppHand = 2)
resultCode ← 0
elseif (myHand = 2 かつ oppHand = 3)
resultCode ← 1
elseif (myHand = 3 かつ oppHand = 1)
resultCode ← 1
elseif (myHand = 3 かつ oppHand = 2)
resultCode ← -1
elseif (myHand = 3 かつ oppHand = 3)
resultCode ← 0
/ 1〜3以外の数字が送られてきたら、エラーの目印として 99 を入れる */
else
resultCode ← 99
endif
/ 最後にまとめてメッセージを表示する */
if (resultCode = 0)
「あいこ」と表示する
elseif (resultCode = 1)
「勝ち」と表示する
elseif (resultCode = -1)
「負け」と表示する
/ エラーの目印(99)がついていたら、エラー画面を出す */
elseif (resultCode = 99)
「ジャンケンの手にエラー出ました」と表示する
endif「負けを-1、勝ちを+1、あいこを0」は、後で「点数計算にも使えそう」。数値から勝敗あいこも想像し易いし。ジャンケンを何回もやって、合計点を競う時もそのまま足してけば良さそう。
数値化できたなら数式化も?
if/elseifが多くて嫌になりました。改善したい。
グーチョキパー(1, 2, 3)、勝ち敗けあいこ(1, -1, 0)って数値にしたから「勝敗判定も数式でできたら良いな」と。
「(相手の手 - 自分の手)mod 3 - 1」でできそう。
resultCode ← (oppHand - myHand + 4) mod 3 - 1※前節のifは「自分の手, 相手の手」の順に考えましたが、数式では逆「相手の手, 自分の手」の順になってます。(自分の手 - 相手の手)×(-1)でも良いですが複雑になるので。
下図は、手と数式の経緯。手コードから勝敗コードに数式で変換できてます。

※試験では数式は発想しなくてOKです。自分でプログラム作る時に生成AIに相談して、手計算で検算すればOK。でもAIは間違う場合も多いので、必ず手計算はして下さい。
引数のエラー検出を最初に
引数のエラー検査は関数最初にした方が効率的です。
現状。例えば、自手=4とか相手=-1とかが入力されても勝敗判定をします。幸いif文には(1, 2, 3)の条件しかないので、elseでエラー検知できます。でも、勝敗判定は無駄処理。

関数最初に引数検査をすれば、無駄処理をせず一気にエラー処理に持ち込めます。
以下は、上図を理解したなら次節へスキップOK。
文章でもまとめます。
勝敗判定:グチパの場合をif/else多数
→数式「(相手の手 - 自分の手)mod 3 - 1」に変更エラー検出:グチパ以外の入力対応
→最後にする意味ある?
引数にグチパ(1, 2, 3)以外が入力された場合。
数式化前の擬似言語では、勝敗判定で全てのif/elseifに該当せず、elseにてエラー検出されます。勝敗判定が無駄処理ですよね。
数式化後の擬似言語では、4とか10とか想定外の数値が入ってきたら計算結果はメチャクチャ。無効な手なのに勝ちとか負けとか判定がでます。
想定外/非対応の引数を受け取った時点で「入力値がオカシイから勝敗判定しないもんね!」としたい。
引数のエラー検出を関数最初に移動させます。
引数と返り値の両方でエラー検査したら良いかもですね。
引数で、取り扱いミス
→関数最初に検査。resultCode = 99を流用返り値で、計算ミス
→対応が必要か?
返り値に想定外の値がでるか。
今回の勝敗コード計算式にて算出。「~ mod 3」なので、0~2が確定。「~mod 3 - 1」なので-1~+1が確定。if/elseifで全部拾えてるので不要、といえば不要。
でも万が一に備えて設置しても良いですね。
なぜなら「~mod 3 - 1」の式をちょこちょこ変えるかもしれません。数式を変えた後に、表示メッセージの「if (resultCode = 0)」界隈も変える必要があります。
もし変更ミスしたら…に備えておきますか。
elseを追加しました(-1, 0, 1, 99 以外への対応)。
if (resultCode = -1)
「負け」と表示する
~略~~~~~~~~~~~~~~~~~~~~
elseif (resultCode = 99)
「ジャンケンの手にエラー出ました」と表示する
else
「勝敗判定にエラー出ました」と表示する
endifやはり、if文にはelse文を標準装備した方が良いかも。プログラムコードが2行長くなるだけで、無駄に実行はされないし、万が一の時の発見に繋がりますからね。
完成版 | 数式/エラー検出/返り値の実装
前々節の数式化・前節のエラー検出の前倒し を採用した擬似言語にしました。あとreturn文も追加。やっぱ関数を呼び出したら報告「返り値」は欲しいですよね。
〇整数型: judgeRPS(整数型: myHand, 整数型: oppHand)
/ グー:1, チョキ:2, パー:3 */
整数型: resultCode
/ 引数検査、OKならresultCode計算 */
if (myHand < 1 または myHand > 3)
resultCode ← 99
elseif (oppHand < 1 または oppHand > 3)
resultCode ← 99
else
resultCode ← (oppHand - myHand + 4) mod 3 - 1
endif
/ 勝敗結果の表示 */
if (resultCode = -1)
「負け」と表示する
elseif (resultCode = 0)
「あいこ」と表示する
elseif (resultCode = 1)
「勝ち」と表示する
elseif (resultCode = 99)
「ジャンケンの手にエラー出ました」と表示する
else
「勝敗判定にエラー出ました」と表示する
endif
return resultCodeこのNote最初の擬似言語より、かなりすっきりしたかなと。
どんな処理/式なのかコメントを残しておきたいですね(書きました!)。
まとめ
お疲れ様でした!
>前回のNote のif文基礎を生かして複雑なif文を扱いました。さらに前回の「コード化」も生かして、ジャンケンの「数式化」ができました。あと「判定/表示のモジュール分離」「引数や返り値のエラー検知」まで工夫しました。
一番大きいのは「ジャンケンの数式化」。プログラムでは文字列も扱えますが、数値/数学に持ち込めると便利ですね。物理学/数学/化学など、現象を数値/数学で表現する理由が少し分かったかも。
こんな感じで、基礎を生かして実例で擬似言語を作って、さらにプログラム的な考察や工夫を深めていきたくて、理解シリーズを作ってます。>【FEB】擬似言語の教科書Note
次は、合計でfor文の基礎を生かします。プログラムならでは自己更新(i←i+1)と初期値の重要さを学びます。>【擬似言語③】合計 | 自己更新式と初期値のNote
やらなくても良い課題。勝敗結果を二次元配列で判定してください。例えば”行番号が自分の手[i]、列番号が相手の手[j]、[i, j]要素に勝敗コードを入れておく”と、数式でもif文でもない判定方式になりますね。>【擬似言語②裏】結果のテーブルNote
最後に私のお薦めの演習順番。
❶学習前の”分からせ”
>【FEB】サンプル問題2のNote
❷テキスト
>【FEB】擬似言語の教科書Note
>【FEB】擬似言語の理解演習Note ←いまこの辺
↓※必要なら
うかる! 基本情報技術者 [科目B・セキュリティ編](amazon)
うかる! 基本情報技術者 [科目B・アルゴリズム編](amazon)
❸各年度の公開問題
>【FEB】令和07年科目BのNote
>【FEB】令和06年科目BのNote
>【FEB】令和05年科目BのNote
➍解法の総復習(➋や➌と併用可)
>【FEB】擬似言語の11の解法Note
➎模擬試験
>【FEB】サンプル問題1のNote(擬似言語)
>【FEB】サンプル問題1のNote(セキュリティ)
いいなと思ったら応援しよう!
学習方法・問題特集のNoteは全て無料提供を続けます▼
もしご覧になったNoteが有益だったり、私の志に共感されたりしましたら、サポート頂けますと励みになります▼
もちろんコメントでも結構です(・ω・▼)ノシ