要求: 1.完成常識中的ATM存取款機功能 2.把ATM機故障考慮進去 3.不能直接輸入賬戶名和卡號等等信息,模擬出插銀行卡讓ATM機自動讀取卡信息 4.密碼驗證超過三次錯誤即鎖定賬戶 5.操作類型有:存款,取款,查詢,轉賬,列印憑條,退卡,一共六個選項,跟用戶輸入做出不同的反饋 6.當用戶正常進入 ...
要求:
1.完成常識中的ATM存取款機功能
2.把ATM機故障考慮進去
3.不能直接輸入賬戶名和卡號等等信息,模擬出插銀行卡讓ATM機自動讀取卡信息
4.密碼驗證超過三次錯誤即鎖定賬戶
5.操作類型有:存款,取款,查詢,轉賬,列印憑條,退卡,一共六個選項,跟用戶輸入做出不同的反饋
6.當用戶正常進入,列出操作類型,每次操作結束後都要重新選擇操作類型,只有退卡操作才會結束
7.操作結束後,數據要同步更新
8.要有日誌文件,每個涉及到錢走向的操作都要有日誌記錄
分析:
同樣的沒什麼可說的,根據生活中的場景來就行
關鍵的問題:怎麼模擬插卡操作,讓ATM機自動獲取信息,方法有:
1.調用API介面讀取卡信息,但基本實現起來很難,除非真的搞來一個和現實中的ATM機一樣的讀卡設備
2.我想了很久,用一個文本文檔,裡面存放有卡號,用戶名等基本信息,然後導入文本的數據來模擬插卡操作,剩下的操作就簡單了
我希望你已經思考過再看的下麵:
源代碼及相關文件源碼下載地址:傳送門
需要四個文件:
主程式ATM.py
#!usr/bin/env python
#-*- coding:utf-8 -*-
# author:yangva
# datetime:2017/12/16 0015 13:32
import random,time
atm_fault = random.randint(0,100) #ATM機隨機故障繫數
if atm_fault == 0:
print('ATM出現故障,暫時不可用,抱歉給您帶來不便')
else:
print('ATM播放幻燈片,推銷新業務(信用卡辦理,VIP會員特權,新卡新功能等等)')
#插入卡操作
try:
#模擬讀卡的操作,這裡用文本文檔代替
card = open(input('歡迎光臨,請在下方插入口插入您的銀行卡(輸入文本文件路徑和文件名):'))
print('正在讀卡,請稍後。。。')
time.sleep(2)
f = eval(card.read())
username = list(f.keys())[0] #取出賬戶名
user_id = f[username]['ID'] #取出銀行卡號
except (NameError,IOError,FileNotFoundError): #輸入的文本不存在則捕獲
print('插入卡操作過程有誤,請檢查是否存在該文件或打開該文件的許可權')
else:
f = open('database.txt','r')
database = eval(f.read())
f.close() #這裡不用with 語句,為保證資料庫文件能立即關閉
print('%s先生,歡迎您!!!'%username[0]) #問候語
if username not in database.keys():
print('您的賬戶已凍結,請本人攜帶身份證到銀行櫃臺解凍\n已退卡,請收好您的銀行卡')
else:
password = input('請輸入您的密碼(密碼為6位數字),請註意周圍環境以及遮擋鍵盤操作:').strip() #後期可以改為語言提示
count = 0 #用於操作計數
ctrl_flag = False #標誌位,用於跳出多層迴圈
while not ctrl_flag:
if count == 2:
print('您已輸入多次錯誤密碼,銀行賬戶已凍結')
with open('log.txt','a') as f2: #寫入日誌
database['freeze'+username] = database.pop(username)
f1 = open('database.txt','w') #同樣的,不用with語句,保證數據文件立即關閉
f1.write(str(database))
f2.write(str(time.strftime("%Y %b %d %X"))+'\n用戶 %s 的銀行卡已凍結\n'%user_id)
f1.close()
ctrl_flag = True
break
if len(str(password)) == 6: #用於判斷輸入的密碼位數是否正確
if password == database[username]['password']:
database_bk = database #做臨時備份數據的操作,方便後面出錯時會滾
temp = '' #憑條
while not ctrl_flag:
cont = input('1.取款\n2.存款\n3.轉賬\n4.查詢\n5.列印憑條\n6.退卡\n請選擇交易類型(輸入對應的序號即可):')
#賬戶主體操作
if cont == '1': #取款
withdraw_money = int(input('請輸入取款金額(最低一百):')) #ATM存取都是100的整數,直接用int類型
if withdraw_money %100 == 0:
print('正在點鈔,請稍後。。。')
if withdraw_money > database[username]['balance']:
print('操作失敗,您輸入的金額大於您的餘額總數')
else:
time.sleep(3)
print('已成功出鈔,請取走您的鈔票 %s元'%withdraw_money)
database[username]['balance'] -= withdraw_money
with open('log.txt','a') as f: #寫入日誌
f.write(str(time.strftime("%Y %b %d %X"))+'\t卡號為 %s 的用戶 %s 取出金額:%d\n'%(user_id,username,withdraw_money))
temp += str(time.strftime("%Y %b %d %X"))+'\t取款金額:%d\n'%withdraw_money #記錄憑條
else:
print('輸入金額不是100的整數倍,請重新輸入')
elif cont == '2': #存款
save_money = int(input('請將鈔票疊好,並整齊放入存鈔口(輸入存款金額):')) #ATM存取款都是100的整數,直接用int類型
print('正在點鈔,請稍後。。。')
time.sleep(3)
print('%s 元已成功存入賬戶 %s\t賬戶名 %s'%(save_money,user_id,username))
database[username]['balance'] += save_money
with open('log.txt','a') as f: #寫入日誌
f.write(str(time.strftime("%Y %b %d %X"))+'\t卡號為 %s 的用戶 %s 已存入金額 %d\n'%(user_id,username,save_money))
temp += str(time.strftime("%Y %b %d %X"))+'\t存入金額:%d\n'%save_money
elif cont == '3': #轉賬
transfer_id = input('請輸入轉賬帳戶卡號:')
transfer_user = input('請輸入帳戶名:')
if transfer_id == database[transfer_user]['ID']:
transfer_money = float(input('請輸入轉賬金額:'))
print('正在轉賬,請稍後。。。')
time.sleep(3)
database[username]['balance'] -= transfer_money
database[transfer_user]['balance'] += transfer_money
with open('log.txt','a') as f: #寫入日誌
f.write(str(time.strftime("%Y %b %d %X"))+'\t卡號為 %s 的用戶 %s 轉出金額為 %d 給卡號為 %s 的用戶 %s\n'%(user_id,username,transfer_money,transfer_id,transfer_user))
print('成功轉賬 %s 給卡號為 %s 的用戶 %s'%(transfer_money,transfer_id,transfer_user))
temp += time.strftime("%Y %b %d %X")+'\t向卡號為 %s 的用戶 %s 轉賬 %d \n'%(transfer_id,transfer_user,transfer_money)
else:
print('輸入的卡號為 %s 的用戶名為 %s 賬戶有誤,原因可能賬戶信息不匹配或被凍結'%(transfer_id,transfer_user))
elif cont == '4': #查詢
print('您的餘額為:%.2f'%database[username]['balance'])
elif cont == '5': #列印憑條
print(temp)
elif cont == '6': #退卡
print('正在退卡。。')
time.sleep(1)
print('請取走您的銀行卡,感謝使用')
ctrl_flag = True
break
else:
print('序號輸入有誤,可能不存在序號%s 對應的選項'%cont)
else:
count +=1
password = input('輸入有誤,您還有 %s 次機會\n請重新輸入:'%(3-count)).strip()
else:
count +=1
password = input('密碼僅為6位數字,您還有 %s 次機會\n請重新輸入: '%(3-count)).strip()
with open('log.txt','a') as f1: #寫入日誌
f2 = open('database.txt','w')
f2.write(str(database))
f1.write(str(time.strftime("%Y %b %d %X"))+'\t修改資料庫文件\n')
f2.close()
日誌文件log.txt(自動生成,初始狀態為空)
模擬的銀行卡文件card.txt
{'yang':{'password':'111111','ID': '6662008891880688689'}}
數據文件database.txt
{'ling': {'password': '123456', 'ID': '6662008891880688688', 'balance': 500.86}, 'liu': {'password': '888888', 'ID': '6662008891880688687', 'balance': 200000.0}, 'tian': {'password': '00000', 'ID': '6662008891880688680', 'balance': 448.03}, 'liang': {'password': '666666', 'ID': '6662008891880688681', 'balance': 522.5}, 'yang': {'password': '111111', 'ID': '6662008891880688689', 'balance': 21310.0}}
結果測試:
運行環境隨便你了
(截圖只展示了部分,全部效果自己去體驗吧)
總結優化:
1.其實不光是這個ATM機,前面的幾個項目里都可以用函數或者類來實現功能,如果你們感興趣可以用函數或者類來操作。(為什麼不用函數的原因後期有空再說)。其實我現在都還正在優化中,儘量的簡化代碼但功能又只增不減那種
2.相信聰明的你已經發現了,程式還沒有加入取款當天內只能取多少,存款存多少(單次最多存取多少)的限制,這個就自己去優化了
3.可以優化和擴展的功能還有很多,你可以做成圖形化界面,也可以編譯成exe可執行文件,儘量的做到和真實的ATM機一樣的功能,那你就牛逼了