##開発環境
- Windows10
- discord.py 1.2.3
- Python3.7.4
#作成したHit&Blowゲームのルール
- 4桁の重複していない数字をCPUが隠し持ち、桁一致を表すHitと数値のみ一致を表すBlowの数をヒントに設定された数字を当てる
- 対戦中にゲームを始めることはできない。CPUといえど2窓行為はしないのだ
- ニックネーム機能による
なりすまし代打が可能
参考:@Smoothie1023さん
#コード
コード全文
import discord
import asyncio
import random
import re
client = discord.Client()
start = time = name = correct = 0
# 起動時に動作する処理。今回のbotには無関係
@client.event
async def on_ready():
CHANNEL_ID = # 起動確認に使っても良いチャンネルのID
channel = client.get_channel(CHANNEL_ID)
await channel.send('ハローワールド!')
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
# なるべくニックネームで呼ぶようにする処理
def callnick(message):
nick = message.author.nick
if nick is None:
return message.author.name
else:
return nick
# 今回のbotの本体
@client.event
async def on_message(message):
if message.author != client.user:
global start,name,time,correct,answer,ans,hit,blow,t
if message.content == "/hb" and start == 0: # ゲーム開始
start = time = 1
name = callnick(message)
await message.channel.send("Let's enjoy Hit & Blow!")
print(f"{name}がゲームを開始しました。")
correct = random.sample(list(range(10)),4) # 正解決め
print(f"correct")
await message.channel.send(f"{name}さん4桁の数字を入力してください。")
if re.match(r'[0-9]{4}',message.content) and name == callnick(message):
time += 1
answer = message.content[:]
ans = list(map(int, answer))
hit = blow = 0
for num in range(len(ans)):
t = "x"
try:
t = correct.index(ans[num])
except ValueError:
pass
if t != "x":
if t == num:
hit += 1
else:
blow += 1
print(f"{ans} {hit} Hit / {blow} Blow {correct}")
await message.channel.send(f"{hit} Hit / {blow} Blow")
if hit == 4: # クリア時の処理
start = 2
if start == 2:
await message.channel.send(f"{correct} : Correct! 挑戦回数:{time-1}回")
print("ゲーム終了")
start = time = name = correct = 0
if message.content == "/reset" and start > 0 and callnick(message) == name: # エラーした場合のリセット
await message.channel.send(f"ゲームをリセットします。正解:{correct}")
print("ゲームがリセットされました。")
start,time,name= 0,0,""
client.run("TOKEN")
#解説
###ニックネーム
def callnick(message):
nick = message.author.nick
if nick is None:
return message.author.name
else:
return nick
ニックネームを持たない発言者にまでmessage.author.nick
のまま返事をしてしまうと、無い物は文字列として取得できずNoneになり返答文が崩壊するため返事を行わないエラーを起こす。
そのため、ニックネームが無い発言者の場合は代わりに本名を返す処理を行った。
面倒なものは関数(def
)化する。
###正解決め
correct = random.sample(list(range(10)),4) # 正解決め
重複なしの4桁の数字にしなければゲームが成立しないため、sample
による非復元抽出でリストから取り出す。
0-9の10文字からなるリストの作成にrange
を使用。
桁数の指定4を変数にすれば、ゲーム開始時に任意の桁数にする拡張を行えそう。
###解答受付
正規表現により、4桁の数字であれば0000から9999まで解答として認識する。
同じ数字の重複を弾く処理はカット。ゲームプレイヤーの良心に委ねる。
誤記例if message.content == "[0-9]{4}":
###なりすまし代打可能
if re.match(r'[0-9]{4}',message.content) and name == callnick(message):
and条件で追加したname == callnick(message)
での判定により、ゲームを開始した者と同じニックネームの者の解答を拾う。
#その他忘備録
@client.event
async def on_ready():
CHANNEL_ID = # 起動確認に使っても良いチャンネルのID
channel = client.get_channel(CHANNEL_ID)
await channel.send('ハローワールド!')
if t != "x":
if t == num:
hit += 1
else:
blow += 1
本体であるif message.content == "/hb" and start == 0: # ゲーム開始
以下も@client.event
の外に出して処理すれば、他の機能を持たせたbotにHit&Blowの機能を追加することも可能なはず。
実証が済んだら更新する。