当前时间

小学四则运算(升级版:生成小程序)

软件工程第二次作业

一、四则运算小程序要求

(1)能够自动生成四则运算练习题

(2)可以定制题目数量

(3)用户可以选择运算符

(4)用户设置最大数(如十以内、百以内等)

(5)用户选择是否有括号、是否有小数

(6)用户选择输出方式(如输出到文件、打印机等)

(7)生成小程序,即提供用户页面

二、代码地址

代码仓库地址:https://github.com/yyp-30/yyp/tree/master

exe文件地址:链接:https://pan.baidu.com/s/1QjMqBYJMSidJQYbLm5wA4g  提取码:gc4s

三、解决思路

首先,先建立一个合适的数据结构,用来表达四则运算这种算式。应该有数,算式符号和括号这些元素的具体值和位置等属性。我决定使用数组这个数据结构来存储这些信息。

其次,需要考虑如何生成这样一个描述算式的数据结构。需要先随机确定有几个数参与运算,然后根据给定的数的最大值确定具体每个数的大小。我们还需要随机确定每两个数之间的运算符号是什么。接着,我们应该随机确定应该有几个括号和括号的位置。

最后,根据符号的约束规则,随机生成这些符号和其位置。 最后,用一个函数,将生成好的数据结构信息,“翻译”为算式去展示。

 

四、具体代码

(1)生成运算式的类

# -*- coding: utf-8 -*-

"""

@File    :   Calculation.py

生成运算类

"""

import random

#  一个数据结构

class stru():


 def __init__(self):
    self.num_count = 0  # 数的个数

    self.num_result_count = 0

    self.num_arr = []  # 数的数组

    self.bra_arr = []  # 括号的数组

    self.brackets = 0  # 括号的数目

    self.sym = []  # 符号的数组

    self.sym_arr = []  # 符号的存储

    self.sym_count = 0  # 符号的数目

    self.result = 0


class ger():


 def gen_que(self, count, max_num, dec, sym, bra, fileout, num_cal_count):
    '''

    :param count:要出的题目数

    :param max_num:最大数

    :param dec:是否有小数

    :param sym:运算符号

    :param bra:是否有括号

    :param fileout:输出方式

    :param num_cal_count:最多几个数运算

    :return:

    '''

    result = ""

    mystru = stru()  # 实例化一个stru类

    for i in range(count):

        mystru.__init__()

        mystru.num_count = random.randint(2, num_cal_count)

        mystru.num_result_count = mystru.num_count

        mystru.sym = sym

        mystru.sym_count = mystru.num_count - 1

        if dec:  # 有小数的情况下

            for i in range(mystru.num_count):

                if random.randint(0, 1):

                    mystru.num_arr.append(round(random.uniform(1, max_num), 1))  # 取一位精度

                else:

                    mystru.num_arr.append(random.randint(1, max_num))

        else:  # 整数情况

            for i in range(mystru.num_count):
                mystru.num_arr.append(random.randint(1, max_num))

        for i in range(mystru.sym_count):  # 生成运算符号

            mystru.sym_arr.append(random.choice(sym))

        if bra:  # 生成括号

            self.genet_bra(mystru)

        result = result + self.print_que(mystru) + "\n"

        # print(self.print_que(mystru) + str(mystru.bra_arr) + "\n")

    return result


def print_que(self, stru):
    """

    根据stru生成一个算式,stru中有必要的原料

    :param stru:输入一个算式结构

    :return:str

    """

    que = ""

    for i in range(stru.num_count + 1):

        if i == 0 and (self.judege_bra(stru, 1, 0)):

            que = que + "(" * self.judege_bra(stru, 1, 0) + str(stru.num_arr[0])

        elif i == 0 and (not self.judege_bra(stru, 1, 0)):

            que = que + str(stru.num_arr[0])

        elif i == stru.num_count and (self.judege_bra(stru, stru.num_count, 1)):

            que = que + ")" * self.judege_bra(stru, stru.num_count, 1) + "="

        elif i == stru.num_count and (not self.judege_bra(stru, stru.num_count, 1)):

            que = que + "="

        else:

            if self.judege_bra(stru, i, 1):
                que = que + ")" * self.judege_bra(stru, i, 1)

            que = que + stru.sym_arr[i - 1]

            if self.judege_bra(stru, i + 1, 0):
                que = que + "(" * self.judege_bra(stru, i + 1, 0)

            que = que + str(stru.num_arr[i])

    return que


def judege_bra(self, stru, posi, left_right):
    """

    判断括号是否存在

    :param stru:

    :param posi:

    :param left_right:位于一个数的左边0,还是右边1

    :return:int 代表出现了几次

    """

    count = 0

    for i in range(stru.brackets):

        if stru.bra_arr[i][left_right] == posi:
            count = count + 1

    return count


def genet_bra(self, stru):
    """

    生成括号数组

    :param stru:输入一个stru结构

    :return:

    """

    brackets = stru.num_count - 2

    stru.brackets = random.randint(0, brackets)  # 括号数目

    while True:

        stru.bra_arr = []

        for i in range(stru.brackets):

            while True:

                temp_list = random.sample([j for j in range(1, stru.num_count + 1)], 2)  # 随机选两个数作为括号

                temp_list.sort()  # 对列表排序

                if (temp_list[0] == 1) and (temp_list[1] == stru.num_count):  # 括号无意义

                    continue

                elif self.list_repeat(stru.bra_arr, temp_list):  # 括号查重

                    continue

                else:

                    stru.bra_arr.append(temp_list)

                    break

        if self.jude_bra_valid(stru):
            break


