基于Python下的自动售货系统

  • 题目描述
  • 分析过程
  • 完整代码
  • 运行测试

题目描述

1 总体说明

考生需要模拟实现一个简单的自动售货系统,实现投币、购买商品、退币、查询库存商品及存钱盒信息的功能。

系统初始化时自动售货机中商品为6种商品,商品的单价参见1.1规格说明,存钱盒内放置1元、2元、5元、10元钱币,商品数量和钱币张数通过初始化命令设置,参见2.1 系统初始化。

1.1规格说明

  1. 商品:每种商品包含商品名称、单价、数量三种属性,其中商品名不重复。考生不能修改商品名称和单价,初始化命令设置商品数量。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。
商品名称 单价 数量
A1 2 X
A2 3 X
A3 4 X
A4 5 X
A5 8 X
A6 6 X

2. 存钱盒信息:
钱币面额、张数两种属性。初始化命令设置各种面额钱币张数。这些信息在考试框架中进行定义,考生在实现功能代码时可直接使用。

钱币面额 张数
10元 X
5元 X
2元 X
1元 X

3. 退币原则 :

  1. 根据系统存钱盒内钱币的 信息 ,按钱币总张数最少的原则进行退币。

  2. 如果因零钱不足导致不能退币,则尽最大可能退币,以减少用户损失。

例如:假设存钱盒内只有4张2元,无其它面额钱币。如果需要退币7元,系统因零钱不足无法退币,则继续尝试退币6元,最终系统成功退币3张2元,用户损失1元钱币。

**4. 投币操作说明:**每次投币成功,投入的钱币面额累加到投币余额;同时,本次投入的钱币放入存钱盒中,存钱盒相应面额钱币增加。

**5. 投币余额:**指当前自动售货机中用户剩余的可购买商品的钱币总额;例如:投入2元面额的钱币,投币余额增加2元;购买一件价格2元的商品,投币余额减少2元;

**6. 投币余额约束:**投币余额不能超过10元。

**7. 退币操作说明:**退币操作需要遵守 退币原则 ;退币成功后,投币余额清零,同时扣除存钱盒相应的金额。

**8. 购买商品操作说明:**一次仅允许购买一件商品;购买商品成功后,自动售货机中对应商品数量减1,投币余额扣除本次购买商品的价格。

2 操作说明

命令字与第一个参数间使用一个空格分隔,多条命令采用分号隔开。考试系统会对输入命令格式进行处理,考生不需要关注输入命令格式的合法性,只需要实现命令处理函数。

2.1 系统初始化

命令格式:

r A1 数量 - A2 数量 - A3 数量 - A4 数量 - A5 数量 - A6 数量 1 元张数 -2 元张数 -5 元张数 -10 元张数

参数名称 参数说明 类型 取值范围
A1数量 商品A1数量 整数 [0,10]
A2数量 商品A2数量 整数 [0,10]
A3数量 商品A3数量 整数 [0,10]
A4数量 商品A4数量 整数 [0,10]
A5数量 商品A5数量 整数 [0,10]
A6数量 商品A6数量 整数 [0,10]
1元张数 面额1元钱币张数 整数 [0,10]
2元张数 面额2元钱币张数 整数 [0,10]
5元张数 面额5元钱币张数 整数 [0,10]
10元张数 面额10元钱币张数 整数 [0,10]

商品和各种面额钱币取值范围只是作为初始化命令的限制,其它场景下不限制取值范围;考试框架已经实现取值范围的检查,考生不需要关注。

功能说明:设置自动售货机中商品数量和存钱盒各种面额的钱币张数;

约束说明:系统在任意阶段均可执行r初始化系统;考生不需要关注参数的合法性,不需要关注增加或缺少参数的场景;

输出说明:输出操作成功提示(执行完r命令后系统会自动输出操作结果,考生不需要再次调用输出函数)
例:

命令 输出 含义
r 6-5-4-3-2-1 4-3-2-1; S001:Initialization is successful 初始化成功

2.2 投币

命令格式:p 钱币面额

功能说明:

(1)如果投入非1元、2元、5元、10元的钱币面额(钱币面额不考虑负数、字符等非正整数的情况),输出“E002:Denomination error”;

(2) 如果存钱盒中1元和2元面额钱币总额小于本次投入的钱币面额,输出“E003:Change is not enough, pay fail”,但投入1元和2元面额钱币不受此限制。

(3) 如果投币余额大于10元,输出“E004:Pay the balance is beyond the scope biggest”;

