ヒットとブローの仕組みをつくって数当てゲームを完成させるよ!

ヒットとブローの仕組みをつくって数当てゲームを完成させるよ!

ゲームを完成させよう!

ここまでで、ランダムな数字をつくるのとユーザーに数字を入力してもらうのができたよね。あとはヒットとブローを判定すればゲームの完成だ!早速つくっていくよー。

ヒットの判定をしよう!

まずはヒットの判定だ。ヒットは数字も位置も同じってことだったね。これは正解の数字の1桁目と、入力した数字の1桁目を比べておなじか見るっていうのを4桁目までやればいいね。

これまでやってきたのと同じで、正解の変数をaにして入力した内容の変数をbにして作っていくよ。それとヒットの数もかぞえたいから、「hit」っていう変数も新しく作ってそこにヒット数を入れることにしよう。書き方はこんな感じだ。

hit = 0

if a[0] == int(b[0]):
    hit = hit+1
if a[1] == int(b[1]):
    hit = hit+1
if a[2] == int(b[2]):
    hit = hit+1
if a[3] == int(b[3]):
    hit = hit+1

これでもちゃんと動くんだけど、[0]から[3]までただ繰り返してるだけだよね。そんなときはforとrangeでシンプルにしよう!書き方はこんな感じ。

 
hit = 0

for i in range(4):
    if a[i] == int(b[i]):
        hit = hit+1

ブローの判定をしよう!

次はブローの判定だ。ブローは「数字は同じだけど位置が違う」ってことだったね。これを判定するには、a[0]とb[0],[1],[2],[3]を比べて、次にa[1]とb[0],[1],[2],[3]を比べて…って言うふうに総当たりで調べていけばいいんだ。

ただし、a[0]とb[1]を比べてブローだったら、残りのa[0]とb[2]、a[0]とb[3]は比べなくていい。そうじゃないと同じブローが何回も判定されちゃうからね。ブローの数は「blow」という変数をつくってそこで数えるよ。それをコードで書くとこんな感じ。

blow = 0
for i in range(4):
    if int(b[0]) == a[i]:
        blow = blow+1
        break
for i in range(4):
    if int(b[1]) == a[i]:
        blow = blow+1
        break
for i in range(4):
    if int(b[2]) == a[i]:
        blow = blow+1
        break
for i in range(4):
    if int(b[3]) == a[i]:
        blow = blow+1
        break

forを使って総当たりで全部調べてるんだね。breakを使って同じ判定を何回もしちゃうのを防いでるのも注目だ。

ヒットとブローの重複を除外する

ここまでの書き方で実は大きな問題点がある。それはヒットもブローの数に足しちゃってるってことだ。だからこれを除外していくよ。まず1桁目の条件だけを書き換えてみる。

for i in range(4):
    if (int(b[0]) == a[i]) and (a[i] != int(b[i])) and (a[0] !=int(b[0])):

こんな感じでヒットになるパターンの条件をandで繋げていけばいいんだね。これを全部の桁で書くとこんな感じだ。

blow = 0
for i in range(4):
    if (int(b[0]) == a[i]) and (a[i] != int(b[i])) and (a[0] !=int(b[0])):
        blow = blow+1
        break
for i in range(4):
    if (int(b[1]) == a[i]) and (a[i] != int(b[i])) and (a[1] !=int(b[1])):
        blow = blow+1
        break
for i in range(4):
    if (int(b[2]) == a[i]) and (a[i] != int(b[i])) and (a[2] !=int(b[2])):
        blow = blow+1
        break
for i in range(4):
    if (int(b[3]) == a[i]) and (a[i] != int(b[i])) and (a[3] !=int(b[3])):
        blow = blow+1
        break

これでブローの判定はOK!でもちょっと長すぎるから、さらにforを入れ子にしてスッキリ書いてみよう。こんな感じ。

blow = 0
for j in range(4):
    for i in range(4):
        if (int(b[j]) == a[i]) and (a[i] != int(b[i])) and (a[j] !=int(b[j])):
            blow = blow+1
            break

だいぶスッキリしたね!2つめのforの変数はjを使ってるよ。

ヒットが4になるまで繰り返そう

さて、これでゲームの仕組みのパーツは全部そろった!おさらいするとこんな感じ。

  1. ランダムな4桁の数をつくる
  2. ユーザーに入力してもらう
  3. ヒットとブローを判定する

あとはこれを繋げる。そして正解が出るまで、つまりヒットが4になるまで繰り返すって処理を追加すれば完成だ。「4ヒットまで」っていうのは「while True」を使う。これは無限に繰り返すって意味だったよね。いったん無限に繰り返す処理の中に入れて、ヒットが4になったらbreakで抜け出せばいいんだ。

全部まとめて書くとこんな感じ!

# codeing=utf-8 
import random

#4桁のランダムな数字をつくる
a = [random.randint(0,9),
     random.randint(0,9),
     random.randint(0,9),
     random.randint(0,9)]

#テスト用に正解を表示
print(str(a[0]) + str(a[1]) + str(a[2]) + str(a[3]))


while True:
    
    #ユーザーに入力してもらう
    input_ok = False
     
    while input_ok == False:
        b = input("数字を入れてね→")
        if len(b) != 4:
            print("4桁の数字を入れてね")
        else:
            input_ok = True
            for i in range(4):
                if(b[i]<"0") or (b[i]>"9"):
                    input_ok = False
                    print("数字じゃないよ")
                    break
                
    #ヒットとブローを判定する
    #ヒット
    hit = 0
     
    for i in range(4):
        if a[i] == int(b[i]):
            hit = hit+1
    #ブロー
    blow = 0
    for j in range(4):
        for i in range(4):
            if (int(b[j]) == a[i]) and (a[i] != int(b[i])) and (a[j] !=int(b[j])):
                blow = blow+1
                break
            
    #ヒット数やアタリのメッセージを表示する
    print("ヒット:" + str(hit))
    print("ブロー:" + str(blow))
    if hit == 4:
        print("アタリ!")
        break

while Trueを使ったのは14行目。

while True:

ランダムな数字を作るのは繰り返さないからこの中には入れないで、ユーザーの入力とヒット&ブローの判定を中に入れてるんだね。

それと、ヒット&ブローの数と4ヒットしたときに「アタリ!」ってメッセージを出す命令も追加した。それが46行目からだ。

#ヒット数やアタリのメッセージを表示する
    print("ヒット:" + str(hit))
    print("ブロー:" + str(blow))
    if hit == 4:
        print("アタリ!")
        break

「if hit == 4」が4ヒットって意味。あたりが出たらbreakで14行目のwhile Trueから抜け出してるんだね。

ちなみに、11行目でテスト用に正解の数字を表示するようにしてる。実際に遊ぶときはこんな風にコメントにしておこう!

#print(str(a[0]) + str(a[1]) + str(a[2]) + str(a[3]))
今日のまとめ

  • 判定は一度総当たりで調べて、例外を除く考え方でつくろう!
  • いままでのプログラムを繋げてゲームを完成させよう!