UdemyでPythonを勉強した結果を残すブログ。

40歳でプログラミング始めて転職までいけるのかを実録してみます。

DAY29 tkinterを使ってパスワード管理・パスワード作成ツールを作成する!

DAY29の講座ではパスワード管理・ジェネレーター機能付のツールを

pythontkinterを使ってグラフィカルに作成します。

 

仕上げは上の画像のような感じ。

Udemyのとはほぼ同じだけど少し機能やコーディングは変えています。

 

パスワードツールの作成の流れはこんな感じ

  • 該当するウェブサイトの入力欄
  • ログインするユーザー名・またはメールアドレスの入力欄
  • パスワードの入力欄
  • 英数字・記号をミックスさせたジェネレータツール
  • 全てを入力すると、csvに情報を追加して管理

保管したデータを検索・引き出す機能は後日でてくるので、

今回はここまでの機能を実装します。

 

tkinterGUIをレイアウト

 

まずはCanvas、Label、Entry、Buttonを使ってgridでレイアウトしていきます。

tkinterの基本的な部分で今までやっているので説明は割愛。

 

from tkinter import *
window = Tk()
window.minsize(width=300, height=300)
window.config(pady=50, padx=50)
window.title("Password Keeper")

canvas = Canvas(width=400, height=270)
pass_img = PhotoImage(file="logo.png")
bc_image = canvas.create_image(200,120, image=pass_img)
canvas.grid(row=0, column=0, columnspan=3)

website_area = Label(text="website", font=("Futura", 15, "italic"),anchor="w")
website_area.grid(row=1, column=0)

website_input = Entry(textvariable="website url", width=40)
website_input.grid(row=1, column=1, columnspan=2, sticky="w")

user_area = Label(text="user/email", font=("Futura", 15, "italic"),anchor="w")
user_area.grid(row=2, column=0)

user_input = Entry(textvariable="user", width=40)
user_input.grid(row=2, column=1, columnspan=2, sticky="w")


pass_area = Label(text="password", font=("Futura", 15, "italic"),anchor="w")
pass_area.grid(row=3, column=0)

pass_gen_btn = Button(text="generate", command=gen_pass)
pass_gen_btn.grid(row=3, column=2, sticky="w")

pass_input = Entry(width=25)
pass_input.grid(row=3, column=1, sticky="w")

add_btn = Button(text="add", command=pass_add)
add_btn.config(width=37)
add_btn.grid(row=4, column=1, columnspan=2, pady=5)

website_input.focus()
window.mainloop()

 

1つだけ説明するなら、最後のwebsite_input.focus()

これは起動した時にマウスがウェブサイトの入力部分をクリックされている状態にしています。

 

レイアウトはできたので、generateボタンをクリックした時に起動するgen_passと

addボタンをクリックした時に起動するpass_addをコーディングしていきます。

 

パスワードジェネレータの実装

強力なパスワードを作るために、

・ランダムで7~10個のアルファベット

・ランダムで3〜6個の数字

・ランダムで3〜5個の記号

を含めたパスワードを生成します。

 

ランダムで文字を抽出するのは、randomとstringを使うとシンプルなコーディングができそうだったので採用しました。

 

参考記事

qiita.com

 

 


import random
import string

 


def gen_pass():
gened_str = random.choices(string.ascii_letters, k=random.randint(7,10))
gened_num = random.choices(string.digits, k=random.randint(3,6))
gened_kigou = random.choices(string.punctuation, k=random.randint(3, 5))
gened_pass = gened_str + gened_kigou + gened_num
random.shuffle(gened_pass)
pass_input.delete(0, END)
pass_input.insert(END, "".join(gened_pass))

 

random.choicesで複数を選んでリストにしています。またkは回数を指定でき、randintでランダムな回数で取得しています。

今回はアルファベット・数字・記号それぞれで取得する回数を分けているので

それぞれに変数をつけて、最後にgened_passでリストをまとめています。

まとめたリストをshuffleすることでアルファベット・数字・記号の順番だったものをさらにランダムに配置しなおした上で入力欄にアウトプットしています。

 

また、パスワードのやり直しができるように.insertの前に一旦クリアするために

.deleteを挟んでいます。(はさまないとパスワード文字がどんどん増えていく)

 

 

情報をcsvに保存する

入力したサイト名・ユーザー名・パスワードをaddボタンを押して保存させます。