(4) 如果自动售货机中商品全部销售完毕,投币失败。输出“E005:All the goods sold out”;

(5) 如果投币成功,输出“S002:Pay success,balance=X”;

约束说明:

(1) 系统在任意阶段都可以投币;

(2) 一次投币只能投一张钱币;

(3) 同等条件下,错误码的优先级:E002 > E003 > E004 > E005;

输出说明:如果投币成功,输出“S002:Pay success,balance=X”。

例:

命令 输出
p 10; S002:Pay success,balance=10

2.3 购买商品

命令格式:b 商品名称

功能说明:

(1) 如果购买的商品不在商品列表中,输出“E006:Goods does not exist”;

(2) 如果所购买的商品的数量为0,输出“E007:The goods sold out”;

(3) 如果投币余额小于待购买商品价格,输出“E008:Lack of balance”;

(4) 如果购买成功,输出“S003:Buy success,balance=X”;

约束说明:

(1) 一次购买操作仅能购买一件商品,可以多次购买;

(2) 同等条件下,错误码的优先级:E006 > E007 > E008;

输出说明:

如果购买成功,输出“S003:Buy success,balance=X”。

例:

命令 输出
b A1; S003:Buy success,balance=8

2.4 退币

命令格式:c

功能说明:

(1) 如果投币余额等于0的情况下,输出“E009:Work failure”;

(2) 如果投币余额大于0的情况下,按照 退币原则 进行“找零”,输出退币信息;

约束说明:

(1) 系统在任意阶段都可以退币;

(2) 退币方式必须按照 退币原则 进行退币;

输出说明:如果退币成功,按照 退币原则 输出退币信息。

例,退5元钱币:

命令 输出
c 1 yuan coin number=0
2 yuan coin number=0
5 yuan coin number=1
10 yuan coin number=0

2.5 查询

命令格式:q 查询类别

功能说明:

(1) 查询自动售货机中商品信息,包含商品名称、单价、数量。 根据商品数量从大到小进行排序;商品数量相同时,按照商品名称的先后顺序进行排序 。

例如:A1的商品名称先于A2的商品名称,A2的商品名称先于A3的商品名称。

(2) 查询存钱盒信息,包含各种面额钱币的张数;

(3) 查询类别如下表所示:

查询类别 查询内容
0 查询商品信息
1 查询存钱盒信息

如果“查询类别”参数错误,输出“E010:Parameter error”。“查询类别”参数错误时,不进行下面的处理;

输出说明:

“查询类别”为0时,输出自动售货机中所有商品信息(商品名称单价数量)例:

命令 输出
q 0; A1 2 6
A2 3 5
A3 4 4
A4 5 3
A5 8 2
A6 6 0

“查询类别”为1时,输出存钱盒信息(各种面额钱币的张数),格式固定。例:

命令 输出
q 1; 1 yuan coin number=4
2 yuan coin number=3
5 yuan coin number=2
10 yuan coin number=1

分析过程

1.画出总体框架

基于Python下的自动售货系统_第1张图片

2.数据存储方式选择
选择列表的存储方式(不建议,字典可能会好一些,准备使用字典再做一遍)

#商品信息
goods = [
    ['A1', 2, 10],
    ['A2', 3, 10],
    ['A3', 4, 10],
    ['A4', 5, 10],
    ['A5', 8, 10],
    ['A6', 6, 10]
]
#机内币数
coins = [
    [1, 10],
    [2, 10],
    [5, 10],
    [10, 10]
]

3.系统函数分块
首先发现命令格式都为字母 + 空格 + 数字的形式,即将命令分割开(.split),判断列表首元素即调用相应的函数。

初始化函数:
命令除过首字母外,分为商品数量,机内币数的初始化值。将命令判断字母、商品数量、机内币数通过(.split)分开后,依次再分别通过(.split)分开获得存储两个数据的列表。
将两个列表中的数据分别赋给相应的商品及面额。

投币函数
除了字母外,只有一个数字,即为所要投币的数目,所投面额的钱数+1。
1).判断面额是否在面额集合[1,2,5,10]中,即使用in判度即可。

if int(CoinValue_list[1]) in [1, 2, 5, 10]: 

2).判断是否1yuan和2yuan总额是否小与所投币的面额,将1yuan和2yuan的数量分别乘以对应面额。

if coins[0][1] * 1 + coins[1][1] * 2 < balance :

