zoukankan      html  css  js  c++  java
  • 洗礼灵魂,修炼python(77)--全栈项目实战篇(5)—— ATM自动存取机系统

    要求:

    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('您的账户已冻结,请本人携带身份证到银行柜台解冻
    已退卡,请收好您的银行卡')
            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"))+'
    用户 %s 的银行卡已冻结
    '%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.取款
    2.存款
    3.转账
    4.查询
    5.打印凭条
    6.退卡
    请选择交易类型(输入对应的序号即可):')
                                #账户主体操作
                                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"))+'	卡号为 %s 的用户 %s 取出金额:%d
    '%(user_id,username,withdraw_money))
                                            temp += str(time.strftime("%Y %b %d %X"))+'	取款金额:%d
    '%withdraw_money  #记录凭条
                                    else:
                                        print('输入金额不是100的整数倍,请重新输入')
                                elif cont == '2': #存款
                                    save_money = int(input('请将钞票叠好,并整齐放入存钞口(输入存款金额):')) #ATM存取款都是100的整数,直接用int类型
                                    print('正在点钞,请稍后。。。')
                                    time.sleep(3)
                                    print('%s 元已成功存入账户 %s	账户名 %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"))+'	卡号为 %s 的用户 %s  已存入金额 %d
    '%(user_id,username,save_money))
                                    temp += str(time.strftime("%Y %b %d %X"))+'	存入金额:%d
    '%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"))+'	卡号为 %s 的用户 %s 转出金额为 %d 给卡号为 %s 的用户 %s
    '%(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")+'	向卡号为 %s 的用户 %s 转账 %d 
    '%(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 次机会
    请重新输入:'%(3-count)).strip()
                    else:
                        count +=1
                        password = input('密码仅为6位数字,您还有 %s 次机会
    请重新输入: '%(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"))+'	修改数据库文件
    ')
                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机一样的功能,那你就牛逼了

  • 相关阅读:
    LeetCode Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/Eeyhan/p/8047622.html
Copyright © 2011-2022 走看看