作業 結對程式設計
一 結對成員
陳穎鋒 201421122113
許鴻洋 201421122114
項目開發的coding.net 位址:https://coding.net/u/ricardoCYF/p/zuoye3/git
二 項目描述
- 一個小組中的兩個同學選取比較優秀的 作業1 (兩個人的都獨立完成了), 把它作為本次作業的基礎,然後再修改。
- 結對程式設計實作上述功能,同樣的,在程式正式開發之前,請先預估下PSP每個環節的消耗時間,并在過程中統計實際耗時,最後送出PSP表格。依然注意,這個主要是給你們自己看的,不必造假資料。
- 在兩人合作的過程中, 請看下面的内容
- 滿足代碼風格規範和代碼設計規範(參考書第4章4.1-4.3内容)http://www.cnblogs.com/xinz/archive/2011/11/20/2255971.html
- 請重視這點,在開發時兩個人要有口頭上的溝通:“好的,我們一起在開發中遵守一起認可的編碼規範”
- 請把你們約定的編碼規範文檔也送出到git
- 給人提意見的方式——送一個漢堡包http://www.cnblogs.com/xinz/archive/2011/08/22/2148776.html
- 了解領航員和駕駛員兩種角色關系,并在結對程式設計中兩個人輪流做對方的角色。兩人都必須參與本次作業的編碼工作,并在git送出日志上展現這點。
三 項目實作
1.需求分析:
題目自動生成, 答題
-
程式設計:
題目自動生成(根據數量和範圍) 答題(做題 答案驗證 得出正确答案)
- 代碼展示:展示每個功能的核心代碼。
控制器(url轉發處理)——業務類(進行業務處理)——使用工具類生成運算字元串——數學類(解析字元串轉成FenShu對象的操作)
業務類:
@Service
public class MainService {
public List<String> getQuestList(int num,int random) {
if (num <= 0)
throw new InputMismatchException();
if (random <= 0)
List<String> list=new ArrayList<String>();
for (int i = 0; i <num ; i++) {
String str= Util.calStringCreate(random);
list.add(str);
}
return list;
public List<String> getResult(List<String> quest,List<String> answer) {
List<String> list=new ArrayList<String>();
if(quest.size()!=answer.size())
try {
throw new Exception("輸入不比對");
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
for (int i = 0; i < quest.size(); i++) {
String str=quest.get(i);
String rs= Math.calc(str);
if(answer.get(i).equals(rs)){
list.add("正确");
else{
list.add("錯誤");
數學類:
/**
* Created by computer on 2017/9/26.
* 計算運算字元串的類
*/
public class Math {
* @param str 需要運算的字元串
public static boolean isBracket(String str){
String regex=".*\\(.*";
return str.matches(regex);
*計算沒有括号得到字元串
* @param str 運算字元串
* @return FenShu的fenshu變量
public static String calc(String str){
/*
1得到運算符的List集合
2得到操作數的List集合
3計算
List<Character> opList=getOpList(str);
List<FenShu> numList=getNumList(str);
FenShu result=jisuan(opList,numList);
return Util.trueFenShu(result);
*
* @param i:運算符的下标
* @param c:運算符
* @param num:操作數集合
public static void mulDiv(int i,Character c,List<FenShu> num){
if (c == '*' || c == '/') {//删除*/運算符并進行對應數值的計算 結果儲存
FenShu opl = num.get(i);
FenShu opr = num.get(i + 1);
if (c == '*') {
num.set(i + 1, fenShuMul(opl, opr));
} else if (c == '/') {
num.set(i + 1, fenShuDivi(opl, opr));
* @param op 操作符集合
* @param num 操作數集合
* @return 真分數值
public static FenShu jisuan(List<Character> op,List<FenShu> num){
//周遊運算符集合提取出+ -的下标并用二維數組儲存+ -分割的運算符字元集
List <Integer>opList1=new ArrayList<Integer>();
for (int i = 0; i <op.size() ; i++) {
if (op.get(i)=='+'||op.get(i)=='-'){
opList1.add(i);
if(opList1.size()>0){
if (0<opList1.get(0)) {
for (int i = 0; i < opList1.get(0); i++) {//下标從0到小于opList1.get(0)
Character c = op.get(i);
mulDiv(i,c,num);
if (opList1.size()>1)
for (int i = 0; i < opList1.size(); i++) {//目的求被+-分割起來的區域 從運算符集合+-後的*/開始直到下一個+-運算符出現
for (int j = opList1.get(i)+1; j <opList1.get(i+1) ; j++) {
Character c=op.get(j);
mulDiv(j,c,num);
if (opList1.get(i+1)==opList1.get(opList1.size()-1))//末尾時候退出
break;
if (opList1.get(opList1.size()-1)!=op.size()-1){//如果+-符号不是是運算符集合的最後一位 需要對于後面的式子進行乘除計算
for (int j = opList1.get(opList1.size()-1)+1; j <op.size() ; j++) {
else if (opList1.size()==0){
for (int i = 0; i < op.size(); i++) {//下标從0到小于opList1.get(0)
//這是先乘除之後的數 和 需要加減的符号
// if (opList1.size()>0)
// for (int i:opList1) {
// System.out.println(num.get(i).getFenzi()+"/"+num.get(i).getFenmu());
// System.out.println(op.get(i));
// }
// System.out.println(num.get(num.size()-1).getFenzi()+"/"+num.get(num.size()-1).getFenmu());
List<Character> opList2=new ArrayList<Character>();
List<FenShu> numList2=new ArrayList<FenShu>();
if (opList1.size()>0)
for (int i:opList1) {
numList2.add(num.get(i));
opList2.add(op.get(i));
numList2.add(num.get(num.size()-1));
while (!opList2.isEmpty()){
Character c=opList2.remove(0);
FenShu opl=numList2.remove(0);
FenShu opr=numList2.remove(0);
if(c=='+'){
numList2.add(0, fenShuAdd(opl,opr));
else if(c=='-'){
numList2.add(0, fenShuSub(opl,opr));
return numList2.get(0);
* @param str 運算的字元串
* @return 傳回運算符集合
public static List<Character> getOpList(String str){
List<Character> list = new ArrayList<Character>();
String regex = "[0-9]*";
Pattern pattern=Pattern.compile(regex);
String []split=pattern.split(str);
for (int i = 0; i <split.length; i++) {
String tmp=split[i].trim();
if(tmp.equals("+")|tmp.equals("-")|tmp.equals("*")|tmp.equals("/")){
list.add(tmp.trim().charAt(0));
* @return 傳回FenShu類型的集合
public static List getNumList(String str){
List<FenShu> list = new ArrayList<FenShu>();
String regex = "\\+|-|\\*|/";
String regex2="[0-9]+";
if(tmp.matches(regex2)){
Integer num=Integer.valueOf(tmp);
FenShu fenshu=new FenShu(num,1);
list.add(fenshu);
* 分數類的加減乘除
* @param fenshu1
* @param fenshu2
* @return
public static FenShu fenShuAdd(FenShu fenshu1, FenShu fenshu2){
int lcm=getMinMul(fenshu1.getFenmu(),fenshu2.getFenmu());//z最小公倍數 未化簡的分母
int numera=(lcm/fenshu1.getFenmu())*fenshu1.getFenzi()+(lcm/fenshu2.getFenmu())*fenshu2.getFenzi();//最小公倍數除以分母乘以分子相加 這是分子和
int gcd= getMaxDiv(numera,lcm);//最大公約數 可以約的值
numera/=gcd;
int deomina=lcm/gcd;
FenShu fenshu3=new FenShu(numera,deomina);
return fenshu3;
public static FenShu fenShuSub(FenShu fenshu1, FenShu fenshu2){
int numera=(lcm/fenshu1.getFenmu())*fenshu1.getFenzi()-(lcm/fenshu2.getFenmu())*fenshu2.getFenzi();//最小公倍數除以分母乘以分子相加 這是分子和
public static FenShu fenShuMul(FenShu fenshu1, FenShu fenshu2){
int a,b,c,d;
a=fenshu1.getFenzi();
b=fenshu1.getFenmu();
c=fenshu2.getFenzi();
d=fenshu2.getFenmu();
int numera=a*c;
int deomina=b*d;
if(deomina<0) {
throw new RuntimeException("分母不能小于0");
int gcd=getMaxDiv(numera,deomina);
deomina/=gcd;
public static FenShu fenShuDivi(FenShu fenshu1, FenShu fenshu2){
c=fenshu2.getFenmu();
d=fenshu2.getFenzi();
numera = -1*numera;
deomina=-1*deomina;
* 求最小公倍數
public static int getMinMul(int a,int b){
int c=a*b/getMaxDiv(a,b);
return c;
* 求最大公約數
public static int getMaxDiv(int a,int b){
if (a<0)
a=java.lang.Math.abs(a);
if(b<0)
while (b!=0){
int c=a%b;
a=b;
b=c;
return a;
工具類:
随機生成運算字元串 将分數類轉成真分數的字元串形式
public class Util {
public static String trueFenShu(FenShu fs){
int abs= Math.abs(fs.getFenzi());
if (abs<fs.getFenmu())
return fs.getFenzi()+"/"+fs.getFenmu();
else if (abs==fs.getFenmu())
return String.valueOf(fs.getFenzi()/fs.getFenmu());
else {
int num=abs/fs.getFenmu();
int fenzi=abs%fs.getFenmu();
if (fenzi==0){
if (fs.getFenzi()>=0)
return num+"";
else
return "-"+num;
return num+"'"+fenzi+"/"+fs.getFenmu();
return "-"+num+"'"+fenzi+"/"+fs.getFenmu();
public static String calStringCreate(int r){
char []c={'+','-','*','/'};//操作符數組
Random random=new Random();
StringBuffer str=new StringBuffer();
int n= random.nextInt(3)+1;
int num=random.nextInt(r-1)+1;
str.append(num);
for (int i = 0; i <n ; i++) {//在1到3範圍内随機個數的運算符
char c2=c[(int)(c.length* java.lang.Math.random())];//生成随機操作符
int num2=random.nextInt(r-1)+1;//生成大于0小于r的自然數
str.append(c2);
str.append(num2);
return str.toString();
public static void main(String[] args) {
calStringCreate(20);
分數類:
public class FenShu {
//整數int 分子 分母 真分數
private int fenzi;
private int fenmu;
public FenShu(int fenzi, int fenmu) {
if (fenmu<=0)
this.fenzi = fenzi;
this.fenmu = fenmu;
public int getFenzi() {
return fenzi;
public int getFenmu() {
return fenmu;
public void setFenzi(int fenzi) {
public void setFenmu(int fenmu) {
- 程式運作:程式運作及每個功能的使用截圖

四 小結
1.小結感受:結對程式設計真的能夠帶來1+1>2的效果嗎?通過這次結對程式設計,請談談你的感受和體會。
可以的,頭腦風暴,多溝通
2.運用“漢堡包”的方式,評價你的合作夥伴,指出優點、缺點,希望ta提高的地方
最外層: 行為和後果 :第一次結對,容易誤解
中間層: 習慣和動機 :習慣一個人做事不溝通,都是為了更好
最内層: 本質和基本屬性 :缺少溝通
3.提供此次結對作業的PSP,PSP 表格中請填寫花費的時間 (機關: 分鐘), 而不是每一步所占的比例。
psp2.1 | Personal Software Process Stages | Time Senior Student(min) | Time(min) |
Planning | 計劃 | 200 | 270 |
· Estimate | 估計這個任務需要多少時間 | 500 | 550 |
Development | 開發 | 450 | 600 |
· Analysis | 需求分析 (包括學習新技術) | 10 | 20 |
· Design Spec | 生成設計文檔 | 30 | |
· Design Review | 設計複審 | ||
· Coding Standard | 代碼規範 | 15 | |
· Design | 具體設計 | 40 | 60 |
· Coding | 具體編碼 | 300 | |
· Code Review | 代碼複審 | ||
· Test | 測試(自我測試,修改代碼,送出修改) | 50 | |
Reporting | 報告 | ||
· | 測試報告 | ||
計算工作量 | |||
并提出過程改進計劃 |