结对项目-四则运算 “软件”之升级版
本次作业要求来自: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个方向:
- 程序可以出带括号的正整数四则运算,支持分数,除法保留两位小数;
- 可以出表达式里含有负整数(负整数最小不小于-100)的题目,且负数需要带括号,用户输入的结果不用带括号;
- 用户可以选择出题的个数(最多不能超过5个题目),答题结束可以显示用户答错的题目个数和答对的题目个数;
- 程序可以设置皮肤功能,可以改变界面的颜色即可。
四、项目的时间规划:
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(); } }