保存する前にどれかが入力がかけていたら「全部入力してください」というアラートを

出すようにします。

アラートを出すにはtkinter の messagebox をインポートします。

from tkinter import * ではインポートできないようです。。

また、csvに保存するのでcsvモジュールもインポートします。

 

import csv
from tkinter import messagebox

 


def pass_add():
website = website_input.get()
user = user_input.get()
password = pass_input.get()
if website == "" or user == "" or password =="":
messagebox.showinfo("Alert", "Fill All Input!")

else:
with open("pass_list.csv", mode="a") as data:
writer = csv.writer(data)
writer.writerow([website, user, password])
messagebox.showinfo("Alert", "Password Added!")
website_input.delete(0, END)
pass_input.delete(0, END)
user_input.delete(0, END)
website_input.focus()

 

取得したいinputの変数.get()で入力したテキストを取得できます。

if文では入力欄が空の時にmessagebox.showinfoでアラートを出します。

 

全部入力された時だけwriterowでそれぞれを1行でcsvに保存しています。

最初の保存ではcsvはありませんが自動生成されます。

 

保存し終わったら全ての入力欄をクリアして最初のウェブサイトの入力欄が

クリックされている状態に戻します。

 

 

これで今回のツール作成は終了!

 

Gitはこちら。

github.com

 

 

 

 

 

DAY 28 python tkinter を応用して仕事を効率的に行えるツールを作成する!

今回の講義はポモドーロ・テクニックという時間管理術を使った

タイマーツールを作成します。

 

ja.wikipedia.org

 

Udemyの講座では背景は変わらずに文字だけかわる仕様でしたが

こんな感じ

 



 

自分のツールでは働く時と休憩の時には背景の絵を変えるようにします。

あとはなぜかstartとresetの背景がUdemyの通りにならずグレイになっているので

そこも直しました。

 

こんな感じ

 

 

流れとしては

  • tkinterをインポートする
  • タイトル・画像・テキスト部分・ボタンを配置する
  • スタートボタンを押すとタイマーがはじまる 
  • ストップボタンを押すとタイマー・文字・画像が最初に戻る

 

こんな感じですかね。

初めて行きます

 

tkinter をインポートする

from tkinter import *

YELLOW = "#f6f3e7"
window = Tk()
window.title("Pomodoro")
window.config(bg=YELLOW,padx=30, pady=20)
canvas = Canvas(width=500, height=500)
pc_img = PhotoImage(file="pomodoro1.png")
coffee_img = PhotoImage(file="pomodoro2.png")

bg_image = canvas.create_image(250, 200, image=pc_img)
canvas.config(bg=YELLOW, highlightthickness=0)
timer_text = canvas.create_text(250,360, text="00:00",fill="#333", font=("Futura", 40, "italic"))
canvas.grid(row=1, column=0, rowspan=3, columnspan=3)

 

YELLOWは背景の色を全て合わせたいので最初に定義しています。

仕事バージョンと休憩バージョンとしてpc_imgとcoffee_imgも最初に定義しています。

 

 

タイトル・画像・テキスト部分・ボタンを配置する


title = Label(text="Timer", font=("Futura", 40, "italic"))
title.config(bg=YELLOW)
title.grid(row=0, column=1)

check_mark = Label(text="", font=("Futura", 20, "italic"))
check_mark.config(bg=YELLOW)
check_mark.grid(row=3, column=1)

start_btn = Button(text="start", width=10, highlightbackground=YELLOW, command=start_timer)
start_btn.grid(row=3, column=0,padx=10)

stop_btn = Button(text="stop", width=10, highlightbackground=YELLOW, command=stop_timer)
stop_btn.grid(row=3, column=2)
window.mainloop()

 

canvasで00:00の表示と背景まですませているので(別々でlabelにしてもいい)

あとはタイトル・スタートボタン・ストップボタンを配置。

ボタンの間に、ポモドーロタイマーのどこまでいってるかを確認するチェックマークも配置します。

休憩を挟むごとにチェックマークがでてきます。

Udemyでは出てこなかったのに、自分のmacではボタン周りの背景がグレーでbg=YELLOWにしても変わらなかったのだけれども、

highlightbackground=YELLOWにすることで解決。

Pycharmでの補助機能で偶然発見できた。

 

ここまでは基礎的なtkinterのレイアウト方法なので一回勉強したら難しくないはず。

 

 

