结对项目-四则运算 “软件”之升级版

本次作业要求来自:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2232

我的github远程仓库的地址:https://github.com/codeforsome/proTwo

结对同伴的学号姓名:赖昱升 201606120083

结对同伴的博客地址:http://www.cnblogs.com/lys1894/

项目开发过程:

一、开发环境及调试的环境IntelliJ IDEA

二、项目的功能基本要求:

  • 生成题目,单个题目最多不能超过4个运算符,操作数小于100。
  • 用户可以输入答案
  • 若用户输入答案正确,则提示正确;若答案错误,则提示错误,并要提示正确答案是多少。

三、项目添加的4个方向:

  1. 程序可以出带括号的正整数四则运算,支持分数,除法保留两位小数;
  2. 可以出表达式里含有负整数(负整数最小不小于-100)的题目,且负数需要带括号,用户输入的结果不用带括号;
  3. 用户可以选择出题的个数(最多不能超过5个题目),答题结束可以显示用户答错的题目个数和答对的题目个数;
  4. 程序可以设置皮肤功能,可以改变界面的颜色即可。

四、项目的时间规划:

PSP2.1

Personal Software Process Stages

Time Senior Student

Time

(minute)

Planning

计划

8

9

· Estimate

估计这个任务需要多少时间

12

25

Development

开发

90

50

· Analysis

需求分析 (包括学习新技术)

20

30

· Design Spec

生成设计文档

0

0

· Design Review

设计复审

3

15

· Coding Standard

代码规范

0

10

· Design

具体设计

10

25

· Coding

具体编码

35

30

· Code Review

代码复审

10

25

· Test

测试(自我测试,修改代码,提交修改)

15

15

Reporting

报告

9

9

·

测试报告

0

0

·

计算工作量

5

5

·

并提出过程改进计划

0

0

五、项目的分工:

本次项目的规划中,本人做了代码的主要测试和编写,代码功能的构思和编写,程序的总体布局;

结对伙伴做了代码的部分测试和项目的改进提要求,并且对程序不好的代码和构思提出了质疑和进行了修改。

第一张为我,第二张是结对伙伴。

六、项目的感想:

本次项目因为涉及到参考界面,程序不再是通过控制台来输出信息,本项目是通过Java的swing来实现代码的功能和窗口,因为之前没有接触过swing,在通过短暂的学习之后用来解决问题,多少还是生疏,程序还有许多的不足之处,代码还是不够简洁有效率,会不断去重构和规划,使得程序容易阅读和修改。

七、项目的主要的运行截图:

1:题目的选择

2:背景颜色的选择:

3:题目的提示和输入:

 八、项目的代码:

package test;

import java.io.IOException;
import java.util.*;
//产生题目和答案的一个类
public class Exercises {
    public static void main(String[] args) {
    }
    private int minNumber=-100; //题目出现的最小数字
    private int maxNumber=100;  //题目出现的最大数字
    private int count=2;  //题目初始化的题目数量
    private String result=""; //题目的字符串量
    private  float resultNumber=0; //题目的正确答案
    //用来保存每一道题目和题目答案
    private Map<Integer, Result> exercisesMap=new HashMap<Integer, Result>();
    //用来保存要用到的运算符号
    private char operations[]=new char[]{'+','-','*','/'};
    //    该类用来保存结果的答案
    public class Result{
        public String result;
      public   float resultNumber;
    }
//获得题目数量
    public int getCount() {
        return count;
    }

    public Map<Integer, Result> getExercisesMap() {
        return exercisesMap;
    }

    public void setCount(int count) {
        this.count = count;
    }
//    获得随机数
    private int getRandomNumber(){
       return  (int)(minNumber+Math.random()*(maxNumber-minNumber+1));
    }
    private char getRandomOperation(){//获得随机运算符号
        int random=(int)(Math.random()*operations.length);
        return operations[random];
    }
//    计算四则结果
    private float getOperationResult(char operation,float x,float y){
        float result=0;
        switch (operation){
            case '+':
                result=x+y;
                break;
            case '-':
                result=x-y;
                break;
            case '*':
                result=x*y;
                break;
            case '/':
                result=x/y;
                break;
        }
        return result;
    }
    public void  arithmetic(){//每次产生一道题目
        int number[]=new int[3]; //运算数量
        char []operation=new char[2]; //符号数量
        while (true){
           for(int i=0;i<number.length;i++){
               number[i]=getRandomNumber(); //给变量赋值
           }
           operation[0]=getRandomOperation(); //给符号位赋值
           operation[1]=getRandomOperation();
           if(operation[0]=='*' || operation[0]=='/'){ //判断第一个是否为*,/ 是,则直接计算
              if(number[1]==0)continue;
               resultNumber=getOperationResult(operation[0],number[0],number[1]);
               if(operation[1]=='/' && number[2]==0)continue;
               resultNumber=getOperationResult(operation[1],resultNumber,number[2]);
          }else {
               //如果第一个符号位不是* ,/那就先算第二个数和三个数的值后,再与第一个值计算
              if(operation[1]=='/'&& number[2]==0)continue;
              if(operation[0]=='-'){
                  resultNumber=getOperationResult(operation[1],-number[1],number[2]);
                  operation[0]='+';
              }
              else{
                  resultNumber=getOperationResult(operation[1],number[1],number[2]);
                  operation[0]='-';
              }
               resultNumber=getOperationResult(operation[0],number[0],resultNumber);
          }
          break;
       }
        //              将数字和符号串联起来 作为输出题目的字符
        result=parseNumber(number[0])+operation[0]+parseNumber(number[1])
                +operation[1]+parseNumber(number[2])+"=";
//        resultNumber=
    }
//    转化负数带有中括号
    private String parseNumber(int number){
      return   number<0 ? "("+number+")" : number+"";
    }
    public  Map<Integer, Result> showArithmetic(){//产生题目,答案并保存和输出
        int countExercise=0;
        while (countExercise<count){
            arithmetic();
            Result result=new Result();
            result.result=this.result;
            result.resultNumber=this.resultNumber;
            exercisesMap.put(countExercise,result);
            countExercise++;
        }
        return exercisesMap;
    }

}
package test;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

