├── .gitattributes ├── Homework ├── Python--第1次平时作业.docx ├── Python--第2次平时作业.docx ├── Python--第3次平时作业.docx ├── Python--第4次平时作业.docx ├── 刘文晨-2018080901006-第一次平时作业.docx ├── 刘文晨-2018080901006-第三次平时作业.docx ├── 刘文晨-2018080901006-第二次平时作业.docx ├── 刘文晨-2018080910006-平时作业答题卡.pdf └── 平时作业答题卡.doc ├── Project ├── ExamSystem │ ├── .idea │ │ ├── .gitignore │ │ ├── ExamSystem.iml │ │ ├── inspectionProfiles │ │ │ ├── Project_Default.xml │ │ │ └── profiles_settings.xml │ │ ├── misc.xml │ │ └── modules.xml │ ├── AntiCheating.py │ ├── BackEnd.py │ ├── Config.py │ ├── FrontEnd.py │ ├── ProjectTree.py │ ├── ReadMe.md │ ├── __pycache__ │ │ ├── BackEnd.cpython-38.pyc │ │ ├── Config.cpython-38.pyc │ │ ├── final_back_end.cpython-38.pyc │ │ └── myConfig.cpython-38.pyc │ └── data │ │ ├── account_file.txt │ │ ├── alarm.mp3 │ │ ├── fail.png │ │ ├── great.png │ │ ├── music.mp3 │ │ ├── pass.png │ │ └── question.xlsx ├── 课程考核说明.pdf └── 课设报告 │ ├── 2018080901006-刘文晨-python课设报告.docx │ ├── 2018080901006-刘文晨-python课设报告.pdf │ ├── pic1.png │ ├── pic2.png │ └── pic3.png └── README.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /Homework/Python--第1次平时作业.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/Python--第1次平时作业.docx -------------------------------------------------------------------------------- /Homework/Python--第2次平时作业.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/Python--第2次平时作业.docx -------------------------------------------------------------------------------- /Homework/Python--第3次平时作业.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/Python--第3次平时作业.docx -------------------------------------------------------------------------------- /Homework/Python--第4次平时作业.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/Python--第4次平时作业.docx -------------------------------------------------------------------------------- /Homework/刘文晨-2018080901006-第一次平时作业.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/刘文晨-2018080901006-第一次平时作业.docx -------------------------------------------------------------------------------- /Homework/刘文晨-2018080901006-第三次平时作业.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/刘文晨-2018080901006-第三次平时作业.docx -------------------------------------------------------------------------------- /Homework/刘文晨-2018080901006-第二次平时作业.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/刘文晨-2018080901006-第二次平时作业.docx -------------------------------------------------------------------------------- /Homework/刘文晨-2018080910006-平时作业答题卡.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/刘文晨-2018080910006-平时作业答题卡.pdf -------------------------------------------------------------------------------- /Homework/平时作业答题卡.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Homework/平时作业答题卡.doc -------------------------------------------------------------------------------- /Project/ExamSystem/.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /shelf/ 3 | /workspace.xml 4 | -------------------------------------------------------------------------------- /Project/ExamSystem/.idea/ExamSystem.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 12 | -------------------------------------------------------------------------------- /Project/ExamSystem/.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | -------------------------------------------------------------------------------- /Project/ExamSystem/.idea/inspectionProfiles/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 6 | -------------------------------------------------------------------------------- /Project/ExamSystem/.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Project/ExamSystem/.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Project/ExamSystem/AntiCheating.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2021/1/20 18:34 3 | # @Author : UestcXiye 4 | # @File : AntiCheating.py 5 | # @Software: PyCharm 6 | 7 | import os 8 | import time 9 | import tkinter 10 | import threading 11 | import ctypes 12 | import psutil 13 | 14 | root = tkinter.Tk() 15 | 16 | root.title('防作弊演示') 17 | 18 | # 窗口初始大小和位置 19 | root.geometry('250x80+300+100') 20 | 21 | # 不允许改变窗口大小 22 | root.resizable(False, False) 23 | 24 | ban = tkinter.IntVar(root, 0) 25 | 26 | 27 | def funcBan(): 28 | while ban.get() == 1: 29 | # 强行关闭主流文本编辑器和网页浏览器 30 | for pid in psutil.pids(): 31 | try: 32 | p = psutil.Process(pid) 33 | exeName = os.path.basename(p.exe()).lower() 34 | if exeName in ('notepad.exe', 'winword.exe', 'wps.exe', 'wordpad.exe', 'iexplore.exe', 35 | 'chrome.exe', 'qqbrowser.exe', '360chrome.exe', '360se.exe', 36 | 'sogouexplorer.exe', 'firefox.exe', 'opera.exe', 'maxthon.exe', 37 | 'netscape.exe', 'baidubrowser.exe', '2345Explorer.exe'): 38 | p.kill() 39 | except: 40 | pass 41 | 42 | # 清空系统剪切板 43 | ctypes.windll.user32.OpenClipboard(None) 44 | ctypes.windll.user32.EmptyClipboard() 45 | ctypes.windll.user32.CloseClipboard() 46 | time.sleep(1) 47 | 48 | 49 | def start(): 50 | ban.set(1) 51 | t = threading.Thread(target=funcBan) 52 | t.start() 53 | 54 | 55 | buttonStart = tkinter.Button(root, text='开始考试', command=start) 56 | buttonStart.place(x=20, y=10, width=100, height=20) 57 | 58 | 59 | def stop(): 60 | ban.set(0) 61 | 62 | 63 | buttonStop = tkinter.Button(root, text='结束考试', command=stop) 64 | buttonStop.place(x=130, y=10, width=100, height=20) 65 | # 模拟用,开启考试模式以后,所有内容都不再允许复制 66 | entryMessage = tkinter.Entry(root) 67 | entryMessage.place(x=10, y=40, width=230, height=20) 68 | root.mainloop() 69 | -------------------------------------------------------------------------------- /Project/ExamSystem/BackEnd.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2021/1/20 20:12 3 | # @Author : UestcXiye 4 | # @File : BackEnd.py 5 | # @Software: PyCharm 6 | 7 | import pandas as pd 8 | import random 9 | from Config import * 10 | 11 | 12 | def checkAccount(filename) -> tuple: 13 | """ 检验用户是否存在,账号密码是否正确 """ 14 | path = getCurrentPath() + DataPath + filename 15 | fid = open(path, 'r+') 16 | accountList = [] 17 | userNameList, userPasswordList = [], [] 18 | line = fid.readlines() 19 | for child in line: 20 | # print('[Function checkAccount]: ' + child) 21 | # if not (line.startswith("@")): # 注释行开头为@ 22 | accountList.append(child.strip("\n").split('\t')) 23 | # print(accountList) 24 | for name, password in accountList: 25 | userNameList.append(name) 26 | userPasswordList.append(password) 27 | # print(userNameList) 28 | # print(userPasswordList) 29 | fid.close() 30 | return userNameList, userPasswordList 31 | 32 | 33 | def addUser(filename, userName: str, userPassword: str) -> int: 34 | """ 添加新用户,在用户名不重读的情况下才会调用 """ 35 | path = getCurrentPath() + DataPath + filename 36 | txtfile = open(path, 'a') 37 | data = '\n' + userName + '\t' + userPassword 38 | txtfile.write(data) 39 | txtfile.close() 40 | return 1 41 | 42 | 43 | class SingleChoiceSubject: 44 | 45 | def __init__(self): 46 | self.scorePer = 3 # 每道题的分值 47 | self.totalNum = 10 # 总共10道单选 48 | self.subjectList = {} # 存放所有题目信息 49 | self.path = getCurrentPath() + DataPath + 'question.xlsx' 50 | self.df = pd.read_excel(self.path, sheet_name='单选') 51 | self.tempList = [] # 存储一行信息 52 | self.randList = [] # 存储已经选用的题目,防止随机题目 53 | 54 | def generateRand(self): 55 | """ 产生随机题目序号 """ 56 | count = 0 57 | while count < self.totalNum: 58 | randCount = random.randint(0, 519) # 共520道单选题 59 | if randCount not in self.randList: 60 | self.randList.append(randCount) 61 | count = count + 1 62 | else: 63 | continue 64 | 65 | def getData(self): 66 | """ 获取题目,返回数据给前端 """ 67 | self.generateRand() 68 | count = 0 69 | for randCount in self.randList: 70 | # 还有记得,是不是要canvas上面分布这些按钮,然后随着canvas销毁而消失 71 | self.subjectList[count] = {} 72 | self.subjectList[count]['题目内容'] = self.df['题目内容'][randCount] 73 | self.subjectList[count]['A'] = self.df['A'][randCount] 74 | self.subjectList[count]['B'] = self.df['B'][randCount] 75 | self.subjectList[count]['C'] = self.df['C'][randCount] 76 | self.subjectList[count]['D'] = self.df['D'][randCount] 77 | self.subjectList[count]['参考答案'] = self.df['参考答案'][randCount] 78 | count = count + 1 79 | return self.subjectList 80 | 81 | 82 | class MultiChoiceSubject: 83 | 84 | def __init__(self): 85 | self.scorePer = 5 # 每道题的分值 86 | self.totalNum = 10 # 总共10道单选 87 | self.subjectList = {} # 存放所有题目信息 88 | self.path = getCurrentPath() + DataPath + 'question.xlsx' 89 | self.df = pd.read_excel(self.path, sheet_name='多选') 90 | self.randList = [] 91 | 92 | def generateRand(self): 93 | """ 产生随机题目序号 """ 94 | count = 0 95 | while count < self.totalNum: 96 | randCount = random.randint(0, 265) # 共520道单选题 97 | if randCount not in self.randList: 98 | self.randList.append(randCount) 99 | count = count + 1 100 | else: 101 | continue 102 | 103 | def getData(self): 104 | """ 获取题目,返回数据给前端 """ 105 | self.generateRand() 106 | count = 0 107 | for randCount in self.randList: 108 | # 还有记得,是不是要canvas上面分布这些按钮,然后随着canvas销毁而消失 109 | self.subjectList[count] = {} 110 | self.subjectList[count]['题目内容'] = self.df['题目内容'][randCount] 111 | self.subjectList[count]['A'] = self.df['A'][randCount] 112 | self.subjectList[count]['B'] = self.df['B'][randCount] 113 | self.subjectList[count]['C'] = self.df['C'][randCount] 114 | self.subjectList[count]['D'] = self.df['D'][randCount] 115 | self.subjectList[count]['E'] = self.df['E'][randCount] 116 | self.subjectList[count]['参考答案'] = self.df['参考答案'][randCount] 117 | count = count + 1 118 | return self.subjectList 119 | 120 | 121 | class JudgeSubject: 122 | 123 | def __init__(self): 124 | self.scorePer = 2 # 每道题的分值 125 | self.totalNum = 10 # 总共10道单选 126 | self.subjectList = {} # 存放所有题目信息 127 | self.path = getCurrentPath() + DataPath + 'question.xlsx' 128 | self.df = pd.read_excel(self.path, sheet_name='判断') 129 | self.randList = [] 130 | 131 | def generateRand(self): 132 | """ 产生随机题目序号 """ 133 | count = 0 134 | while count < self.totalNum: 135 | randCount = random.randint(0, 362) # 共520道单选题 136 | if randCount not in self.randList: 137 | self.randList.append(randCount) 138 | count = count + 1 139 | else: 140 | continue 141 | 142 | def getData(self): 143 | """ 获取题目,返回数据给前端 """ 144 | self.generateRand() 145 | count = 0 146 | for randCount in self.randList: 147 | self.subjectList[count] = {} 148 | self.subjectList[count]['题目内容'] = self.df['题目内容'][randCount] 149 | self.subjectList[count]['参考答案'] = self.df['参考答案'][randCount] 150 | count = count + 1 151 | return self.subjectList 152 | 153 | 154 | class BackEnd: 155 | """ 与前端的数据接口 """ 156 | 157 | def __init__(self): 158 | self.Single = SingleChoiceSubject() 159 | self.Multi = MultiChoiceSubject() 160 | self.Judge = JudgeSubject() 161 | self.SingleList = self.Single.getData() 162 | self.MultiList = self.Multi.getData() 163 | self.JudgeList = self.Judge.getData() 164 | 165 | def test(self): 166 | print("SingleList:", self.SingleList) 167 | print("MultiList:", self.MultiList) 168 | print("JudgeList:", self.JudgeList) 169 | 170 | 171 | if __name__ == '__main__': 172 | test = BackEnd() 173 | test.test() 174 | print(test.SingleList[0]['A']) 175 | print(test.MultiList[2]['参考答案']) 176 | print(test.JudgeList[9]['题目内容']) 177 | print(type(test.MultiList[2]['参考答案'])) 178 | print(test.SingleList[2]['参考答案']) 179 | if test.SingleList[2]['参考答案'] == 'A': 180 | print('aaaa') 181 | if test.SingleList[2]['参考答案'] == 'B': 182 | print('bb') 183 | if test.SingleList[2]['参考答案'] == 'C': 184 | print('cc') 185 | if test.SingleList[2]['参考答案'] == 'D': 186 | print('dd') 187 | -------------------------------------------------------------------------------- /Project/ExamSystem/Config.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2021/1/20 20:23 3 | # @Author : UestcXiye 4 | # @File : Config.py 5 | # @Software: PyCharm 6 | 7 | import os 8 | 9 | DataPath = '\\' + 'data' + '\\' 10 | 11 | STATE_INIT = 1 12 | STATE_SINGLE = 2 13 | STATE_MULTI = 3 14 | STATE_JUDGE = 4 15 | STATE_DONE = 5 16 | 17 | 18 | def getCurrentPath(): 19 | """ 获取当前路径,找寻用户信息表和题库 """ 20 | path = os.getcwd() # 当前工作路径 21 | # path = os.path.abspath('..') #当前工作目录的父目录路径 22 | return path 23 | 24 | 25 | def list2str(changList) -> str: 26 | """ 为tkinter的varString显示处理准备,可以显示考生选择的选项 """ 27 | res = '' 28 | for index in range(len(changList)): 29 | res = res + str(changList[index]) 30 | return res 31 | 32 | 33 | if __name__ == '__main__': 34 | from pil import Image, ImageTk 35 | 36 | pilImage = Image.open(getCurrentPath() + DataPath + "fail.png") 37 | img = pilImage.resize((600, 500), Image.ANTIALIAS) 38 | tkImage = ImageTk.PhotoImage(image=img) 39 | print(pilImage[0]) 40 | -------------------------------------------------------------------------------- /Project/ExamSystem/FrontEnd.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2021/1/20 19:55 3 | # @Author : UestcXiye 4 | # @File : FrontEnd.py 5 | # @Software: PyCharm 6 | 7 | import tkinter as tk 8 | from tkinter import messagebox 9 | from tkinter import scrolledtext 10 | from threading import Timer 11 | from playsound import playsound 12 | from BackEnd import BackEnd, checkAccount, addUser 13 | from Config import * 14 | from pil import Image, ImageTk 15 | 16 | dataList = BackEnd() # 存储得到的考题 17 | 18 | for i in range(5): 19 | print(dataList.SingleList[i]['参考答案']) 20 | im = [] # 读取文件 21 | img = [] # 转换格式后 22 | 23 | for i in range(5): # 初始化读取的图片列表 24 | im.append(None) 25 | img.append(None) 26 | 27 | 28 | class FrontEnd: 29 | """ 前端类,完成注册和答题两个界面和数据调用 """ 30 | 31 | def __init__(self): 32 | self.state = STATE_INIT # 有限状态机,完成题目衔接和变化 33 | self.count = 0 # 计数到第几道题了 34 | self.minute = 60 35 | self.second = 0 # 设定考试时间60min 36 | self.ans = [] # 存放考生的结果,确认后判断 37 | self.score = 0 # 分数 38 | self.loginWindow = tk.Tk() 39 | self.initialLoginWindow(self.loginWindow) 40 | 41 | def initialLoginWindow(self, loginWindow): 42 | """for login""" 43 | loginWindow['bg'] = 'skyblue' # background color 44 | loginWindow.title('考试系统登陆界面') 45 | loginWindow.resizable(width=True, height=True) 46 | 47 | width = loginWindow.winfo_screenwidth() 48 | height = loginWindow.winfo_screenheight() 49 | loginWindow.geometry( 50 | "400x200+%d+%d" % 51 | (width / 2 - 200, height / 2 - 200)) 52 | 53 | self.varAccount = tk.StringVar() 54 | self.varAccount.set('') 55 | self.varKey = tk.StringVar() 56 | self.varKey.set('') 57 | 58 | # 创建标签 59 | self.labelAccount = tk.Label( 60 | loginWindow, 61 | text='用户名:', 62 | justify=tk.RIGHT, 63 | width=80) 64 | self.labelKey = tk.Label( 65 | loginWindow, 66 | text='密 码:', 67 | justify=tk.RIGHT, 68 | width=80) 69 | self.labelRegister = tk.Label( 70 | loginWindow, text='注 册', justify=tk.RIGHT, width=80) 71 | 72 | # 将标签放到窗口上 73 | self.labelAccount.place(x=20, y=10, width=160, height=40) 74 | self.labelKey.place(x=20, y=60, width=160, height=40) 75 | 76 | # 创建账号文本框,同时设置关联的变量 77 | self.account = tk.Entry( 78 | loginWindow, 79 | width=80, 80 | textvariable=self.varAccount) 81 | self.account.place(x=200, y=10, width=160, height=40) 82 | # 创建密码文本框 83 | self.key = tk.Entry( 84 | loginWindow, 85 | show='*', 86 | width=80, 87 | textvariable=self.varKey) 88 | self.key.place(x=200, y=60, width=160, height=40) 89 | 90 | # 创建按钮组件,同时设置按钮事件处理函数 91 | buttonOk = tk.Button(loginWindow, text='登录', command=self.login) 92 | buttonOk.place(x=20, y=140, width=100, height=40) 93 | buttonCancel = tk.Button( 94 | loginWindow, 95 | text='取消', 96 | command=self.cancelLogin) 97 | buttonCancel.place(x=140, y=140, width=100, height=40) 98 | buttonRegister = tk.Button(loginWindow, text='注册', command=self.regist) 99 | buttonRegister.place(x=260, y=140, width=100, height=40) 100 | 101 | # make Esc exit the program 102 | loginWindow.bind('', lambda e: loginWindow.destroy()) 103 | # 启动消息循环 104 | loginWindow.mainloop() 105 | 106 | def login(self): 107 | """ 获取用户名和密码 """ 108 | name = self.account.get() 109 | passwd = self.key.get() 110 | 111 | nameList, passwordList = checkAccount('account_file.txt') 112 | # for test 113 | for i in range(len(nameList)): 114 | if name == nameList[i]: 115 | if passwd == passwordList[i]: 116 | tk.messagebox.showinfo(title='提示', message='登录成功!') 117 | self.loginWindow.destroy() 118 | self.mainWindow = tk.Tk() 119 | self.initialMainWindow(self.mainWindow) 120 | return 121 | tk.messagebox.showerror('Python tk', message='账号或密码错误!') 122 | 123 | def cancelLogin(self): 124 | """ 清空用户输入的用户名和密码 """ 125 | self.varAccount.set('') 126 | self.varKey.set('') 127 | 128 | def regist(self): 129 | name = self.account.get() 130 | passwd = self.key.get() 131 | userNameList, userPasswordList = checkAccount('account_file.txt') 132 | if not userNameList or not userPasswordList: 133 | addUser('account_file.txt', name, passwd) 134 | return 135 | for userName in userNameList: 136 | if name == userName: 137 | tk.messagebox.showerror('Python tk', message='已有该用户名!') 138 | registerSuccessful = addUser('account_file.txt', name, passwd) 139 | if registerSuccessful: 140 | messagebox.showinfo('提示信息', message='注册成功!') 141 | 142 | def initialMainWindow(self, mainWindow): 143 | """ initialize window and the window settings""" 144 | self.width = mainWindow.winfo_screenwidth() 145 | self.height = mainWindow.winfo_screenheight() 146 | 147 | print('[Function: initialMainWindow]') 148 | mainWindow.geometry("%dx%d" % (self.width, self.height)) 149 | mainWindow['bg'] = 'skyblue' # background color 150 | mainWindow.title('考试系统答题界面') 151 | mainWindow.resizable(width=True, height=True) 152 | 153 | mainWindow.protocol('WM_DELETE_WINDOW', self.closeMainWindow) 154 | self.setMenu(mainWindow) 155 | # make Esc exit the program 156 | mainWindow.bind('', lambda e: mainWindow.destroy()) 157 | 158 | self.totalCount = dataList.Single.totalNum + \ 159 | dataList.Multi.totalNum + dataList.Judge.totalNum 160 | 161 | self.showInitFsm() 162 | self.watchDog() 163 | mainWindow.mainloop() 164 | 165 | def showInitFsm(self): 166 | nextState = STATE_SINGLE 167 | print('[Function: Init_fsm] startup') 168 | 169 | self.varScore = tk.StringVar() # 已获得分数 170 | self.varScore.set(str(self.score) + '\100') 171 | self.showScoreName = tk.Label(self.mainWindow, 172 | text='已获得分数: ', 173 | width=150, # 设置label的宽度:30 174 | height=50, # 设置label的高度:10 175 | justify='left', # 设置文本对齐方式:左对齐 176 | anchor='nw', # 设置文本在label的方位:西北方位 177 | font=('微软雅黑', 18), # 设置字体:微软雅黑,字号:18 178 | fg='white', # 设置前景色:白色 179 | bg='grey', # 设置背景色:灰色 180 | ) 181 | self.showScoreName.place(x=10, y=10, width=150, height=50) 182 | self.showScore = tk.Label(self.mainWindow, textvariable=self.varScore) 183 | self.showScore.place(x=10, y=70, width=150, height=50) 184 | self.varTimeLft = tk.StringVar() 185 | # self.varTimeLft.set(str(min) + '分' + str(sec) + '秒') 186 | self.timeLeft = tk.Label(self.mainWindow, textvariable=self.varTimeLft) 187 | self.timeLeft.place(x=self.width - 200, y=70, width=150, height=50) 188 | 189 | # 剩余时间见函数 watchDog 190 | # self.watchDog(10, 00) # 考试时间10min 191 | 192 | self.showTimeLeft = tk.Label(self.mainWindow, text='剩余时间', # 设置文本内容 193 | width=150, # 设置label的宽度:30 194 | height=50, # 设置label的高度:10 195 | justify='left', # 设置文本对齐方式:左对齐 196 | anchor='ne', # 设置文本在label的方位:西北方位 197 | font=('微软雅黑', 18), # 设置字体:微软雅黑,字号:18 198 | fg='white', # 设置前景色:白色 199 | bg='grey', # 设置背景色:灰色 200 | padx=20, # 设置x方向内边距:20 201 | pady=10) # 设置y方向内边距:10 202 | self.showTimeLeft.place(x=self.width - 200, y=10, width=150, height=60) 203 | 204 | self.varButtonA = tk.StringVar() 205 | self.varButtonA.set( 206 | 'A. ' + str(dataList.SingleList[self.count % 10]['A'])) 207 | self.varButtonB = tk.StringVar() 208 | self.varButtonB.set( 209 | 'B. ' + str(dataList.SingleList[self.count % 10]['B'])) 210 | self.varButtonC = tk.StringVar() 211 | self.varButtonC.set( 212 | 'C. ' + str(dataList.SingleList[self.count % 10]['C'])) 213 | self.varButtonD = tk.StringVar() 214 | self.varButtonD.set( 215 | 'D. ' + str(dataList.SingleList[self.count % 10]['D'])) 216 | self.varButtonE = tk.StringVar() 217 | self.varButtonE.set('') 218 | 219 | self.buttonA = tk.Button(self.mainWindow, 220 | textvariable=self.varButtonA, 221 | command=self.buttonAFsm) 222 | self.buttonB = tk.Button(self.mainWindow, 223 | textvariable=self.varButtonB, 224 | command=self.buttonBFsm) 225 | self.buttonC = tk.Button(self.mainWindow, 226 | textvariable=self.varButtonC, 227 | command=self.buttonCFsm) 228 | self.buttonD = tk.Button(self.mainWindow, 229 | textvariable=self.varButtonD, 230 | command=self.buttonDFsm) 231 | self.buttonOK = tk.Button(self.mainWindow, 232 | text='确认', 233 | command=self.buttonOKFsm) # 确认按钮,确认不再更改答案 234 | self.buttonA.place(x=100, y=400, width=750, height=50) 235 | self.buttonB.place(x=100, y=500, width=750, height=50) 236 | self.buttonC.place(x=100, y=600, width=750, height=50) 237 | self.buttonD.place(x=100, y=700, width=750, height=50) 238 | self.buttonOK.place(x=1000, y=400, width=300, height=50) 239 | 240 | self.varChoice = tk.StringVar() 241 | self.varChoice.set(list2str(self.ans)) # 显示考生选择的选项 242 | self.showChoice = tk.Label( 243 | self.mainWindow, textvariable=self.varChoice) 244 | self.showChoice.place(x=1000, y=600, width=150, height=50) 245 | self.subject = scrolledtext.ScrolledText( 246 | self.mainWindow, relief="solid") 247 | self.subject.place(x=self.width / 3, y=10) 248 | self.subject.insert('end', str(self.count + 1) + '. ' + 249 | dataList.SingleList[self.count]['题目内容'] + '\n') 250 | 251 | self.count = 0 252 | print('[Function: Init_fsm] complicated') 253 | self.state = nextState 254 | 255 | def buttonAFsm(self): 256 | print(' [Event: buttonA clicked]') 257 | if self.state == STATE_SINGLE: # 单选 258 | self.ans = [] 259 | self.ans.append('A') 260 | elif self.state == STATE_MULTI: # 多选 261 | if 'A' not in self.ans: 262 | self.ans.append('A') 263 | self.ans = sorted(self.ans) 264 | else: 265 | self.ans.remove('A') 266 | else: # 判断题 267 | self.ans = [] 268 | self.ans.append('对') 269 | self.varChoice.set(list2str(self.ans)) 270 | 271 | def buttonBFsm(self): 272 | print(' [Event: buttonB clicked]') 273 | if self.state == STATE_SINGLE: # 单选 274 | self.ans = [] 275 | self.ans.append('B') 276 | elif self.state == STATE_MULTI: # 多选 277 | if 'B' not in self.ans: 278 | self.ans.append('B') 279 | self.ans = sorted(self.ans) 280 | else: 281 | self.ans.remove('B') 282 | sorted(self.ans) 283 | else: 284 | self.ans = [] 285 | self.ans.append('对') 286 | self.varChoice.set(list2str(self.ans)) 287 | 288 | def buttonCFsm(self): 289 | print(' [Event: buttonC clicked]') 290 | if self.state == STATE_SINGLE: # 单选 291 | self.ans = [] 292 | self.ans.append('C') 293 | elif self.state == STATE_MULTI: # 多选 294 | if 'C' not in self.ans: 295 | self.ans.append('C') 296 | self.ans = sorted(self.ans) 297 | else: 298 | self.ans.remove('C') 299 | sorted(self.ans) 300 | else: # 判断 301 | self.ans = [] 302 | self.ans.append('错') 303 | self.varChoice.set(list2str(self.ans)) 304 | 305 | def buttonDFsm(self): 306 | print(' [Event: buttonD clicked]') 307 | if self.state == STATE_SINGLE: # 单选 308 | self.ans = [] 309 | self.ans.append('D') 310 | elif self.state == STATE_MULTI: # 多选 311 | if 'D' not in self.ans: 312 | self.ans.append('D') 313 | self.ans = sorted(self.ans) 314 | else: 315 | self.ans.remove('D') 316 | sorted(self.ans) 317 | else: # 判断 318 | self.ans = [] 319 | self.ans.append('错') 320 | self.varChoice.set(list2str(self.ans)) 321 | 322 | def buttonEFsm(self): 323 | print(' [Event: buttonE clicked]') 324 | if self.state == STATE_SINGLE: # 单选 325 | self.ans = [] 326 | self.ans.append('E') 327 | elif self.state == STATE_MULTI: # 多选 328 | if 'E' not in self.ans: 329 | self.ans.append('E') 330 | self.ans = sorted(self.ans) 331 | else: 332 | self.ans.remove('E') 333 | sorted(self.ans) 334 | else: # 判断 335 | self.ans = [] 336 | self.ans.append('错') 337 | self.varChoice.set(list2str(self.ans)) 338 | 339 | def buttonOKFsm(self): 340 | """ 确认按钮,点击后进入下一状态 """ 341 | print(' [Event: buttonOK clicked]') 342 | 343 | self.score += self.checkAns() 344 | self.varScore.set(str(self.score) + '/100') # 显示得分 345 | 346 | self.count = self.count + 1 # 下一题 347 | self.varChoice.set('') # 清空显示的考生选项,准备下一题 348 | 349 | self.ans = [] # 清空内部存储的考生选项,准备下一题 350 | if self.state == STATE_SINGLE: 351 | self.showSingleFsm() 352 | elif self.state == STATE_MULTI: 353 | self.showMultiFsm() 354 | elif self.state == STATE_JUDGE: 355 | self.showJudgeFsm() 356 | else: # 结束,分数不再变动 357 | self.showDoneFsm() 358 | 359 | def checkAns(self) -> int: 360 | """ 检查结果,返回本题得分 """ 361 | if self.state == STATE_SINGLE: 362 | print(' [Debug: your choice:] ' + str(self.ans)) 363 | if list2str( 364 | self.ans) == dataList.SingleList[self.count % 10]['参考答案']: 365 | # self.score = self.score + 3 # 本题得分 366 | return 3 367 | else: 368 | return 0 369 | elif self.state == STATE_MULTI: 370 | print(' [Debug: your choice:] ' + str(self.ans)) 371 | if list2str( 372 | self.ans) == dataList.MultiList[self.count % 10]['参考答案']: 373 | # self.score += 5 # 本题得分 374 | return 5 375 | else: 376 | return 0 377 | else: 378 | print(' [Debug: your choice:] ' + str(self.ans)) 379 | if list2str( 380 | self.ans) == dataList.JudgeList[self.count % 10]['参考答案']: 381 | # self.score += 2 # 本题得分 382 | return 2 383 | else: 384 | return 0 385 | 386 | def updateSubject(self, listName): 387 | self.subject.delete(0.0, tk.END) 388 | self.subject.insert('end', str(self.count + 1) + '. ' + 389 | listName[self.count % 10]['题目内容'] + '\n') 390 | self.varButtonA.set( 391 | 'A. ' + str(listName[self.count % 10]['A'])) 392 | self.varButtonB.set( 393 | 'B. ' + str(listName[self.count % 10]['B'])) 394 | self.varButtonC.set( 395 | 'C. ' + str(listName[self.count % 10]['C'])) 396 | self.varButtonD.set( 397 | 'D. ' + str(listName[self.count % 10]['D'])) 398 | if self.state == STATE_MULTI: 399 | self.varButtonE.set( 400 | 'E. ' + str(listName[self.count % 10]['E'])) 401 | 402 | def showSingleFsm(self): 403 | if self.count < self.totalCount / 3 - 1: 404 | nextState = STATE_SINGLE 405 | else: 406 | nextState = STATE_MULTI 407 | self.buttonE = tk.Button(self.mainWindow, 408 | textvariable=self.varButtonE, 409 | command=self.buttonEFsm) 410 | self.buttonA.place(x=100, y=400, width=750, height=50) 411 | self.buttonB.place(x=100, y=480, width=750, height=50) 412 | self.buttonC.place(x=100, y=560, width=750, height=50) 413 | self.buttonD.place(x=100, y=640, width=750, height=50) 414 | self.buttonE.place(x=100, y=720, width=750, height=50) 415 | 416 | self.updateSubject(dataList.SingleList) 417 | 418 | self.state = nextState 419 | 420 | def showMultiFsm(self): 421 | if self.totalCount / 3 <= self.count < 2 * self.totalCount / 3: 422 | nextState = STATE_MULTI 423 | else: 424 | nextState = STATE_JUDGE 425 | self.buttonA.destroy() 426 | self.buttonB.destroy() 427 | self.buttonC.destroy() 428 | self.buttonD.destroy() 429 | self.buttonE.destroy() 430 | self.buttonTrue = tk.Button(self.mainWindow, 431 | text='对', 432 | command=self.buttonAFsm) 433 | self.buttonFalse = tk.Button(self.mainWindow, 434 | text='错', 435 | command=self.buttonEFsm) 436 | self.buttonTrue.place(x=100, y=400, width=750, height=50) 437 | self.buttonFalse.place(x=100, y=600, width=750, height=50) 438 | 439 | self.updateSubject(dataList.MultiList) # 刷新题目和选项 440 | 441 | self.state = nextState 442 | 443 | def showJudgeFsm(self): 444 | print('total count: ', self.totalCount) 445 | if self.count < self.totalCount: 446 | nextState = STATE_JUDGE 447 | else: 448 | nextState = STATE_DONE 449 | 450 | self.subject.delete(0.0, tk.END) # 清空上一题 451 | self.subject.insert('end', str(self.count + 1) + '. ' + 452 | dataList.JudgeList[self.count % 10]['题目内容'] + '\n') 453 | 454 | self.state = nextState 455 | 456 | def showDoneFsm(self): 457 | """ 结束状态 """ 458 | 459 | # 清除所有无用控件 460 | self.buttonTrue.destroy() 461 | self.buttonFalse.destroy() 462 | self.buttonOK.destroy() 463 | self.showChoice.destroy() 464 | self.subject.destroy() 465 | 466 | # 播放音乐 467 | playsound(getCurrentPath() + DataPath + 'music.mp3', block=False) 468 | 469 | # 计时结束,清零 470 | self.timeCount.cancel() 471 | # self.varTimeLft.set('0:00') 472 | self.showScoreName = tk.Label(self.mainWindow, 473 | text='最终得分: ', 474 | width=150, # 设置label的宽度:30 475 | height=50, # 设置label的高度:10 476 | justify='left', # 设置文本对齐方式:左对齐 477 | anchor='nw', # 设置文本在label的方位:西北方位 478 | font=('微软雅黑', 18), # 设置字体:微软雅黑,字号:18 479 | fg='white', # 设置前景色:白色 480 | bg='grey', # 设置背景色:灰色 481 | ) 482 | self.showScoreName.place(x=10, y=10, width=150, height=50) 483 | # 加载图像 484 | global im 485 | global img 486 | 487 | if self.score < 60: 488 | im[0] = Image.open(getCurrentPath() + DataPath + "fail.png") 489 | img[0] = ImageTk.PhotoImage(im[0]) 490 | imLabel = tk.Label(self.mainWindow, image=img[0]).pack() 491 | elif 60 <= self.score <= 85: 492 | im[1] = Image.open(getCurrentPath() + DataPath + "pass.png") 493 | img[1] = ImageTk.PhotoImage(im[1]) 494 | imLabel = tk.Label(self.mainWindow, image=img[1]).pack() 495 | else: 496 | im[2] = Image.open(getCurrentPath() + DataPath + "great.png") 497 | img[2] = ImageTk.PhotoImage(im[2]) 498 | imLabel = tk.Label(self.mainWindow, image=img[2]).pack() 499 | 500 | def setMenu(self, window): 501 | """create a menu bar with Exit command and version info""" 502 | menubar = tk.Menu(window) 503 | filemenu = tk.Menu(menubar, tearoff=0) 504 | filemenu.add_command(label="Exit", command=window.destroy) 505 | infoMenu = tk.Menu(menubar, tearoff=0) 506 | infoMenu.add_command(label="Version Info", command=self.menuInfo) 507 | menubar.add_cascade(label="File", menu=filemenu) 508 | menubar.add_cascade(label="Info", menu=infoMenu) 509 | window.config(menu=menubar) 510 | 511 | def menuInfo(self): 512 | messagebox.showinfo( 513 | 'info', 514 | 'Created By UestcXiye \n version 1.0') 515 | 516 | def watchDog(self): 517 | """ 定时程序,考试时间最多一小时,结束终止答题,显示分数,播放音乐 """ 518 | timeLeft = 60 * self.minute + self.second 519 | timeLeft -= 1 520 | self.second = self.second - 1 521 | if self.second < 0: 522 | self.minute = self.minute - 1 523 | self.second = 59 524 | if self.minute < 0 or timeLeft == 0: 525 | self.state = STATE_DONE 526 | playsound( 527 | getCurrentPath() + DataPath + 'music.mp3', 528 | block=False 529 | ) # 倒计时结束,播放提示音乐。 530 | self.showDoneFsm() 531 | self.varTimeLft.set(str(self.minute) + ':' + str(self.second)) 532 | self.timeCount = Timer(1, self.watchDog, ()) 533 | self.timeCount.start() # 计时器启动 534 | 535 | def closeMainWindow(self): 536 | """ to check if you really wanna exit """ 537 | ans = messagebox.askyesno(title='Quit', message='要关闭窗口吗?您所做的修改不会保存') 538 | if ans: 539 | self.mainWindow.destroy() 540 | else: 541 | pass 542 | 543 | 544 | if __name__ == '__main__': 545 | test = FrontEnd() 546 | -------------------------------------------------------------------------------- /Project/ExamSystem/ProjectTree.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # @Time : 2021/1/20 21:01 3 | # @Author : UestcXiye 4 | # @File : ProjectTree.py 5 | # @Software: PyCharm 6 | 7 | from pathlib import Path 8 | 9 | tree_str = '' 10 | 11 | 12 | def generate_tree(pathname, n=0): 13 | """ 产生项目结构树图 """ 14 | global tree_str 15 | if pathname.is_file(): 16 | tree_str += ' |' * n + '-' * 4 + pathname.name + '\n' 17 | elif pathname.is_dir(): 18 | tree_str += ' |' * n + '-' * 4 + \ 19 | str(pathname.relative_to(pathname.parent)) + '\\' + '\n' 20 | for cp in pathname.iterdir(): 21 | generate_tree(cp, n + 1) 22 | 23 | 24 | if __name__ == '__main__': 25 | generate_tree(Path.cwd()) 26 | print(tree_str) 27 | -------------------------------------------------------------------------------- /Project/ExamSystem/ReadMe.md: -------------------------------------------------------------------------------- 1 | # 项目简介 2 | 3 | python语言程序设计期末课程设计: 4 | 5 | 用Python语言编程实现自动组卷评卷考试系统,软件主要功能包括: 6 | 从题库中随机抽取试题自动组成试卷(满分100分);实现考生考试答题操作界面;实现自动阅卷评分功能;等等。 7 | 8 | 本项目完成:考试定时、自动组卷、客观题自动判卷、自动评分和考试界面设计。 9 | 10 | # 完成者 11 | 12 | 姓名:刘文晨 13 | 14 | 学号:2018080901006 15 | 16 | 学院:计算机科学与工程学院 17 | 18 | # 项目结构 19 | 20 | ```` 21 | ----ExamSystem\ 22 | |----data\ 23 | | |----account_file.txt 24 | | |----alarm.mp3 25 | | |----fail.png 26 | | |----great.png 27 | | |----pass.png 28 | | |----question.xlsx 29 | |----AntiCheating.py 30 | |----BackEnd.py 31 | |----Config.py 32 | |----FrontEnd.py 33 | |----ProjectTree.py 34 | |----ReadMe.md 35 | ```` 36 | 37 | # 功能特性 38 | 39 | ## 前端: 40 | 41 | 完成登录、注册功能核验考生身份,如果身份正确则进入考试界面,否则重新输入。 42 | 43 | 考试界面稍作等待得到随机分配的考题,开始答题。每道题完成后即时判卷打分,完成所有题目后显示总分:85分及以上为合格;否则为不合格。 44 | 45 | 考试开始即开始计时,超时自动结束考试,统计分数,播放音乐 46 | 47 | ## 后端: 48 | 49 | 为方便部署,采用文件读写而非数据库的方式存储信息和题库。 50 | 51 | 完成核验考生身份信息,题库自动组卷,按照前端需求进行传递。 52 | 53 | # 环境依赖 54 | 55 | Windows10 + Python 3.8 56 | 57 | # 使用与测试 58 | 59 | 文件目录需完整拖拽至本机,所有文件读写均会自动检测当前目录。 60 | 61 | 运行FrontEnd.py。 62 | 63 | 测试时需要登录,已有管理员账号admin,对应密码123456;测试账号test1和test2,密码和账号一样;以及调试用的空账号空密码,直接登录即可。 64 | 65 | 选择选项,选项右侧的文本框中会显示当前选项,按确认键完成本题。如果结果正确,左上角的分数会有变动。 66 | -------------------------------------------------------------------------------- /Project/ExamSystem/__pycache__/BackEnd.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/__pycache__/BackEnd.cpython-38.pyc -------------------------------------------------------------------------------- /Project/ExamSystem/__pycache__/Config.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/__pycache__/Config.cpython-38.pyc -------------------------------------------------------------------------------- /Project/ExamSystem/__pycache__/final_back_end.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/__pycache__/final_back_end.cpython-38.pyc -------------------------------------------------------------------------------- /Project/ExamSystem/__pycache__/myConfig.cpython-38.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/__pycache__/myConfig.cpython-38.pyc -------------------------------------------------------------------------------- /Project/ExamSystem/data/account_file.txt: -------------------------------------------------------------------------------- 1 | admin 123456 2 | test1 test1 3 | test2 test2 4 | -------------------------------------------------------------------------------- /Project/ExamSystem/data/alarm.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/data/alarm.mp3 -------------------------------------------------------------------------------- /Project/ExamSystem/data/fail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/data/fail.png -------------------------------------------------------------------------------- /Project/ExamSystem/data/great.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/data/great.png -------------------------------------------------------------------------------- /Project/ExamSystem/data/music.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/data/music.mp3 -------------------------------------------------------------------------------- /Project/ExamSystem/data/pass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/data/pass.png -------------------------------------------------------------------------------- /Project/ExamSystem/data/question.xlsx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/ExamSystem/data/question.xlsx -------------------------------------------------------------------------------- /Project/课程考核说明.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/课程考核说明.pdf -------------------------------------------------------------------------------- /Project/课设报告/2018080901006-刘文晨-python课设报告.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/课设报告/2018080901006-刘文晨-python课设报告.docx -------------------------------------------------------------------------------- /Project/课设报告/2018080901006-刘文晨-python课设报告.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/课设报告/2018080901006-刘文晨-python课设报告.pdf -------------------------------------------------------------------------------- /Project/课设报告/pic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/课设报告/pic1.png -------------------------------------------------------------------------------- /Project/课设报告/pic2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/课设报告/pic2.png -------------------------------------------------------------------------------- /Project/课设报告/pic3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/UestcXiye/Python-Language-Programming/e4e99516455098397d39cae34dcf99b150567140/Project/课设报告/pic3.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python-Language-Programming 2 | 电子科技大学2020年《Python语言程序设计》的平时作业和期末课设。 3 | 4 | 平时作业共4次,每次有25道编程题和100道单项选择题。 5 | 6 | 课设题目是自动组卷评卷考试系统。 7 | --------------------------------------------------------------------------------