スタートボタンを押すとタイマーがはじまる動作を作る

start_btnのcommand start_timerのファンクションを定義する。

 

タイマーをスタートする機能と、カウントダウンを始める機能は別個で作成する。

先に秒をカウントする機能。

 


def count_down(count):
minutes = math.floor(count / 60)
second = count % 60
if second < 10:
second = f"0{second}"
canvas.itemconfig(timer_text, text=f"{minutes}:{second}")
if count > 0:
global timer
timer = window.after(1000, count_down, count - 1)
else:
start_timer()
mark =""
work_sessions = math.floor(repeat/2)
for _ in range(work_sessions):
mark +=""
check_mark.config(text=mark)

 

tkinterではtime をインポートしてsleepみたいな機能はwindow.after()でできる。

1000で1秒を表して、1秒ごとにcount - 1 を繰り返す。0になったら

start_timer()をやり直す。

秒数の表示はcountに入れた秒から60で割り切れない数字を表示する。

minutesでcountに入れた秒数から60を割ることで分を表わす。

 

なので2分の場合は120秒なので、

minutes = 120 / 60 => 2

second = 120 % 60 => 割り切れるので0

 

となる。

 

10以下の場合だと表示が9,8,7と09,08,07表示にならないため、

if second < 10 以下のコーディングで1桁の場合はストリングにして表示するようにしています。

 

start_timer()

 

repeat = 0
def start_timer():
global repeat
repeat += 1
work_sec = 25 * 60
break_sec = 5 * 60
break_long_sec = 15 * 60
if start_btn["state"]:
start_btn.config(state=DISABLED)
if repeat % 8 == 0:
count_down(break_long_sec)
title.config(text="Long Break!")
canvas.itemconfig(bg_image, image=coffee_img)
elif repeat % 2 == 0:
count_down(break_sec)
title.config(text="Break...")
canvas.itemconfig(bg_image, image=coffee_img)
else:
count_down(work_sec)
title.config(text="WORK!")
canvas.itemconfig(bg_image, image=pc_img)

 

repeatでは1回count_downが終わるごとに1を追加して、今どこのタイマーなのかを記録しています。

またここでわかりやすく作業の時間、休憩時間、長休憩時間を定義しています。

秒数で表すので25分なら 25 * 60というような感じで。

 

if start_btn["state"]:

というのはスタートボタンの状態を表しています。

この書き方だとbooleanなのでTrueの状態であれば動作するようにしています。

スタートボタンを2回以上連打されないようにするために最初にstateをDISABLEDにしています。

Udemyの講座にはない追加機能です。

 

ポモドーロでは仕事と小休憩を3回はさんで4回目は長休憩をするメソッドなので

入れ子になっているif文のところでは、

repeatが偶数で小休憩を挟むけど 8回目では長休憩をできるよう % を使うことで

動作を分けています。

ここでタイトル部分と背景もチェンジするようにしています。

 

count_downではカウントが終わったらstart_timerを起動させ、

start_timerではrepeatの回数を見たらすぐにcount_downを起動させるので

ずっと続けるなら無限にループされます。

8回1セットの想定なのですが何セットもされるとチェックマークがどんどん増えて

表示は横長になっていきます。

 

 

ストップボタンでタイマーを止める


def stop_timer():
window.after_cancel(timer)
title.config(text="Timer")
canvas.itemconfig(timer_text, text="00:00")
canvas.itemconfig(bg_image, image=pc_img)
check_mark.config(text="")
start_btn.config(state=NORMAL)
global repeat
repeat = 0

 

タイマーを止めるには、defのidではなく、window.afterをとめる必要があります。

window.after_cancel(window.afterを定義している変数)で止められます。

ここでタイトルや秒数、背景画像、チェックマーク、クリックできないようにしていた

スタートボタンなど全てを初期化するようにしています。

 

記事にしていてわかるけど、記事の言葉がそのままpythonでは1行のコードに

なっているのでpythonはわかりやすいなと改めて思います。

 

 

これでポモドーロタイマーのGUIアプリは完成。

 

ソースはgithubにて。

github.com

 

 

 

 

 

DAY27 : tkinterを学んで簡単な摂氏→華氏コンバーターを作成する!

今回の講座はmileをkmにする機能をpythonで作るもの。

ブログではそのままコピーせずに摂氏を華氏に変更するツールに変えた。

