Python制作一個(gè)隨機(jī)抽獎(jiǎng)小工具的實(shí)現(xiàn)
最近在工作中面向社群玩家組織了一場(chǎng)活動(dòng),需要進(jìn)行隨機(jī)抽獎(jiǎng),參考之前小明大佬的案例,再結(jié)合自己的需求,做了一個(gè)簡(jiǎn)單的隨機(jī)抽獎(jiǎng)小工具。
今天我就來順便介紹一下這個(gè)小工具的制作過程吧!
先看效果:
1. 核心功能設(shè)計(jì)
針對(duì)隨機(jī)抽獎(jiǎng)的小工具,需要可以導(dǎo)入?yún)⑴c抽獎(jiǎng)的人員名單,然后選擇不同的獎(jiǎng)勵(lì)類型進(jìn)行隨機(jī)抽取獲獎(jiǎng)名單并導(dǎo)出。
那么,簡(jiǎn)單進(jìn)行需求拆解,大致梳理出以下核心功能:
名單導(dǎo)入
為了避免出現(xiàn)重名情況,這里我們約定以下幾點(diǎn):
①導(dǎo)入?yún)⑴c抽獎(jiǎng)的人員名單文件(xlsx
類型文件)
②數(shù)據(jù)第一列為ID,第二列為name
參考格式案例
獎(jiǎng)項(xiàng)類型選擇
獎(jiǎng)項(xiàng)類型是指一等獎(jiǎng)、二等獎(jiǎng)這類標(biāo)識(shí)語,這里我們內(nèi)置了特等獎(jiǎng)-六等獎(jiǎng)共7個(gè)選項(xiàng)供選取
本輪人數(shù)
本輪人數(shù)是指每次抽獎(jiǎng)時(shí)一次性抽取的獲獎(jiǎng)人數(shù),默認(rèn)值為5
①當(dāng)填入的數(shù)字超過剩余未獲獎(jiǎng)人數(shù)時(shí),會(huì)進(jìn)行提示并顯示未獲獎(jiǎng)人數(shù)
②當(dāng)填入的數(shù)字為0表示輪空,也需要手動(dòng)結(jié)束
③當(dāng)填入的數(shù)字為負(fù)數(shù)時(shí),點(diǎn)擊抽獎(jiǎng)無響應(yīng)
④當(dāng)填入的非數(shù)字時(shí),會(huì)進(jìn)行提示需要輸入正確數(shù)字
抽獎(jiǎng)時(shí)輪播區(qū)域
用于顯示抽獎(jiǎng)中隨機(jī)滾動(dòng)參與本輪抽獎(jiǎng)的人員名單
人員名單
當(dāng)選擇正確的人員名單文件后,這里會(huì)自動(dòng)顯示人員信息列表
中獎(jiǎng)記錄
記錄每次抽取的獎(jiǎng)項(xiàng)類型及獲獎(jiǎng)名單
開始抽獎(jiǎng)
①開始抽獎(jiǎng)時(shí),會(huì)先判斷抽獎(jiǎng)設(shè)置是否滿足條件,否則會(huì)有相關(guān)提示
②抽獎(jiǎng)中點(diǎn)擊開始抽獎(jiǎng)會(huì)提示正在抽獎(jiǎng)中
結(jié)束
①非抽獎(jiǎng)狀態(tài)下點(diǎn)擊結(jié)束無響應(yīng)
②抽獎(jiǎng)中點(diǎn)擊結(jié)束將顯示本次抽獎(jiǎng)結(jié)果
重置
①重置會(huì)清掉歷史抽獎(jiǎng)記錄(含本地文件,如有必要建議對(duì)中獎(jiǎng)名單留檔)
②抽獎(jiǎng)中點(diǎn)擊重置會(huì)提示正在抽獎(jiǎng)中
③非抽獎(jiǎng)狀態(tài)點(diǎn)擊重置會(huì)提示該操作會(huì)刪除歷史記錄,是否確認(rèn)
基本功能點(diǎn)確認(rèn)后,我們就開始進(jìn)行GUI設(shè)計(jì)。
2. GUI設(shè)計(jì)與實(shí)現(xiàn)
基于功能點(diǎn),我們用axure
簡(jiǎn)單進(jìn)行UI布局設(shè)計(jì)
,然后再通過GUI
開發(fā)庫進(jìn)行設(shè)計(jì),這里依舊采用的是pysimplegui
,主要是簡(jiǎn)單方便。
基于GUI設(shè)計(jì),我們編碼如下:
nameList_column = [ [sg.Text('人員名單:')], [sg.Listbox(values=[], size=(20, 10), key='nameList')], ] result_column = [ [sg.Text('中獎(jiǎng)記錄:')], [sg.Multiline('', size=(48, 10), key='result', text_color='DeepPink')], ] # 主題設(shè)置 sg.theme('SystemDefaultForReal') # 布局設(shè)置 layout = [[sg.Text('選擇參與抽獎(jiǎng)人員名單文件:', font=('微軟雅黑', 12)), sg.InputText('', key='_file', size=(50, 1), font=('微軟雅黑', 10), enable_events=True), sg.FileBrowse('打開', file_types=(('Text Files', '*.xlsx'),), size=(10, 1), font=('微軟雅黑', 11))], [sg.Frame(layout=[ [sg.Text('本輪獎(jiǎng)項(xiàng):', font=('微軟雅黑', 12)), sg.Combo(['特等獎(jiǎng)', '一等獎(jiǎng)', '二等獎(jiǎng)', '三等獎(jiǎng)', '四等獎(jiǎng)', '五等獎(jiǎng)', '六等獎(jiǎng)'], font=('微軟雅黑', 10), default_value='特等獎(jiǎng)', size=(15, 5), key='_type'), sg.Text('本輪人數(shù):', font=('微軟雅黑', 12)), sg.InputText('5', key='_num', size=(38, 1), font=('微軟雅黑', 10))], ], title='抽獎(jiǎng)設(shè)置', title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='請(qǐng)進(jìn)行抽獎(jiǎng)設(shè)置后再開始抽獎(jiǎng)')], [sg.Multiline(size=(48, 5), font=( '微軟雅黑', 18), text_color='Blue', key='luckyName', justification='center')], [sg.Column(nameList_column), sg.Column(result_column)], [sg.Text('操作說明:', font=('微軟雅黑', 12))], [sg.Text('①先選擇參與抽獎(jiǎng)的人員名單xlsx文件,人員名單文件包含ID和name兩個(gè)字段\n②獲獎(jiǎng)名單將存在小工具所在文件夾,重置會(huì)刪除歷史記錄文件', font=('微軟雅黑', 10)), sg.Text('', font=('微軟雅黑', 12), size=(5, 1)), sg.Button('開始抽獎(jiǎng)', font=('微軟雅黑', 12), button_color='Orange'), sg.Button('結(jié)束', font=('微軟雅黑', 12), button_color='red'), sg.Button('重置', font=('微軟雅黑', 12), button_color='red'), ], ] # 創(chuàng)建窗口 window = sg.Window('抽獎(jiǎng)小工具,作者@微信公眾號(hào):可以叫我才哥', layout, font=('微軟雅黑', 12), default_element_size=(50, 1))
其包含的控件如下:
- Text 文本
- InputText 輸入文本框
- FileBrowse 文件瀏覽
- Multiline 多行文本框
- Combo 下拉框
- Listbox 列表
- Button 按鈕
需要注意的是這里有個(gè)Frame組件,用于layout嵌套,可以很好地模塊化UI布局。
3. 功能實(shí)現(xiàn)
在本案例中,需要實(shí)現(xiàn)三個(gè)功能,分別是:讀取人員名單、隨機(jī)抽獎(jiǎng)以及保存中獎(jiǎng)名單。
3.1 讀取人員名單
這里采用的是openpyxl
讀取表格數(shù)據(jù)并獲得某幾列的值,由于存在表頭,所以最后不需要表頭
def nameList(window): fileName = values['_file'] try: wb = openpyxl.load_workbook(fileName) active_sheet = wb.active names = [cell_object.value for cell_object in list(active_sheet.columns)[1]][1:] ids = [cell_object.value for cell_object in list(active_sheet.columns)[0]][1:] names = [name+'_'+str(id_) for name, id_ in zip(names, ids)] window['nameList'].update(names) return names except: sg.popup('請(qǐng)選擇正確格式的的人員名單文件', title='提示',)
3.2. 隨機(jī)抽獎(jiǎng)
由于我們需要一次隨機(jī)抽取的人數(shù)存在多個(gè),所以這里用的是random.sample()
,需要注意的是傳入的參數(shù)中names是需要去掉已中獎(jiǎng)名單
def Result(window, names): global is_run, luckyNames _type = values['_type'] # 本輪獎(jiǎng)項(xiàng)類型 _num = int(values['_num']) # 本輪人數(shù) while True: randomName = random.sample(names, k=_num) luckyName = ' '.join(randomName) window['luckyName'].update(luckyName) if not is_run: headers = ['獎(jiǎng)項(xiàng)', '名單'] toCsv(headers, [_type]*len(randomName), randomName, lucky) luckyNames = luckyNames + _type+' : '+luckyName+'\n\n' window['result'].update(luckyNames) return time.sleep(0.088)
3.3. 保存中獎(jiǎng)名單
這里我們用的是csv
庫的方法,追加存儲(chǔ)
def toCsv(headers, col1, col2, file): # 存在則追加,不存在則新建 if os.path.exists(lucky): with open(lucky, 'a', encoding='utf_8_sig', newline='') as csvfile: writer = csv.writer(csvfile) writer.writerows(zip(col1, col2)) else: with open(lucky, 'w', encoding='utf_8_sig', newline='') as csvfile: writer = csv.writer(csvfile) writer.writerow(headers) writer.writerows(zip(col1, col2))
完成核心功能函數(shù)后,我們?cè)龠M(jìn)行GUI交互邏輯的實(shí)現(xiàn)。
3.4. GUI交互邏輯
這里有兩個(gè)全局變量,其中一個(gè)用于記錄當(dāng)前抽獎(jiǎng)狀態(tài),另外一個(gè)用于存儲(chǔ)當(dāng)前已經(jīng)獲獎(jiǎng)的人員信息。關(guān)于交互邏輯的詳情,大家可以結(jié)合核心功能需求及以下代碼了解。
# 初始狀態(tài) is_run = False luckyNames = '' # 事件循環(huán) while True: event, values = window.read() if event in (None, '關(guān)閉程序'): break if event == '_file': nameList(window) if event == '開始抽獎(jiǎng)': if is_run: sg.popup('抽獎(jiǎng)進(jìn)行中,無需重復(fù)操作......', title='提示') continue try: names = nameList(window) # 人員名單 _num = int(values['_num']) # 本輪人數(shù) lucky = '中獎(jiǎng)名單.csv' # 中獎(jiǎng)名單 if os.path.exists(lucky): with open('中獎(jiǎng)名單.csv', 'r', encoding='utf_8_sig') as f: reader = csv.reader(f) selectedNames = set([i[1] for i in reader][1:]) names_set = set(names)-selectedNames else: names_set = set(names) if len(names_set) >= _num: is_run = True _thread.start_new_thread(Result, (window, names_set)) else: sg.popup( f'請(qǐng)選擇正確本輪抽獎(jiǎng)人數(shù)(當(dāng)前 {len(names_set)} 個(gè)未中獎(jiǎng)人數(shù))', title='提示') except: sg.popup('請(qǐng)選擇正確本輪抽獎(jiǎng)人數(shù)(別超過總?cè)藬?shù)哦)', title='提示') elif event == '結(jié)束': is_run = False elif event == '重置': if is_run: sg.popup('抽獎(jiǎng)進(jìn)行中,請(qǐng)等待抽獎(jiǎng)結(jié)束后重置...', title='提示') continue yes_no = sg.popup_yes_no( '重置會(huì)清楚歷史數(shù)據(jù),是否執(zhí)行此操作??', text_color='red', title='提示') if yes_no == 'Yes': try: os.remove(lucky) luckyNames = '' window['result'].update(luckyNames) window['luckyName'].update(luckyNames) sg.popup('抽獎(jiǎng)歷史記錄已被重置......', title='提示') except: sg.popup('無抽獎(jiǎng)歷史記錄......', title='提示') window.close()
基于此,我們就完成了隨機(jī)抽獎(jiǎng)小工具的制作。
啟動(dòng)頁如下:
最后,大家感興趣就可以將代碼打包成exe可執(zhí)行文件了,我這邊打包下來大概10MB左右大小。
到此這篇關(guān)于Python制作一個(gè)隨機(jī)抽獎(jiǎng)小工具的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Python 隨機(jī)抽獎(jiǎng)小工具內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Python機(jī)器學(xué)習(xí)應(yīng)用之基于天氣數(shù)據(jù)集的XGBoost分類篇解讀
XGBoost是一個(gè)優(yōu)化的分布式梯度增強(qiáng)庫,旨在實(shí)現(xiàn)高效,靈活和便攜。它在?Gradient?Boosting?框架下實(shí)現(xiàn)機(jī)器學(xué)習(xí)算法。XGBoost提供并行樹提升(也稱為GBDT,GBM),可以快速準(zhǔn)確地解決許多數(shù)據(jù)科學(xué)問題2022-01-01解決jupyter notebook 前面書寫后面內(nèi)容消失的問題
這篇文章主要介紹了解決jupyter notebook 前面書寫后面內(nèi)容消失的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-04-04Python實(shí)現(xiàn)遍歷大量表格文件并篩選出數(shù)據(jù)缺失率低的文件
這篇文章主要為大家詳細(xì)介紹了如何利用Python實(shí)現(xiàn)遍歷大量表格文件并篩選出表格內(nèi)數(shù)據(jù)缺失率低的文件的功能,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-05-05Python采集貓眼兩萬條數(shù)據(jù) 對(duì)《無名之輩》影評(píng)進(jìn)行分析
這篇文章主要給大家介紹了關(guān)于利用Python榮國(guó)采集兩萬條貓眼數(shù)據(jù),對(duì)《無名之輩》影評(píng)進(jìn)行分析的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-12-12Pycharm添加虛擬解釋器報(bào)錯(cuò)問題解決方案
這篇文章主要介紹了Pycharm添加虛擬解釋器報(bào)錯(cuò)問題解決方案,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-10-10python實(shí)現(xiàn)微信打飛機(jī)游戲
這篇文章主要為大家詳細(xì)介紹了python實(shí)現(xiàn)微信打飛機(jī)游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03python調(diào)用Matplotlib繪制分布點(diǎn)圖
這篇文章主要為大家詳細(xì)介紹了python調(diào)用Matplotlib繪制分布點(diǎn)圖,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2019-10-10