public class ExercisesSwing implements ActionListener {
    private JLabel jlabelExercise,jlabelTip;
    private JFrame jfrm;
    private JTextField jtfInput;
//    第一个题目的初始位置和距离
    private  int startX=20,startY=20,distance=220;
    private Map<Integer,Exercises.Result> map; //保存所有的题目
    private Map<Integer,JTextField> mapJtfInput; //保存用户输入框
    private  Exercises exercises; //题目类
    private static class Score{ //保存答错题数和答题总数
      public static  int errorCount=0;
      public static int   num=0;
    }
    private JMenuBar menubar;   //菜单条
    private JMenu menuSet,menuColor; //菜单
    private JMenuItem  itemColorCYAN, itemColorYELLOW,itemColorPICK;  //颜色菜单项
    private JMenuItem itemCount;
    private JPanel jPanel;

    public static class Constant{//程序用到的数据常量
//        以下三个常量是试题所在的宽度和高度以及字体大小
        private static final int  JLABEl_WIDTH=220;
        private static final int  HEIGHT=25;
        private static final int  JLABEl_FONTSIZE=20;
        private static final int  JTF_INPUT_WIDTH=100;
        private  static final int  STRATY=20;
//        菜单栏中可以选择的题目最大数字
        private static final int EXERCICESCOUNT=5;
    }
    ExercisesSwing(){
        init(); //程序的加载和初始化
    }
    private  void init(){
        exercises=new Exercises();
        jfrm=new JFrame("四则运算");
        jPanel=new JPanel();
        jPanel.setBounds(0,0,600,6000);
        jPanel.setBackground(Color.CYAN);
        jPanel.setLayout(null);
        jfrm.setLayout(null);
        jfrm.setSize(600,600);
        jfrm.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        jfrm.setLocation(100,100);
        initMenu();
        jlabelTip=new JLabel();
        jPanel.add(jlabelTip);
        jPanel.setVisible(true);
        showExercises();
        jfrm.add(jPanel);
        jfrm.setVisible(true);
    }
    private void showExercises(){
        map=exercises.showArithmetic();
        mapJtfInput=new HashMap<Integer, JTextField>();
        Score.errorCount=0;
        Score.num=0;
        startY=20;
        for (int i=0;i<exercises.getCount();i++){
            startY+=Constant.HEIGHT;
            jlabelExercise=new JLabel(map.get(i).result);
            jlabelExercise.setFont(new Font("宋体",Font.BOLD, Constant.JLABEl_FONTSIZE ));
            jlabelExercise.setBounds(startX,startY,Constant.JLABEl_WIDTH,Constant.HEIGHT);
            jtfInput=new JTextField(10);
            jtfInput.addKeyListener(new KeyAdapter() {
                @Override
                public void keyTyped(KeyEvent e) {
                    int key = e.getKeyChar();
                    // 只能输入数字
                    char keyCh = e.getKeyChar();
                    if ((keyCh < '0') || (keyCh > '9')) {
                        if(keyCh=='-'||keyCh=='.'){

                        }
                        else if(keyCh != KeyEvent.VK_ENTER ){
                            e.setKeyChar('\0');
                        }
                    }

                    if (key == KeyEvent.VK_ENTER) {
                        String sub="JTextField[,"+(distance+startX)+",";
                        int indexOf=e.toString().indexOf(sub)+sub.length();
                        int lastOf=e.toString().indexOf(Constant.JTF_INPUT_WIDTH+"x"+Constant.HEIGHT);
                        String inputNumber = e.toString();
                        if(lastOf<indexOf)
                            return;
                        String targetY=e.toString().substring(indexOf,lastOf-1);
                        int count= (Integer.parseInt(targetY)-Constant.STRATY ) /Constant.HEIGHT-1;
                        mapJtfInput.get(count).setEditable(false);
                    }
                }
            });
            mapJtfInput.put(i,jtfInput);
            jtfInput.setBounds(startX+distance,startY,Constant.JTF_INPUT_WIDTH,Constant.HEIGHT);
            jtfInput.addActionListener(this);
            jPanel.add(jlabelExercise);
            jPanel.add(jtfInput);

        }

    }
//    初始化菜单内容
    private void initMenu(){
        menubar = new JMenuBar();
        menuSet = new JMenu("选择题目数量");
        for(int i=0;i<Constant.EXERCICESCOUNT;i++){
            itemCount=new JMenuItem((i+1)+"");
            itemCount.addActionListener(this);
            menuSet.add(itemCount);
        }
        menuColor = new JMenu("颜色设置");
        itemColorCYAN=new JMenuItem("深加蓝");
        itemColorYELLOW=new JMenuItem("天然黄");
        itemColorPICK=new JMenuItem("少女粉");
        menuColor.add(itemColorCYAN);
        menuColor.add(itemColorYELLOW);
        menuColor.add(itemColorPICK);
        menubar.add(menuSet);  //将菜单添加到菜单条上
        menubar.add(menuColor);
        jfrm.setJMenuBar(menubar);
        setMenuItemEvent();
    }
//    设置菜单颜色按钮事件
    private void setMenuItemEvent(){
        itemColorCYAN.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {//只能检测到mousePressed事件
                super.mouseClicked(e);
                jPanel.setBackground(Color.CYAN);
            }
        });
        itemColorYELLOW.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {//只能检测到mousePressed事件
                super.mouseClicked(e);
                jPanel.setBackground(Color.YELLOW);
            }
        });
        itemColorPICK.addMouseListener(new MouseAdapter() {
            @Override
            public void mousePressed(MouseEvent e) {//只能检测到mousePressed事件
                super.mouseClicked(e);
                jPanel.setBackground(Color.pink);

            }
        });
    }
    public void repaintJPanel(int number){
         jPanel.removeAll();
         jPanel.repaint();
         exercises.setCount(number);
          showExercises();
          return;
    }
    public static boolean isInteger(String str) {  
        Pattern pattern = Pattern.compile("^[-\\+]?[\\d]*$");  
        return pattern.matcher(str).matches();  
  }