ウェブで動かすみたいに数値を入れてクリックすると変わるような感じ。

 

 

今まではこういう数値を出力するとかはコンソール上でしかできなかったけど、

tkinterを使うことでグラフィカルに操作できるようになる。

この見栄えのことをGUIグラフィカルユーザーインターフェース)といい、

普段目にしているマウス、ファイルのアイコン、フォルダアイコン、アプリのアイコンとかはすべてGUI

昔は文字だけで操作していたものを見てわかりやすく表現しているもの=GUI

 

python上でそのGUIを作成・操作できるモジュールがtkinterです。

実務で使うかはわからないが…笑

 

tkinterの使い方を学ぶ

簡単なものであればセットアップはとても簡単。

 

from tkinter import *
window = Tk()
window.title(" to converter")
#coding
window.mainloop()

tkinterをインポートして、定義して最後に.mainloop()を入れる。

これだけで#codingの部分に入れる要素を追加するだけ。

.titleで題名を設定できるけど簡単なテストくらいだったらなくても起動はできる。

 

tkinter()で基礎的に使うのはLabel(),Entry(),Button()。

書く型としては、

変数=ラベル(text=”表示したい要素”, オプション的な要素)

変数を配置する

 

これをコーディングすると


my_label = Label(text="test", font=("Futura", 15, "bold"))
my_label.grid(column=2, row=0,padx=10, pady=10)

 

こんな感じになる。

font=("")部分はオプション的な要素で指定ない場合はデフォルトで表示される。

配置はpack()とgrid()があり、特に配置をこだわらなくてもいい場合は全てpack()にすればいい。

grid()を使うと要素をグリッドわけで配置ができるようになり、

主にrowとcolumnを使って配置を決める。row=0, column=0 は左上になる。

padx,padyは横方向、縦方向に余白を追加できる機能でなくてもいいけどバランスを見る場合は追加する。

 

今回は画像を見る感じ3 x 3のグリッドなので、row・columnを使ってレイアウトしていく。

 

今回使う要素は

input部分 => Entry

℃部分 => Label

is qeual to 部分 => Label

86.0 部分(可変) => Label

°F部分 => Label

変換ボタン => Button

の6つ。

 

コーディングは


my_label = Label(text="", font=("Futura", 15, "bold"))
my_label.grid(column=2, row=0,padx=10, pady=10)

to_f = Label(text="is equal to", font=("Futura", 20, "bold"))
to_f.grid(column=0, row=1,padx=10, pady=10)

input_f = Label(text="0", font=("Futura", 30, "bold"))
input_f.grid(column=1, row=1,padx=10, pady=10)

num_c = Label(text="", font=("Futura", 20, "bold"))
num_c.grid(column=2, row=1,padx=10, pady=10)

#input
input_c = Entry(width=10)
input_c.grid(row=0, column=1,padx=10, pady=10)

#button
button = Button(text=" is...", command=encode)
button.grid(column=1, row=2,padx=10, pady=10)
window.mainloop()

こんな感じ。

Entryのwidthはその名の通り長さを表す。数値が多いほど長い。

 

buttonのcommand=は、ボタンを押すと書いた機能が動くためのもの。

この場合はencode()が機能する。

 

最後にそのencode()をコーディング。

 


#button
def encode():
temp_c = int(input_c.get())
temp_f = temp_c * 1.8 + 32
input_f.config(text=temp_f)

 

Entryに書かれた数字を華氏に変換する式を書いて、

input_f (86.0 部分(可変) => Label)

を書き換えるようにしています。

configはテキストとかじゃなくて文字の大きさだったり背景色だったりと色々変更ができる。

今回はテキストだけ変えるので、input_f.configでなく、input_f["text"] = temp_f

でも動く。

 

 

ソースはこちら。

github.com

変数を指定しないdef の書き方(*args, *kwargs)

絶対覚えておいたほうがいい!変数の数が不特定な場合でも対応できるdefの作り方

 

例えば

計算機アプリを作るとして、足し算の機能を作成するとする場合

def add(n1, n2):
return n1 + n2

 

が基本的なコーディングになるが、この状態だと足し算は1回しかできない。

5+ 5+8 +10 とかになると毎回add()を起動させないといけなくなる。

 

でも、*argsを使うことで()内の変数を指定せずに計算が無限にできる。

def add(*args):
sum = 0
for n in args:
sum += n
return sum

 

