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机一样的功能,那你就牛逼了

  • 相关阅读:
    sql server中使用链接服务器访问oracle数据库
    biztalk中使用信封(Envelope)消息
    EMS SQL Manager 2007 for MySQL发布
    MySQL Connector/NET
    Silverlight相关资源
    ADO.NET嵌套数据绑定
    收到网上订得书了,开始充电...
    几个.net下的ajax框架
    Visual Studio 2008 Beta 2 初步体验
    .Net Remoting常用部署结构
  • 原文地址:https://www.cnblogs.com/Eeyhan/p/8047622.html
Copyright © 2011-2022 走看看