//  对所有组件进行监听事件
    public void actionPerformed(ActionEvent e) {
//        获取组件值
        String targetNumber=e.getActionCommand();
//        如果用户按下的组件是菜单的选择数字 则对页面进行重绘
        if(!targetNumber.equals("")|| !isInteger(targetNumber)){

            int number=Double.valueOf(targetNumber).intValue();
//                    Integer.parseInt(targetNumber);
            if( number>0 && number<=Constant.EXERCICESCOUNT)
            repaintJPanel(number); //重绘页面上的试题 即对试题进行刷新
        }
//        以下是对用户输入答案后 对用户答案进行判断 和输出文字

//        首先获取用户输入框的位置 然后再输入框的位置右边输出要显示的信息
        String sub="JTextField[,"+(distance+startX)+",";
        int indexOf=e.toString().indexOf(sub)+sub.length();
        int lastOf=e.toString().indexOf(Constant.JTF_INPUT_WIDTH+"x"+Constant.HEIGHT);
        String inputNumber = e.getActionCommand();
        if(lastOf<indexOf)
            return;
        String targetY=e.toString().substring(indexOf,lastOf-1);
        int count= (Integer.parseInt(targetY)-Constant.STRATY ) /Constant.HEIGHT-1;
        jlabelTip=new JLabel();
        if(inputNumber.equals(""))
            inputNumber="-1";
        float result=map.get(count).resultNumber-Float.parseFloat(inputNumber);
        if(Math.abs(result)<0.01){
            jlabelTip.setText("你答对了");
        }else{
            jlabelTip.setText("答错了,正确答案:"+
                            String.format("%.2f", map.get(count).resultNumber));
            Score.errorCount++;
        }
        jPanel.add(jlabelTip);
        jlabelTip.setBounds(startX+(int)(distance*1.5),Integer.parseInt(targetY),Constant.JTF_INPUT_WIDTH*2,Constant.HEIGHT);
//        以下是判断用户答错的题目和总的答题数目 在用户答题后  输入框便不能使用了
        Score.num++;
        if(Score.num==exercises.getCount()){
            jlabelTip=new JLabel();
            jPanel.add(jlabelTip);
            jlabelTip.setText("你答对了"+(Score.num-Score.errorCount)+"道题  "
            +"答错了"+Score.errorCount+"道题");
            jlabelTip.setBounds(100,Integer.parseInt(targetY)*2,Constant.JTF_INPUT_WIDTH*2,Constant.HEIGHT);
        }
    }

    public static void main(String[] args) {
        ExercisesSwing  exercisesSwing=new ExercisesSwing();
    }
}

 

posted @ 2018-10-27 19:13  一觉不觉已千年  阅读(247)  评论(0编辑  收藏  举报