python-實現不放回抽簽


需求:1.不放回抽簽 2.把名單上的人員都抽取完以后才能開始下一輪 3.每次打分數都累加 4.可以查看前三和后三名

使用excel實現:思路就是先拿到名單數據,然后抽簽(判斷抽出來的人在不在新list中),打分,排序。使用遞歸調用實現多次抽取。

數據樣例:

import xlrd
import random
import sys
from openpyxl import load_workbook

filename = '參訓人員名單.xlsx'
name_new_list = []

def open_excel():
    xl = xlrd.open_workbook(filename)
    sheet = xl.sheet_by_index(0)
    return sheet

def read_name():
    sheet = open_excel()
    row_num = sheet.nrows# 獲取excel中有多少行
    name_score = []
    for i in range(1,row_num):
        value = sheet.row_values(i)#取出每一行的名字和分數
        name_score.append(value)
    new_name_score = dict(name_score)  #返回姓名分數列表
    return new_name_score

def draw_people():
    names = read_name()  # 獲取姓名分數字典
    name_list = list(names.keys())  # 把姓名拿出來,當一個列表,用來抽取
    if len(name_new_list) == len(name_list):# 如果原始列表和存放抽取名字的列表相等,清空存放名字列表
        nu = input('名單上的人員都已被抽過!開啟新一輪的抽簽請輸入1\n 返回上級菜單請輸入2\n')
        if nu == '1':
            name_new_list.clear()
        else:
            return   #返回主菜單
    people_name = random.choice(name_list)
    if people_name not in name_new_list:
        name_new_list.append(people_name)
        name_num = name_list.index(people_name)+2  # 獲取序號+2,因為下標從0開始,
        print('此次抽中的人員是:',people_name)
        mark_score(name_num)
    else:
        draw_people()

def mark_score(people_num):
    wb = load_workbook(filename)
    wb1 = wb.active  # 激活sheet
    old_score = wb1.cell(row = people_num,column = 2).value #取出原始分數
    print("該人員的現有分數是:",old_score)
    while True:
        try:
            this_score = input("請給抽中的人員打分數(請輸入整數):")
            this_score = int(this_score)
            break
        except ValueError:
            print('請輸入一個整數')
    now_score = int(old_score) + int(this_score)
    wb1.cell(people_num,2,now_score)#寫入分數列
    wb.save(filename)  # 保存

def sort_score():  #排序
    all_score = read_name()#拿到姓名和分數組成的字典
    for key in all_score:
        all_score[key] = int(all_score[key])  # 把數字的小數點去掉才排序
    desc = sorted(all_score.items(),key=lambda x:x[1], reverse=False)[:3]#倒序排,輸出前三
    asc = sorted(all_score.items(),key=lambda x:x[1], reverse=True)[:3]#正序排,輸出前三
    print("排名前三的人員:",asc)
    print("排名后三的人員:",desc)

def main():
    num = input("---抽簽,請輸入1\n---查看排名,請輸入2\n---退出程序,請輸入3\n")
    if num == '1' :
        draw_people()
        main()
    elif num == '2':
        sort_score()
        main()
    else:
        sys.exit(0)

if __name__ == '__main__':
    main()

 

用txt實現:先讀出全部數據,然后分割成列表。寫入的時候現封裝成一個列表,再寫進去。排序時應該先把value轉成int,才能進行排序

數據樣例:

import random
import sys
import codecs
import operator

filename = '名單.txt'
name_new_list = []
name_dict = {}


def read_txt():
    with codecs.open(filename, 'r', 'utf-8') as fp:
        data = fp.readlines()
        '''
        讀取到的data:
        ['張三:62\r\n', '李四:117\r\n', 'waang2:40\r\n', 'yuuu:60\r\n', '李磊:90']
        '''
        for line in data:
            name_score = line.replace('\r', '').replace('\n', '').split(':')  # 把每一行數據用:拆分成2個元素
            '''
            ['張三', '62']
            ['李四', '117']
            ['waang2', '40']
            ['yuuu', '60']
            ['李磊:90']
            '''
            if len(name_score) == 2:  # 以防txt里面有空行
                name_dict[name_score[0]] = int(name_score[1]) #把value轉成int,用於后面的加減和排序 return name_dict