3).判断是否余额大于十元,即多次投币结果,我选择将所投钱数装进一个列表里,判断总余额时对列表里的数累加即可。

coins_sum.append(int(CoinValue_list[1]))

4).判断商品全部售完,即for循环遍历所有商品数量,我选择累加,判断累加和是否为0

for i in range(6):
	goods_count += goods[i][2]      #商品总数判断

5).输出投币成功

购买函数
分割命令,除字母外,为商品名称。
1).循环遍历所有商品名,判断所购买的商品是否在列表中。

for good in goods:     #循环商品
    if GoodsNeed_list[1] not in GoodsName:      ##如果输入商品不在商品名称列表里,则E006
        print(GoodsNeed_list[1])
        print(good)
        print("E006:Goods does not exist")
    elif GoodsNeed_list[1] == good[0]:             #输入商品在商品名称列表里,输出对应商品的相关信息
        GoodsInfo = good

2).判断所购买商品的数量为0,即判断所购买商品所对应的商品数量是否为0.

    if GoodsInfo[2] == 0:
        print("E007:The goods sold out")

3).判断投币余额小余购买的商品价格,即存储的余额与商品价格对比,

if GoodsInfo[1] > sumMycoin(coins_sum):

4)购买成功,将所购买商品的价格取负加入余额列表,对列表取和即为此时余额,所买商品数量-1。

coins_sum.append(-GoodsInfo[1])
BuySpend.append(GoodsInfo[1])
print("S003:Buy success,balance=%d" % (sumMycoin(coins_sum)))

退币函数
1)判断余额是否等于0

sumMycoin(coins_sum) == 0

2).当余额大于0时退币,退币按张数最少的原则退币,即针对余额首先判断最大面额的钱数,成功,若还有未退的钱,重新循环,零钱不足时,也可由此方法按原则退币。

for i in range(4)[::-1]:	#反转钱币面额列表
    if coins[i][0] <= sumMycoin(coins_sum) and coins[i][1] > 0:
        coins[i][1] -= 1         #对应钱币减1
        coins_sum.append(-coins[i][0])   #余额减去对应面额
        Coin_return[i][1] += 1   #退币列表增加所退面额的数量

查询函数
判断字母后的数为0还是1
1).商品信息排序通过sorted排序,设置排序方式为商品由大到小,且数量相同时。按照名称进行排序。
2)钱币排序为面额由小到大,默认即为如此,循环输出即可。

goodsSorted = sorted(goods,key = sorted_by_count_price,reverse=True)

完整代码

goods = [
    ['A1', 2, 10],
    ['A2', 3, 10],
    ['A3', 4, 10],
    ['A4', 5, 10],
    ['A5', 8, 10],
    ['A6', 6, 10]
]
coins = [
    [1, 10],
    [2, 10],
    [5, 10],
    [10, 10]
]
balance = 0
GoodsName = []
for i in goods:  # 循环商品
    GoodsName.append(i[0])  # 添加商品名称

def sumMycoin(li,type=list):
    sum_1 = 0
    for i in li:
        sum_1 += i
    return sum_1
def sorted_by_count_price(x):
    return x[2],x[0]

def initial(Command_list):
    ##判断命令是否为'r'
    goods_count_list = Command_list[1].split("-")
    coins_count_list = Command_list[2].split("-")
    ##将输入的数量赋值给商品数量
    for i in range(6):
        if int(goods_count_list[i]) < 11 and int(goods_count_list[i]) >= 0:
            goods[i][2] = int(goods_count_list[i])
        else:
            if int(goods_count_list[i]) < 0:
                goods_count_list[i] = 0
            elif int(goods_count_list[i]) > 10:
                goods_count_list[i] = 10
            else:
                print("error")
    ##将输入的数量赋值给钱币数量
    for i in range(4):
        if int(coins_count_list[i]) < 11 and int(coins_count_list[i]) >= 0:
            coins[i][1] = int(coins_count_list[i])
        else:
            if int(coins_count_list[i]) < 0:
                coins_count_list[i] = 0
            elif int(coins_count_list[i]) > 10:
                coins_count_list[i] = 10
            else:
                print("error")
    print("S001:Initialization is successful")

