【解説付き】Python3でHit&Blowを作ってみた

# Hit & Blow(ヒット アンド ブロー)とは？
Hit & Blowとは、数当てゲームの1種です。

プレイヤーが提出した数字と秘密の数字を比較し、次の2つの要素を確認します。
ヒット（Hit）：数字と位置が正確に一致する桁の数。
ブロー（Blow）：数字は正しいが、位置が異なる桁の数。
このhit数とblow数を参考に、プレイヤーが秘密の数を当てます。

>例) 秘密の数字が1234で、プレイヤーが1245と言った場合、
・どちらも同じ桁に「1」と「2」があるので、2hit
・どちらの数にも「4」が含まれるので、1blow

# Pythonで書いてみる
基本設定：
・randomモジュールなどを使って、4桁の重複しない整数を設定
・HBというクラスを作成し、その中のhit関数とblow関数で、hit数とblow数をカウント。

まず、完成形がこちら

```python:Hit_and_Blow.py
import random    # ランダムモジュールをインポート


class HB:    # ヒットアンドブローのクラス
    def __init__(self, ans, num, times):
        self.ans = str(ans)
        self.num = str(num)
        self.times = times

    def hit(self):    # hit関数で、ヒット数をカウント
        hits = 0
        for i in range(0, 4):
            if self.ans[i] == self.num[i]:
                hits += 1
        print(str(hits) + "H", end="")
        if hits == 4:   # ヒット数が4になったらクリア
            return print(f"\nおめでとうございます！ あなたは{self.times}手でクリアしました！")

    def blow(self):    # blow関数でblow数をカウント
        blows = 0
        for l1 in range(0, 4):
            for l2 in range(0, 4):
                if l1 != l2:
                    if self.ans[l1] == self.num[l2]:
                        blows += 1
        return print(str(blows) + "B")


a = random.randint(1, 8)    # 0から始まることがなく、かつ、どの桁も重複しない4桁の整数を生成
ints_list = [str(a)]
one_to_ten = [i for i in range(9)]
del one_to_ten[a]
random.shuffle(one_to_ten)
for i in range(3):
    ints_list.append(str(one_to_ten[i]))
ints = "".join(ints_list)
ints = int(ints)


t = 0    # 無限ループして代入
while True:
    try:
        t += 1
        hb = HB(ints, int(input(">>>")), t)
        hb.hit()
        hb.blow()
    except:
        print("エラー：4桁の数字を正しく入力してください")
```
## もっと詳しく
①ここで、クラスHBの中にhit数とblow数をカウントする関数を入れます。
hit関数の中身は、
まず、for文でself.ansとself.numのi番目がそれぞれ一致したら変数hitsに1を足します。
そして、hitsが4になったらprintでメッセージを出力します。
blow関数の中身は、
hitではないとき```l1 != l2```に、self.ansのl1番目とself.numのl2番目が一致するとき、blowに1を足します。
```python
class HB:    # ヒットアンドブローのクラス
    def __init__(self, ans, num, times):
        self.ans = str(ans)
        self.num = str(num)
        self.times = times

    def hit(self):    # hit関数で、ヒット数をカウント
        hits = 0
        for i in range(0, 4):
            if self.ans[i] == self.num[i]:
                hits += 1
        print(str(hits) + "H", end="")
        if hits == 4:   # ヒット数が4になったらクリア
            return print(f"\nおめでとうございます！ あなたは{self.times}手でクリアしました！")

    def blow(self):    # blow関数でblow数をカウント
        blows = 0
        for l1 in range(0, 4):
            for l2 in range(0, 4):
                if l1 != l2:
                    if self.ans[l1] == self.num[l2]:
                        blows += 1
        return print(str(blows) + "B")
```


②ここで、桁が重複しない4桁の整数を生成します。
aに、1～8までも乱数を代入し、リストints_listの最初の数字に設定します。
one_to_tenリストに、1～9までの数を1つずつ入れ、重複しないようにaを削除します。
one_to_tenをシャッフルし、for文で、one_to_tenリストの最初の3つをints_listに追加します。
次に、joinを使って、ints_listをintsに代入します。
こうすることにより、変数intsに、桁が重複しない4桁の整数が代入されます。
```python
a = random.randint(1, 8)
ints_list = [str(a)]
one_to_ten = [i for i in range(9)]
del one_to_ten[a]
random.shuffle(one_to_ten)
for i in range(3):
    ints_list.append(str(one_to_ten[i]))
ints = "".join(ints_list)
ints = int(ints)
```
③最後に、クラスHBに必要な変数を代入します。
エラーが発生したらもう一度実行します。

```python
t = 0    # 無限ループして代入
while True:
    try:
        t += 1
        hb = HB(ints, int(input(">>>")), t)
        hb.hit()
        hb.blow()
    except:
        print("エラー：4桁の数字を正しく入力してください")
```

# 実行結果
pycharmで実行
```
C:\Users\****\OneDrive\ドキュメント\****\****\venv\Scripts\python.exe C:\Users\****\OneDrive\ドキュメント\****\****\_PyCharm\Code9_Hit&Blow.py 
>>>1234
2H0B
>>>5634
1H1B
>>>1437
2H1B
>>>1834
2H0B
>>>1536
2H1B
>>>1936
2H0B
>>>1035
3H0B
>>>1036
2H0B
>>>1735
4H
おめでとうございます！ あなたは9手でクリアしました！
```