え〜採点中の機械です。
バケガクの計算なんかでは、RPN電卓が非常に使いやすいのですが、
私はHP200LXのRPN計算機モードなので、携帯には便利なのですが、
大量計算するには、やっぱキーがちょっと小さい・・・
ということで、Tkinterの習作として、簡単なRPNを作ってしまいま
した。
--^ rpn_v01
# RPN Calculator ver 0.1
# グローバル変数を多用する、非常に汚いコード
# クラスにして、対処する予定
stack=[]
inputStr=""
tempValue=0
newLine=0
def push(str):
stack.append(str)
def pop():
if not stack.__len__():
return "0"
else:
return stack.pop()
from Tkinter import *
root = Tk()
root.title("RPN Calculator")
canvas = Canvas(root,width=480,height=360,bg="black")
def setText(txt,x,y):
canvas.create_text(x,y,text=txt,
fill="white",
anchor=NE,
font = "Helvetica 15 bold"
)
def alert(txt): # 不正入力に対する警告
canvas.create_text(
10,10,text=txt,
fill="RED",
anchor=NW,
font = "Helvetica 15 bold"
)
def showDisplay():
canvas.delete(ALL)
if stack.__len__() > 3:
setText(stack[-4],450,50)
else:
setText("0",450,50)
if stack.__len__() > 2:
setText(stack[-3],450,100)
else:
setText("0",450,100)
if stack.__len__() > 1:
setText(stack[-2],450,150)
else:
setText("0",450,150)
if stack.__len__() > 0:
setText(stack[-1],450,200)
else:
setText("0",450,200)
canvas.create_line(10,230,470,230,fill="white")
if inputStr=="":
setText("0",450,250)
else:
setText(inputStr,450,250)
def allClear(event): # スタック内部をクリア
global stack
global inputStr
stack = []
inputStr = ""
showDisplay()
def enterValue(event): # Enterキーによるスタック積み
global newLine
push(inputStr)
newLine = 2
showDisplay()
def calc(opr): # 演算キーの処理
global inputStr
global newLine
if not (((inputStr == "") or (inputStr == "0")) and opr =="/"):
e = "tempValue=" + pop() + opr + inputStr
exec e
inputStr = str(tempValue)
newLine = 1
showDisplay()
else:
alert("ZERO DIVIDE!")
def backSpace(event): # 入力文字の1文字消去
global inputStr
if inputStr:
inputStr = inputStr[:-1]
showDisplay()
def deleteKey(event): # 入力行の消去
global inputStr
inputStr = ""
showDisplay()
def change(event): # Zキーによる、Entry行とTOSの交換
global newLine
global inputStr
stack[-1],inputStr = inputStr,stack[-1]
newLine = 1
showDisplay()
def inputCharacter(event): # キー入力ルーチン
global newLine
global inputStr
if event.char in "0123456789xXabcdefABCDEF.":
if newLine:
if newLine == 1:
if inputStr <> "":
push(inputStr)
inputStr = ""
newLine = 0
inputStr = inputStr + event.char
showDisplay()
elif event.char in "+-*/":
calc(event.char)
else :
alert()
canvas.bind("<Escape>",allClear)
canvas.bind("<Return>",enterValue)
canvas.bind("<BackSpace>",backSpace)
canvas.bind("<Delete>",deleteKey)
canvas.bind("<z>",change)
canvas.bind("<Key>",inputCharacter)
import sys
canvas.bind("<Home>",sys.exit)
canvas.pack()
showDisplay()
canvas.focus_set()
root.mainloop()
--$
はっきり言えば、まだ「なんとか動く」段階で、挙動不審に陥る
バグも残ってますが、やっつけスクリプトなんてこんなもん
でしょう。
書き出してから気がついたのは、globalキーワードを多用すること。
これはもう、典型的な「ヤバいスクリプト」なので、採点が終わり
次第、クラスベースの全面改訂版を作ってみようと思います。
※450とかのマジックナンバーもなんとかしたいですね
あと、スクリプトらしい面白いトコといえば、計算をexec文で行
っているので、16進法だろうが8進法だろうが、省略浮動小数点表記
だろうが(.5を0.5として評価されるなんて、知らなかった・・・)
結構ファジーに計算できることです。
・・・今のところ結果は全て10進法ですが・・・
採点からの逃避で作り出した(をい)スクリプトですが、手を入れて
いじっていくと結構面白いかもしれません。
・・・んでも、採点はちっともすすまん・・・
「今夜は徹夜か?(泣)」機械伯爵