addの()に*argsを入れ、中でforを回して合計を出力するという書き方にすると

add(4,5) = 9

add(54,6,3,4,5,6) = 78

とかなり柔軟に計算ができるようになる。

*argsのargsは他の言葉でもよくて、argsの文字ではなく*+変数名でこの機能が使えるということ。

 

同じように、キーワードもコーディングや入力する要素が固定しない場合は

**kwargsを使うことで効率よくコーディングができる。


def calculate(n, **kwargs):
n += kwargs["add"]
n *= kwargs["multiple"]
n -= kwargs["subtraction"]
n /= kwargs["division"]
return n

print(calculate(2, add=3, multiple=4,subtraction=0,division=1))

最初の数が2で、

この場合は n=2 += (add=3) なので 5

n=5 *= (multiple=4) なので 20

という感じになる。

 

 

 

 

 

 

DAY26 リスト・ディクショナリーを内包記述してコード数削減&名前でフォネティックコードを取得するツールを作成

今回の講義では内包記述、という言い方が合っているかどうかわからないが

英語では comprehensionという書き方を使ってコードをスッキリ・簡潔に書く練習をしつつ、アルファベットのフォネティックコードを取得するツールを作成してみる。

ここでは毎回単語かくのもあれなので内包記述としておく。

 

最初にフォネティックコードとは、電話などでLかMか聞き取りにくい文字を

わかりやすくするために

L = Lima

M = Mike と伝えやすくするように単語で伝えるようにするためのコードです。

www.worldometers.info

 

日本語でも電話とかであるやつ。

田中の田はたんぼの田、中は中国の中、とか。

 

 

内包記述(comprehension)をざっくり覚える

 

内包記述の便利なところは、通常なら数行書くコードを1行でまとめられるところ。

 

例えば、

numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

 

このリストを偶数のみでリスト作り直す場合は今までなら


numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
guusuu = []
for i in numbers:
if i % 2 == 0:
guusuu.append(i)
print(guusuu)

 

とfor の部分で3行使うところを内包記述であれば

numbers = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
guusuu = [ n for n in numbers if n % 2 == 0]
print(guusuu)

 

書き方は


guusuu = [ 要素に直接変更したい新しい要素 for リストの1つずつの要素 in リスト名 (if リストの中から要素を抽出したい場合などに使う)]

こんな感じ。

 

guusuu のリストの中に型に合わせて記述をすることでコード数がすっきりと。

リストだけでなく、辞書型リストでもできる。

 

辞書型リストはpandasでも使われるので覚えた方がいい。

 

辞書型の内包記述


names = ["太郎", "二郎", "三郎", "四郎", "吾郎", "", "慎吾"]
student_group = { name:f"group {random.randint(1, 5)}" for name in names }
print(student_group)

出力されるのはこんな感じ

{'太郎': 'group 3', '二郎': 'group 3', '三郎': 'group 3', '四郎': 'group 2', '吾郎': 'group 1', '剛': 'group 5', '慎吾': 'group 4'}

かっこが [] じゃなく {}なので注意。最初の部分が a:bの辞書型になっています・

 

 

pandasの場合は

import pandas

student_dict = {
"student" : ["A", "B", "C"],
"tensuu" : [80, 75, 30]
}
data = pandas.DataFrame(student_dict)
print(data)

student_score = {row.student:row.tensuu for (index, row) in data.iterrows()}
print(student_score)

出力は
  student  tensuu
0       A      80
1       B      75
2       C      30
{'A': 80, 'B': 75, 'C': 30}

 

こんな感じ。

辞書型の出力方法・pandasでの内包記述はいくつかあるので

 

qiita.com

 

ここなどに詳しく書かれています。

 

 

ある程度の内包記述の型を覚えてから、フォネティックコードを取得するツールを

pythonで作ってみます。

 

どういう出力をするかというと、

 

出力イメージはこんな感じ

Type a word you want. : gakpy
G for Golf
A for Alfa
K for Kilo
P for Papa
Y for Yankee

 

それでは始めます。

 

import pandas
phonetic = pandas.read_csv("phonetic_alphabet.csv")
df = {row.letter: row.code for index,row in phonetic.iterrows()}
 読み込んだcsvをpandasで出力するとこんな感じ 
 letter      code
0       A      Alfa
1       B     Bravo
2       C   Charlie

pandasをインポートして、csvを読み込みます。