def draw_people(name_list):
    if len(name_new_list) == len(name_list):  # 如果原始列表和存放抽取名字的列表相等,清空存放名字列表
        nu = input('名單上的人員都已被抽過!開啟新一輪的抽簽請輸入1  返回上級菜單請輸入2\n')
        if nu == '1':
            name_new_list.clear()
        else:
            return
    while True:
        people_name = random.choice(name_list)
        if people_name not in name_new_list:
            name_new_list.append(people_name)
            print('此次抽中的人員是:', people_name)
            mark_score(people_name, name_dict)
            break


'''
使用遞歸調用
    people_name = random.choice(name_list)
    if people_name not in name_new_list:
        name_new_list.append(people_name)
        print('此次抽中的人員是:', people_name)
        mark_score(people_name, name_dict)
    else:
        draw_people()
'''


def mark_score(people_name, name_dict):
    print("該人員的現有分數是:%s分" % (name_dict[people_name]))
    while True:
        try:
            now_score = int(input("請給抽中的人員打分數(請輸入整數):"))
            name_dict[people_name] += now_score # 總分
            with open(filename, 'w', encoding='utf-8') as f:
                tmp = ''
                for key in name_dict:  # 用key來循環,把key和value組裝
                    tmp += (str(key) + ":" + str(name_dict[key]) + '\n')
                f.writelines(tmp)  # 一次性寫入
                f.close()  # 保存
            break
        except ValueError:
            print('請輸入一個整數')


def sort_score(name_and_score):  # 排序
    desc = sorted(
        name_and_score.items(),
        key=operator.itemgetter(1),
        reverse=False)[:3]  # 倒序排,輸出前三
    asc = sorted(
        name_and_score.items(),
        key=operator.itemgetter(1),
        reverse=True)[:3]  # 正序排,輸出前三
    '''
    name_and_score.items(): dict_items([('張三', 506), ('李四', '344'), ('waang2', '4029'), ('yuuu', '64')])
    operator排序速度比匿名函數更快,也支持多個關鍵字同時排序。,operator.itemgetter函數獲取的不是值,而是定義了一個函數,通過該函數作用到對象上才能獲取值。
    itemgetter(1)是獲取items()對象的第一個域,對域的值排序(對value排序)
    '''
    print("排名前三位的人員:", dict(asc))
    print("排名后三位的人員:", dict(desc))


def main():
    name_score = read_txt()
    name_list = list(name_score.keys())  # 把姓名拿出來,當一個列表,用來抽取
    num = input("---抽簽,請輸入1\n---查看排名,請輸入2\n---退出程序,請輸入3\n請輸入:")
    if num == '1':
        draw_people(name_list)
        print('\r')
        main()
    elif num == '2':
        sort_score(name_score)
        print('\r')
        main()
    else:
        sys.exit(0)


if __name__ == '__main__':
    main()

 

 

抽簽方法不用遞歸,用while循環實現

def draw_people():
    name_score = read_txt()
    name_list = list(name_score.keys())  # 把姓名拿出來,當一個列表,用來抽取
    if len(name_new_list) == len(name_list):# 如果原始列表和存放抽取名字的列表相等,清空存放名字列表
        nu = input('名單上的人員都已被抽過!開啟新一輪的抽簽請輸入1  返回上級菜單請輸入2\n')
        if nu == '1':
            name_new_list.clear()
        else:
            return
    while True:
        people_name = random.choice(name_list)
        if people_name not in name_new_list:
            name_new_list.append(people_name)
            print('此次抽中的人員是:',people_name)
            mark_score(people_name,name_dict)
            break

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM