洗禮靈魂,修煉python(77)--全棧項目實戰篇(5)—— ATM自動存取機系統

来源:http://www.cnblogs.com/yangva/archive/2017/12/16/8047622.html
-Advertisement-
Play Games

要求: 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機一樣的功能,那你就牛逼了

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 初步完成博客系統的架構設計,功能設計和資料庫設計,博客系統的前臺界面和後臺界面目前正在設計中,待完成以後,就可以進入項目搭建和編碼階段了。 ...
  • Map集合 Map介面概述: Java.util.Map<k,v>介面:是一個雙列集合 Map集合的特點: 是一個雙列集合,有兩個泛型key和value,使用的時候key和value的數據類型可 以相同。也可以不同 Key不允許重覆的,value可以重覆的; 一個key只能對應一個value Map ...
  • import queue from battle import commander # import math unit_client = commander.Client() doing_last_order = True towerid = [] towerrg = [] towerfr = [... ...
  • 一、filter()函數 filter()接收一個函數和一個序列。filter()把傳入的函數依次作用於每個元素,然後根據返回值是True還是False決定保留還是丟棄該元素。 filter()函數返回的是一個Iterator,也就是一個惰性序列,所以要強迫filter()完成計算結果,需要用lis ...
  • CSS 為了讓網頁元素的樣式更加豐富,也為了讓網頁的內容和樣式能拆分開,CSS由此思想而誕生,CSS是 Cascading Style Sheets 的首字母縮寫,意思是層疊樣式表。有了CSS,html中大部分表現樣式的標簽就廢棄不用了,html只負責文檔的結構和內容,表現形式完全交給CSS,htm ...
  • 定義: 為子系統中的一組介面提供一個一致的界面,Facade模式定義了一個高層介面,這個介面使得這一子系統更加容易使用。 角色: 1,外觀(Facade)角色 :客戶端可以調用這個角色的方法。此角色知曉相關子系統的功能和責任。在正常情況下,本角色會將所有從客戶端發來的請求委派到相應的子系統去。 2, ...
  • 一、map()函數 map()函數接收兩個參數,一個是函數,一個是Iterable,map將傳入的函數依次作用到序列的每個元素,並把結果作為新的Iterator返回。 二、reduce()函數 reduce把一個函數作用在一個序列[x1, x2, x3, ...]上,這個函數必須接收兩個參數,red ...
  • 一、2個概念: 1、變數可以指向函數本身 2、函數名也是變數 二、高階函數 一個函數可以接收另一個函數作為參數,這種函數就稱之為高階函數。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...