早速1つ目の内包記述で、データフレームのphoneticをiterrows()で1行ずつ読み込んで、rowは 0 A Alfa のオブジェクトとなる。辞書型リストになると

{'A': 'Alfa', 'B': 'Bravo', 'C': 'Charlie',,,,

という感じに保存されます。


answer = input("Type a word you want. : ").upper()
answer_letter = [letter for letter in answer if answer.isalpha()]

 

answerで質問をして、answer_letterで2つ目の内包記述。一番基礎のやつ。

answer = gakpyの場合、["G", "A", "K", "P", "Y"]というリストに変換されます。

アルファベット以外を入れたら動作しないようにしたかったので、そういう機能ないかなとググったら.isalpha()というのがあったので追加。

 

最後に、それぞれをデータフレームと照らし合わせてフォネティックコードを取得するコードへ。

 

answer_phonetic = {print(f"{letter} for {df[letter]}") for letter in answer_letter}

これも1行だけ。

GAKPYの場合はdf[letter]を記述することでdfのcode= Golfを取得してprintでコンソールに出力しています。

 

今回の講座ではアウトプットは辞書型リストだったのですが、

内包記述の最初の部分はprintも使えるのかな?と試してみたら使えたので採用しました。笑

 

データはこちら。

 

github.com

DAY25 pandasを使ってデータを整形&日本地図都道府県名ゲームを作る

25日目ではcsvを読み込んでデータを扱う授業。

Angela YuのUdemyではアメリカの州を当てるクイズを作成しましたが、

今回は日本地図で応用してみました。

 

csvは今までは

import csv

with openとかで読み込んでましたが、今回はpandasモジュールを使います。

pandasモジュールはpythonでデータ分析などをするならかなり重要なので

勉強してたら絶対見聞きするもの。

 

csvを表にしてcsvデータの取得や入力・変更などを簡単にできるモジュール。

pandasは後々の授業で詳しくしていたので後々復習。

 

イメージはこんな感じ

 

都道府県名当てゲームイメージ

 

流れとしては

  • 都道府県名を答える入力ポップアップが出てくる
  • 答えがあっていたら、その県名の位置か近くに県名が表示される
  • 答えられると答えた数と表示される県名がどんどん増える
  • saveを入力すると、答えていない都道府県名だけをcsvにして保存する

 

こんな感じです。

今回は保存するだけでプロジェクトを再起動した時に残りの都道府県からはじまる、というような機能は持ち合わせていないです。

あくまでpandasでcsvを保存する機能を使う、というだけ。

 

 

はじめます。

 

今回もturtleモジュールを使います。turtle便利。

import pandas
import turtle
screen = turtle.Screen()
screen.title("日本地図都道府県当てゲーム")
screen.setup(883, 800)
image = "map.gif"
screen.addshape(image)
turtle.shape(image)

 

screenでサイズを設定して、

タートルの形を日本地図の形に設定。


data = pandas.read_csv("47ken.csv")
all_states = data.state.to_list()
states_num = []

pandas.read_csv("読み込みたいファイル")

で読み込むことができます。

pandasで読み込むと、

コンソール上でもこんな感じで綺麗に表示されます。

x、yは表記される位置を表しています。

 

all_states はこの表では質問と答えを照らし合わせるものにx,yは必要ないので

都道府県名のみをto_listでリスト化しています。

data.stateはdata["state"]と同じ。

states_numの空リストは、saveを押した時に答えた都道府県じゃないものを保存するためのリスト。

 

答えを求める入力ウィンドウを表示する

全部答えたら終わりというwhileを設定して、

inputで都道府県入力ウィンドウを出します。

 


while len(states_num) < 48:
answer = screen.textinput(f"{len(states_num)}/47県 正解!", "都道府県名を答えてください")

 

答えがall_statesのリストにあったら、

dataのxとyの位置に答えを入力するというコードを書きます。


if answer in all_states:
ken = turtle.Turtle()
ken.ht()
ken.penup()
state_data = data[data.state == answer]
ken.goto(int(state_data.x), int(state_data.y))
ken.write(answer)
states_num.append(answer)

state_data = data[data.state == answer]というのは

dataのテーブルの要素と答えたものの要素だけを抽出したものをstate_dataに抽出しています。pandasだからできること(なはず)

なのでpandasの表のスクショを見てもらって

答えた都道府県が北海道の場合は

0 北海道 88 305 というデータがstate_dataに保存されているということ。

その後のgotoで、state_data.x = 88 , sate_data.y = 305 の場所に

answer = 北海道 を入力するという動作になります。

ここはstate_data.stateになぜしないのかというとstate_data.stateというのは

あくまでdataというオブジェクトから抽出しているので本体はdata。

試しにwrite(state_data.state)にしてみると、こうなる。

dataはオブジェクト

余計なものがついてくる。

 

 

 

 

最後にstates_numに答えた都道府県を空リストに追加します。

 

これでほぼゲームは完成。

あとはsaveを入力した時に答えていない都道府県をcsvで保存します。

 


elif answer == "save":
remain_states = []
for state in all_states:
if state not in states_num:
remain_states.append(state)
remain_data = pandas.DataFrame(remain_states)
remain_data.to_csv("remain_states.csv", header=False, index=False)
break

screen.exitonclick()

 

ちょっとややこしい部分がfor以下の部分ですが

remain_states = []は、全ての都道府県が入っているall_statesリストから

最初に定義した答えをリストに入れていった states_num を引いたものをいれるためのリスト。

 

なのでfor以下を説明すると

all_statesから1つずつ回していって、答えのリストに入ってなかったら

remain_statesに入れていって全て終わったらremain_states.csvに保存する、ということ。

header=False, index=Falseというのはエクセルでいうところの一番上の行と左の行の数字はいらないよという指示をしています。

 

saveをしたらbreakで質問がでなくなるので、画面をクリックして終了。

 

 

全てのデータはこちら。

 

github.com

 

python DAY-24 with open... を使ってスネークゲームにハイスコア機能を実装する

DAY24ではDAY20で作ったスネークゲームにハイスコア機能をつけます。

今までであればプログラムを閉じたら全てのデータは消去されてしまい

起動すると全て初期化されてしまうのですが、

大事な部分はデータとして残しておくようにします。

 

f:id:GO-py:20220412174153p:plain

snake game high score option

全データはgitにて公開しています。

 

github.com

 

今回改修する部分はスコアなので、score_board.py部分。

  • 初期値にハイスコアの変数
  • 表示部分にハイスコアの表示
  • プログラム起動時にハイスコアのデータを読み込む
  • ゲーム時にハイスコアが更新されたら、現在のスコアがハイスコアになる
  • ゲーム終了時に更新されたハイスコアをデータに保存する

このような感じでしょうか。

 

更新したコードはこちら。

 

from turtle import Turtle

class ScoreBoard(Turtle):
def __init__(self):
super(ScoreBoard, self).__init__()
self.score = 0
self.high_score = 0
self.penup()
self.ht()
self.goto(0, 270)
self.color("white")
self.get_highscore()

def get_score(self):
self.write(f"Score: {self.score} Highscore: {self.high_score}", font=("Sans", 20, "bold"), align="center")

def get_highscore(self):
try:
with open("score.txt", mode="r") as data:
self.high_score = int(data.read())
except:
pass
self.get_score()

def game_over(self):
self.goto(0, 0)
self.write("Game Over.", font=("Sans", 20, "bold"), align="center")

def increase_score(self):
self.clear()
self.score += 1
if self.score > self.high_score:
self.high_score = self.score
with open("score.txt", mode="w") as data:
data.write(str(self.high_score))
self.get_score()

前は初期値でget_score()を起動するようにしていましたが、

今回はget_highscore()を起動するようにしています。

 

with open('<file name>', mode="w or a or r") as <name>

でファイルをあけられるコードで、modeがwだと上書き、aで追記、rで読み取り

ができます。 as の後に変数名をいれることで以降その変数でコードができます。

 

try, exceptは後々やるのですが初めてやる場合に読み込む画像がない場合

エラーになってしまうので、入れてます。

tryでwith openを試して問題なければそのコードをそのまま続けますが、

問題があればスルーしてget_score()を動かすような流れです。

 

get_score()にハイスコアのコードを追加。

 

increase_score()には

もし現在のスコアがハイスコアより大きくなった場合に

スコア=ハイスコアを表示しつつテキストにもハイスコアを保存するようにしています。

書き込みはgame_over()の時にした方がいいのかもしれません。

 

 

今回は読み込みしたものはtxtでしたが、csvももちろん読み込めます。

今後スクレイピングなどでよく使うので覚えておかないと。