coins_sum = []                                          ##投币
def Paycoin(Command_list):
    global balance
    goods_count = 0                                     ##商品数量总数
    coins_values = [1,2,5,10]
    if int(Command_list[1]) in [1, 2, 5, 10]:     ##判断投币是否在[1,2,5,10]面额上
        balance = int(Command_list[1])  ##用户投币的面额加入余额
        coins_sum.append(int(Command_list[1]))
        coins[coins_values.index(int(Command_list[1]))][1] += 1       ##对所投币的累加
        ##判断剩余1元面额与2元面额之和是否比投入面额小
        if coins[0][1] * 1 + coins[1][1] * 2 < balance :                   ##sumMycoin(coins_sum)
             #判断是否1,2元总数小于本次投入的面额
            print("E003:Change is enough,pay fail")
            coins_sum.pop()                                 #停止此次投币
        else:
            if balance > 10:
                print("E004:Pay the balance is beyond the scope biggest")
                coins_sum.pop()                             #停止此次投币
            else:
                for i in range(6):
                    goods_count += goods[i][2]      #商品总数判断
                if goods_count == 0:
                    print("E005:All the goods sold out")
                    coins_sum.pop()
                else:
                    print("S002:Pay success,balance=%d" %(sumMycoin(coins_sum)))
        # return sumMycoin(coins_sum)
    elif int(Command_list[1]) not in [1, 2, 5, 10]:
        print("E002:Denomination error")


BuySpend = []
def buyGoods(Command_list):     #b A1
    for good in goods:     #循环商品
        if Command_list[1] not in GoodsName:      ##如果输入商品不在商品名称列表里,则E006
            print("E006:Goods does not exist")
        elif Command_list[1] == good[0]:             #输入商品在商品名称列表里,输出对应商品的相关信息
            GoodsInfo = good
    if GoodsInfo[2] == 0:
        print("E007:The goods sold out")
    else:
        if GoodsInfo[1] > sumMycoin(coins_sum):
            print("E008:Lack of balance")
        else:
	    GoodsInfo[2] -= 1
            coins_sum.append(-GoodsInfo[1])
            BuySpend.append(GoodsInfo[1])
            print("S003:Buy success,balance=%d" % (sumMycoin(coins_sum)))

Coin_return = []
for i in range(4):
    Coin_return.append([coins[i][0],0])
def returnCoin(Command_list):
    if sumMycoin(coins_sum) == 0:
        print("E009:Work failure")
    elif sumMycoin(coins_sum) > 0:
        for i in range(4)[::-1]:
            if coins[i][0] <= sumMycoin(coins_sum) and coins[i][1] > 0:
                coins[i][1] -= 1
                coins_sum.append(-coins[i][0])
                Coin_return[i][1] += 1
        for i in range(3):
            print("%d  yuan coin number=%d" %(Coin_return[i][0],Coin_return[i][1]))
        print("%d yuan coin number=%d" % (Coin_return[3][0], Coin_return[3][1]))



def queryGoods(Command_list):
    if Command_list[1] == '0':
        goodsSorted = sorted(goods,key = sorted_by_count_price,reverse=True)
        for i in goodsSorted:
            print("%s\t%d\t%d" %(i[0],i[1],i[2]))
    elif Command_list[1] == '1':
        for i in range(3):
            print("%d  yuan coin number=%d" %(coins[i][0],coins[i][1]))
        print("%d yuan coin number=%d" % (coins[3][0], coins[3][1]))
    else:
        print("E010:Parameter error")


def main():

    print("""
                    请在以下命令中选择所需操作

                    1.   r x-x-x-x-x-x x-x-x-x     初始化操作
                    2.     p 1/2/5/10(yuan)        投币             
                    3.         b goods             购买商品
                    4.         c                   退币
                    5.         q 0                 查询商品信息
                    6.         q 1                 查询钱盒信息
                    7.         quit                退出系统
    """)

    while True:
        Command = input("请输入操作:")
        Command_list = Command.split(" ")
        if Command_list[0] == 'p':
            Paycoin(Command_list)
        elif Command_list[0] == 'b':
            buyGoods(Command_list)
        elif Command_list[0] == 'c':
            returnCoin(Command_list)
        elif Command_list[0] == 'q':
            queryGoods(Command_list)
        elif Command_list[0] == 'r':
            initial(Command_list)
        elif  Command_list[0] == 'quit':
            break
main()

测试运行

成功运行结果
基于Python下的自动售货系统_第2张图片
非成功结果
投币模块
基于Python下的自动售货系统_第3张图片
购买模块
E006有点问题
基于Python下的自动售货系统_第4张图片
查询模块
基于Python下的自动售货系统_第5张图片

还有很多问题需要改进!!!

你可能感兴趣的:(Python应用,Python)