def list_repeat(self, list1, list2):
    """

    括号去重

    :param list1:stru中的括号数组

    :param list2:

    :return:

    """

    for i in range(len(list1)):

        if (list1[i][0] == list2[0]) and (list1[i][1] == list2[1]):
            return True

        if (list1[i][1] == list2[0]) or (list1[i][0] == list2[1]):
            return True

    return False


def jude_bra_valid(self, stru):
    """

    判定括号是否合法

    :param stru:

    :return:bool

    """

    if stru.brackets == 1:

        return True

    else:

        stru.bra_arr.sort(key=self.get_list_subtract)  # 对数组排序

        stru.bra_arr.sort(key=self.get_list_fir)  # 再次排序

        for i in range(stru.brackets - 1):

            for j in range(i + 1, stru.brackets):

                if (stru.bra_arr[i][1] > stru.bra_arr[j][0]) and (

                        stru.bra_arr[i][0] < stru.bra_arr[j][0]) and (

                        stru.bra_arr[i][1] < stru.bra_arr[j][1]):
                    return False

        return True


def get_list_subtract(self, lst):
    """

    返回数组中第二个和第一个的差

    :param lst:

    :return:

    """

    return lst[1] - lst[0]


def get_list_fir(self, lst):
    """

    返回数组中的第一个值

    :param lst:

    :return:

    """

    return lst[0]

(2)主控程序类

# -*- coding: utf-8 -*-

"""

@File    :   deal.py

主控程序类
"""

from PyQt5 import QtCore, QtGui, QtWidgets

from untitled import Ui_MainWindow


from child import Ui_Dialog

from PyQt5.QtWidgets import QMessageBox

import sys

from Calculation import ger




class Mywindow(QtWidgets.QMainWindow, Ui_MainWindow):

    def __init__(self):

        """

        完成GUI初始化工作,绑定槽

        """

        super(Mywindow, self).__init__()

        self.setupUi(self)  # 初始化GUI控件

        self.horizontalSlider.valueChanged[int].connect(self.horizon_changeValue)

        self.horizontalSlider_2.valueChanged[int].connect(self.horizon2_changeValue)

        self.pushButton.clicked.connect(self.pushbutton_clich)

        self.child_dia = Mydialog()

    def pushbutton_clich(self):

        try:

            if self.check_inpue_valid():

                count = int(self.lineEdit_2.text())

                max_num = self.horizontalSlider.value()

                dec = self.checkBox.isChecked()

                bar = self.checkBox_2.isChecked()

                out = self.radioButton.isChecked()

                sym = self.get_sym()

                num_cal_count = self.horizontalSlider_2.value()

                mygerne = ger()  # 实例化一个ger对象

                pri_str = mygerne.gen_que(count, max_num, dec, sym, bar, out, num_cal_count)  # 调用生成算式的函数

                info.STR = pri_str

                if out:  # 输出到文件

                    self.fileout(pri_str)

                    QMessageBox.information(self, "提示信息", "已生产文件,文件名为‘que.txt’", QMessageBox.Yes)

                else:  # 屏幕显示

                    self.child_dia.set_textbro()

                    self.child_dia.exec_()

        except Exception as e:

            print(e)

    def fileout(self, t_str):

        with open("que.txt", "w", encoding="utf8") as f:
            f.write(t_str)

    #  检查输入是否合法

    def check_inpue_valid(self):

        if self.lineEdit_2.text() == '' or int(self.lineEdit_2.text()) == 0:
            QMessageBox.warning(self, "警告信息", "题目数量数据不合法", QMessageBox.Yes)

            return False

        if self.horizontalSlider.value() == 0:
            QMessageBox.warning(self, "警告信息", "最大数不合法", QMessageBox.Yes)

            return False

        if not self.get_sym():
            QMessageBox.warning(self, "警告信息", "至少选择一个运算法则", QMessageBox.Yes)

            return False

        return True

    # 获取选择的运算符

    def get_sym(self):

        sym_list = []

        if self.checkBox_3.isChecked():
            sym_list.append('+')

        if self.checkBox_4.isChecked():
            sym_list.append('÷')

        if self.checkBox_5.isChecked():
            sym_list.append('-')

        if self.checkBox_6.isChecked():
            sym_list.append('×')

        return sym_list

    def horizon_changeValue(self, value):

        self.label_3.setText(str(value))

    def horizon2_changeValue(self, value):

        self.label_5.setText(str(value))


#  子窗口

class Mydialog(QtWidgets.QDialog, Ui_Dialog):

    def __init__(self):
        super(Mydialog, self).__init__()

        self.setupUi(self)

    def set_textbro(self):
        self.textBrowser.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)

        # textBrowser要想正常显示水平滚动条,必须将lineWrapMode设置为nowrap

        self.textBrowser.setText(info.STR)  # 设置文本浏览器


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)

    myshow = Mywindow()

    myshow.show()

    sys.exit(app.exec_())

五、结果显示

 

mainwindow窗体显示

 

 

题目窗口弹出:

 

 

 

 六、总结

 

PyQt5是基于图形程序框架Qt5的Python语言实现,由一组Python模块构成。

此作业是初次接触PyQt5,不太熟悉PyQt5的应用,应加强学习。

 

七、psp表格

 

 

psp
任务内容
计划完成需要的时间(min) 实际完成需要的时间(min)
Planning 计划 50 60
Estimate 估计这个任务需要多少时间,并规划大致工作步骤 20 30
Analysis 需求分析 (包括学习新技术) 60 90
Design 具体设计 50 60
Coding 具体编码 400 500
test
测试(自我测试,修改代码,提交修改)
200 250

Postmortem & Process

Improvement Plan

事后总结 ,并提出过程改进计划 30 50
Summary 合计 810 1040
posted on 2020-09-28 15:32  Y杨宇平  阅读(231)  评论(0编辑  收藏  举报