pythonでNumer0n(ヌメロン)を作る part2


<はじめに>

pythonでNumer0n(ヌメロン)を作る part1の続きです。

今回作成したもの

前回はコンピューターが毎回1/720の確率で数字を当てようとしてきました。今回は0EAT 0BITEだった時に、以後その数字を使わないようにしました。実際にヌメロンで遊ぶ時も0EAT 0BITEがでるとかなり有利になると思います。

コード全体

import random
available_number = [0,1,2,3,4,5,6,7,8,9]

while True:
    my_number = input("0~9の数字を使って3桁の数字を作ってください(重複なし)")
    if my_number.isdigit() and len(set(my_number)) == 3:
        break
times = 0
enemy_number = None
while my_number != enemy_number:
    times += 1
    selected_number = random.sample(available_number,3)
    enemy_number = "".join(map(str,selected_number))
    eat = sum(my_number == enemy_number for my_number, enemy_number in zip(my_number, enemy_number))
    bite = sum(enemy_number in my_number for enemy_number in enemy_number) - eat
    if eat == 0 and bite == 0:
        available_number.remove(selected_number[0])
        available_number.remove(selected_number[1])
        available_number.remove(selected_number[2])
    print("コンピューターが予想した番号:", enemy_number)
    print(f"{times}回目: {eat}EAT {bite}BITE")
    print("----------------------------------------")

print("数字を当てました!!!褒めてください!!!")
print(f"{times}回目で当てられました。")

補足

前回のpythonでNumer0n(ヌメロン)を作る part1のコメントでいろいろアドバイスを頂き、それをもとに作ったのでここまでコードが短くなりました。以下、新たな書き方を自分なりに解釈したものを紹介しようと思います。

その1 isdigit (6行目)
・すべての文字列が数字なら真となります。
例)

number = "12a"
if number.isdigit():
    print("すべて数字です")
else:
    print("数字以外が混ざっています")
#数字以外が混ざっています

これでちゃんと数字を入力しているか確認します

その2 set (6行目)
・重複を許さずに要素を取り出します。
例)

number = "122"
print(set(number))
#{'1', '2'}
print(len(set(number)))
#2

これで数字が重複しているかどうかを確認します。
その3 random.sample(配列を取り出す場所,いくつ取り出すか)(12行目)
・重複を許さずに任意の数値を新たに作ることができます。
例)

import random
number = [1,2,3,4,5,6,7,8,9]
print(random.sample(number,3))
#[8,5,3]
print(random.sample(number,3))
#[3,5,1]

これだけでかなりコードを少なくできちゃう・・・便利

その4 join(13行目)
・文字列を連結することができます。
例)

word = ["i","z","a","k","o","z","a"]
print("".join(word))
#izakoza

その5 map(13行目)
・数値を文字列に変換できます。
例)

number = [3,1,4,1,5]
new_number = map(str,number)
print("".join(new_number))
#31415

今回はmapを使うことでjoinを使えるようにしました。

その6 zip(14行目)
・2つ以上の要素を同時に取得できる。
例)

japan = ["りんご","肉","寿司"]
english = ["apple","meat","sushi"]

for japan,english in zip(japan,english):
    print(japan,english)
#りんご apple
#肉 meat
#寿司 sushi

今回はsum(等しいものであれば足す、という条件有り)とzipを組み合わせてEATを調べるのに使用しています。

その7 sum(B in A for B in B)(15行目)
・数値同士の重なりを調べます。
例)

A = "123"
B = "234"
print(sum(B in A for B in B))
#2

その8 remove(削除したい数値)(17~19行目)
・特定の数値を削除します
例)

number = [10,20,30,40,50,60,70,80,90]
number.remove(20)
print(number)
#[10, 30, 40, 50, 60, 70, 80, 90]

今回はこれで0EAT 0BITEになった数字を以後使わないようにしました。

その9 文字列の表現(20,21,25行目)
・文字列の連結のさせ方です。
例)

time = "24時間"
print("一日は",time)
#一日は 24時間
age = 10
print(f"私の年齢は{age}歳です") 
#私の年齢は10歳です

いろいろ勉強すべきことがあります・・・

考察

こちらはpart1で作ったコンピューターが何回で数字を当てられるか示したものです。(横軸が何回目で当てたかを、縦軸は頻度を表しています)試行回数は200回です。

横軸は200刻みです。

続いてこちらはpart2で作成したものです。

横軸は10刻みです。

まだまだ弱いですがpart1と比べるとかなり強くなりました。これ確率求めるにはどうするのだろうか・・・

終わりに

・コメントなんでもお待ちしてます。もっと強くしたいです、ぐぬぬぬ
最後まで読んでいただきありがとうございました。