北京电子科技学院(BESTI)
实验报告
课程:java程序设计 班级:1352 姓名:何伟钦 学号:20135223
成绩: 指导教师: 娄嘉鹏 实验日期: 2015.6.4
实验密级: 预习程度: 实验时间:
仪器组次: 23 必修/选修:必修 实验序号:03
实验名称:敏捷开发与XP实践
实验目的与要求:通过对各种内部排序算法进行比较,更好的掌握各种排序的基本思想,掌握各种排序方法的算法实现,掌握各种排序方法的优劣分析及花费的时间的计算,掌握各种排序方法所适应的不同场合.
实验仪器 |
型号 |
数量 |
笔记本电脑 |
戴尔14z-5423 |
1 |
实验楼虚拟机 |
|
|
实验步骤
(一)敏捷开发与XP
一项实践在XP环境中成功使用的依据通过XP的法则呈现,包括:快速反馈、假设简单性、递增更改、提倡更改、优质工作。
XP软件开发的基石是XP的活动,包括:编码、测试、倾听、设计。
以测试为核心的开发流程:
(二)编码标准
编程标准使代码更容易阅读和理解,甚至可以保证其中的错误更少。编程标准包含:具有说明性的名字、清晰的表达式、直截了当的控制流、可读的代码和注释,以及在追求这些内容时一致地使用某些规则和惯用法的重要性。
以下程序没有最基本的缩进,读起来很费劲
在Eclipse中单击Eclipse菜单中的source->Format 或用快捷键Ctrl+Shift+F就可以按Eclipse规定的规范缩进,效果如下:
(三)结对编程
(四)版本控制
结对编程对这一实践贡献良多:借由在不同的结对中工作,所有的程序员都能看到完全的代码。集体所有制的一个主要优势是提升了开发程序的速度,因为一旦代码中出现错误,任何程序员都能修正它。
Git是Linus除了Linux操作系统外的另外一个重要发明。
$ cd /home/shiyanlou/Code/shiyanlou_cs212
# 修改代码文件
# 添加修改文件
$ git add 所有修改的文件
# 提交到环境中本地代码仓库
$ git commit -m '本次修改的描述'
# push到git.shiyanlou.com,无需输入密码
$ git push
(五)重构(Refactor)
重构:在不改变软件外部行为的基础上,改变软件内部的结构,使其更加易于阅读、易于维护和易于变更 。
1.重构的第一项功能就是Rename,可以给类、包、方法、变量改名字。 例如这有个ABC类:
2.用鼠标单击要改的名字,选择Eclipse中菜单中的Refactor->Rename。重构完的效果如下:
3.封装,该用类的地方都用了结构体
Eclipse中菜单中的Refactor->Encapsulate Field...,如下图:
4.每次打印学生信息都这么写代码违反了DRY原则,造成代码重复,正常的重构可以使用Eclipse中的Extract Method...,如下图:
一个完整的重构流程包括:
- 从版本控制系统代码库中Check out code
- 读懂代码(包括测试代码)
- 发现bad smell
- Refactoring
- 运行所有的Unit Tests
- 往代码库中Check in code
修改软件,万变不离其宗,无非就是四种动机:
- 增加新功能;
- 原有功能有BUG;
- 改善原有程序的结构;
- 优化原有系统的性能 。
(六)实践项目
一、实验结队分工
1:何伟钦:负责代码找寻与编写,控制键盘输入部分
2:马启扬:负责代码修改与运行测试部分http://www.cnblogs.com/mqy123/
二、概要说明
本程序是在eclipse环境下编写的Windows应用程序,函数中利用了画图函数绘制基本方块模型,并通过键盘或鼠标执行相应的操作。在产生的方块中,调用随机方法,随机产生1~100中的任何一个数字,数字小于90,方块显示数字为2,否则显示为4,每一,通过这种方式,实现了游戏中其中不同模块的数字的随机产生。
(一).题目 :2048
(二)需求分析
游戏操作需求:
1、可使用鼠标或↑、↓、→、←或W、X、A、D键进行操作;
2、Play按钮 重新开始游戏;
3、Undo按钮 取消本次操作,回到上一步。
2048游戏算法
1、游戏开始时随机的产生2个数值为2/4的方格,其中1个方格置于4个角中的一个位置,另一个方格随机的置于其它位置,其余方格值为0。
2、每次移动鼠标或按方向键后,逐行计算移动后的方格值。每行移动的算法是:先将所有 值为0的数移至行首。能后从行尾开始逐一和前一个数比较,如果相等则合并这2个格子。
3、每合并一次格子,将其值累计到游戏总分中。
4、一次移动结束后,在所有值为0的方格中随机的分配一个2/4的值。
5、所有方格值不为0且上下、左右相邻的方格都不相等,则游戏结束。
6、2出现的概率为90%,4出现的概率为为10%。
(三).程序流程图
(四)功能说明
(1) 实现可以显示2或者4两张数字的方块
(2) 实现各个方块的上下左右移动
(3) 实现方块间数字判断与相加
四、具体代码
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import javax.swing.border.*;
public class Test extends JApplet{
private static final int UP=0,DOWN=1,LEFT=2,RIGHT=3;
private static final int WID=150,SP=10;
private int scores=0;
private static JLabel scoreLabel;
private boolean change,CheckMode=false,gameOverFlag=false,successFlag=false;
private int[] label={2,4,8,16,32,64,128};
private Color[] clo={
new Color(200,200,200),new Color(228,228,160),new Color(214,163,92),
new Color(234,124,72),new Color(240,84,77),new Color(255,68,53),new Color(200,200,64)
};
private Map cmap=new HashMap();
public static RectObject[][] rset=new RectObject[4][4];
public RectObject[][] list=new RectObject[4][4];
private My2048Panel myp;
private LinkedList saveList=new LinkedList();
private JButton goBackButton;
KeyListener kl=new KeyListener(){
public void keyPressed(KeyEvent e){
saveTheStep();
goBackButton.setVisible(true);
if(gameOverFlag==true){
return;
}
if(!aDirAble()){
gameOver();
}
int key=e.getKeyCode();
switch(key){
case KeyEvent.VK_UP:
change=false;
moveUp(true);
if(change==true){
getARandomRect();
//saveTheStep();
}
break;
case KeyEvent.VK_DOWN:
change=false;
moveDown(true);
if(change==true){
getARandomRect();
//saveTheStep();
}
break;
case KeyEvent.VK_LEFT:
change=false;
moveLeft(true);
if(change==true){
getARandomRect();
//saveTheStep();
}
break;
case KeyEvent.VK_RIGHT:
change=false;
moveRight(true);
if(change==true){
getARandomRect();
//saveTheStep();
}
break;
}
//saveTheStep();
}
public void keyTyped(KeyEvent e){}
public void keyReleased(KeyEvent e){}
};
class RectObject{
private int value;
public RectObject(){
value=0;
}
public RectObject(RectObject obj){
value=obj.value;
}
public boolean equals(Object inobj){
RectObject obj=(RectObject)inobj;
if(obj.value==value){
return true;
}
return false;
}
}
class Point{
int x;
int y;
public Point(int i,int j){
x=i;
y=j;
}
}
class My2048Panel extends JPanel{
private int[] xindex={SP,2*SP+WID,3*SP+2*WID,4*SP+3*WID};
private int[] yindex={SP,2*SP+WID,3*SP+2*WID,4*SP+3*WID};
public void paintComponent(Graphics g){
//background
super.paintComponent(g);
for(int i=0;i<xindex.length;i++){
for(int j=0;j<yindex.length;j++){
g.setColor(Color.WHITE);
g.drawRoundRect(xindex[i], yindex[j], WID, WID, WID/5, WID/5);
g.setColor(new Color(197,183,129));
g.fillRoundRect(xindex[i], yindex[j], WID, WID, WID/5, WID/5);
}
}
//paint rectangle
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(rset[i][j]!=null){
g.setColor(Color.WHITE);
g.drawRoundRect(yindex[j], xindex[i], WID, WID, WID/5, WID/5);
if(rset[i][j].value<128){
g.setColor((Color)cmap.get(rset[i][j].value));
}else{
g.setColor((Color)cmap.get(128));
}
g.fillRoundRect(yindex[j], xindex[i], WID, WID, WID/5, WID/5);
g.setColor(Color.BLACK);
Font font=new Font("TimesRoman",Font.BOLD,50);
g.setFont(font);
FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
int len=fm.stringWidth(""+rset[i][j].value);
int hg=fm.getHeight();
g.drawString(""+rset[i][j].value, yindex[j]+WID/2-len/2, xindex[i]+WID/2+hg/4);
if(rset[i][j].value==2048 && successFlag==false){
successFlag=true;
gameSuccess();
}
}
}
}
}
}
class GameOverPane extends JPanel{
public GameOverPane(int w,int h){
setSize(w,h);
//setOpaque(false);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Font font=new Font("TimesRoman",Font.BOLD,80);
g.setFont(font);
FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
int width=fm.stringWidth("Game Over");
int height=fm.getHeight();
g.setColor(new Color(255,0,0));
g.drawString("Game Over!", getWidth()/2-width/2, getHeight()/2-height/2);
}
}
class SuccessPane extends JPanel{
public SuccessPane(int w,int h){
setSize(w,h);
//setOpaque(false);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Font font=new Font("TimesRoman",Font.BOLD,80);
g.setFont(font);
FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
int width=fm.stringWidth("Success!");
int height=fm.getHeight();
g.setColor(new Color(255,0,0));
g.drawString("Success!", getWidth()/2-width/2, getHeight()/2-height/2);
}
}
class LOGO extends JPanel{
public LOGO(int w ,int h){
setSize(w,h);
}
public void paintComponent(Graphics g){
super.paintComponent(g);
Font font=new Font("TimesRoman",Font.BOLD,60);
g.setFont(font);
FontMetrics fm=Toolkit.getDefaultToolkit().getFontMetrics(font);
int width=fm.stringWidth("2048");
int height=fm.getHeight();
g.setColor(new Color(255,0,0));
g.drawString("2048", 20, getHeight()/2+20);
}
}
public class goBackListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if(saveList.size()==0){
goBackButton.setVisible(false);
return;
}
ArrayList arr=(ArrayList)saveList.getLast();
scoreLabel.setText(""+arr.get(0));
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
int num=(int)arr.get(4*i+j+1);
if(num!=0){
rset[i][j]=new RectObject();
rset[i][j].value=num;
}else{
rset[i][j]=null;
}
}
}
saveList.removeLast();
repaint();
}
}
public class resetListener implements ActionListener{
public void actionPerformed(ActionEvent e){
refreshBest();
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
rset[i][j]=null;
}
}
scoreLabel.setText("0");
repaint();
getARandomRect();
getARandomRect();
}
}
//the applet init
public void init(){
Container cp=getContentPane();
cp.setLayout(null);
cp.setFocusable(true);
cp.addKeyListener(kl);
Font font=new Font("TimesNewman",Font.BOLD,30);
JLabel sl=new JLabel();
sl.setLayout(new GridLayout(2,1));
JLabel sllb=new JLabel("Scores");
sllb.setFont(font);
scoreLabel=new JLabel("0");
scoreLabel.setFont(font);
sl.add(sllb);
sl.add(scoreLabel);
int best=0;
try{
File file=new File("BestRecord");
if(file.exists()){
RandomAccessFile f=new RandomAccessFile(file,"rw");
best=f.readInt();
f.close();
}
}catch(FileNotFoundException e){
best=0;
e.printStackTrace();
}catch(IOException e){
best=0;
e.printStackTrace();
}
JLabel bsl=new JLabel();
bsl.setLayout(new GridLayout(2,1));
JLabel jl=new JLabel("Best");
jl.setFont(font);
JLabel jl1=new JLabel(""+best);
jl1.setFont(font);
bsl.add(jl);
bsl.add(jl1);
myp=new My2048Panel();
LOGO logo=new LOGO(0,0);
goBackButton=new JButton("UNDO");
goBackButton.setFont(font);
goBackButton.addActionListener(new goBackListener());
goBackButton.addKeyListener(kl);
JButton jb=new JButton("RESET");
jb.setFont(font);
jb.addActionListener(new resetListener());
jb.addKeyListener(kl);
sl.setBounds(500,20,200,80);
bsl.setBounds(300,20,200,80);
logo.setBounds(0, 0, 600, 100);
myp.setBounds(0,90,700,700);
goBackButton.setBounds(700,250,150,60);
jb.setBounds(700,450,150,60);
cp.add(sl);
cp.add(bsl);
cp.add(logo);
cp.add(myp);
cp.add(goBackButton);
cp.add(jb);
File f=new File("LASTRECORD");
if(f.exists()){
try{
RandomAccessFile file=new RandomAccessFile(f,"rw");
int num=file.readInt();
scoreLabel.setText(""+num);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
num=file.readInt();
if(num!=0){
rset[i][j]=new RectObject();
rset[i][j].value=num;
}
}
}
file.close();
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}else{
getARandomRect();
getARandomRect();
}
}
public Test(){
//saveTheStep();
for(int i=0;i<7;i++){
cmap.put(label[i], clo[i]);
}
}
//moveLeft
public void moveLeft(boolean flag){
clearList(list);
for(int i=0;i<4;i++){
int k=0;
for(int j=0;j<4;j++){
if(rset[i][j]!=null){
list[i][k++]=new RectObject(rset[i][j]);
}
}
}
for(int i=0;i<4 && flag;i++){
for(int j=0;j<3;j++){
if(list[i][j]!=null && list[i][j+1]!=null && list[i][j].value==list[i][j+1].value){
list[i][j].value*=2;
if(CheckMode==false){
int sum=Integer.parseInt(scoreLabel.getText());
sum+=list[i][j].value;
scoreLabel.setText(""+sum);
}
list[i][j+1]=null;
j++;
}
}
}
if(isChange()){
if(CheckMode==false){
copySet(rset,list);
repaint();
moveLeft(false);
}
change=true;
}else{
repaint();
}
}
//moveRight
public void moveRight(boolean flag){
clearList(list);
for(int i=0;i<4;i++){
int k=3;
for(int j=3;j>-1;j--){
if(rset[i][j]!=null){
list[i][k--]=new RectObject(rset[i][j]);
}
}
}
for(int i=0;i<4 && flag;i++){
for(int j=3;j>0;j--){
if(list[i][j]!=null && list[i][j-1]!=null && list[i][j].value==list[i][j-1].value){
list[i][j].value*=2;
if(CheckMode==false){
int sum=Integer.parseInt(scoreLabel.getText());
sum+=list[i][j].value;
scoreLabel.setText(""+sum);
}
list[i][j-1]=null;
j--;
}
}
}
if(isChange()){
if(CheckMode==false){
copySet(rset,list);
repaint();
moveRight(false);
}
change=true;
}else{
repaint();
}
}
//moveup
public void moveUp(boolean flag){
clearList(list);
for(int j=0;j<4;j++){
int k=0;
for(int i=0;i<4;i++){
if(rset[i][j]!=null){
list[k++][j]=new RectObject(rset[i][j]);
}
}
}
for(int j=0;j<4 && flag;j++){
for(int i=0;i<3;i++){
if(list[i][j]!=null && list[i+1][j]!=null && list[i][j].value==list[i+1][j].value){
list[i][j].value*=2;
if(CheckMode==false){
int sum=Integer.parseInt(scoreLabel.getText());
sum+=list[i][j].value;
scoreLabel.setText(""+sum);
}
list[i+1][j]=null;
i++;
}
}
}
if(isChange()){
if(CheckMode==false){
copySet(rset,list);
repaint();
moveUp(false);
}
change=true;
}else{
repaint();
}
}
//movedown
public void moveDown(boolean flag){
clearList(list);
for(int j=0;j<4;j++){
int k=3;
for(int i=3;i>-1;i--){
if(rset[i][j]!=null){
list[k--][j]=new RectObject(rset[i][j]);
}
}
}
for(int j=0;j<4 && flag;j++){
for(int i=3;i>0;i--){
if(list[i][j]!=null && list[i-1][j]!=null && list[i][j].value==list[i-1][j].value){
list[i][j].value*=2;
if(CheckMode==false){
int sum=Integer.parseInt(scoreLabel.getText());
sum+=list[i][j].value;
scoreLabel.setText(""+sum);
}
list[i-1][j]=null;
i--;
}
}
}
if(isChange()){
if(CheckMode==false){
copySet(rset,list);
repaint();
moveDown(false);
}
change=true;
}else{
repaint();
}
}
//other functions
private void copySet(RectObject[][] dst, RectObject[][] src){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
dst[i][j]=src[i][j];
}
}
}
//detect whether rset is different from list or not
private boolean isChange(){
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(rset[i][j]!=null && list[i][j]!=null && !rset[i][j].equals(list[i][j])){
return true;
}
if(rset[i][j]!=null && list[i][j]==null){
return true;
}
if(rset[i][j]==null && list[i][j]!=null){
return true;
}
}
}
return false;
}
private void clearList(RectObject[][] s){
for(int i=0;i<s.length;i++){
for(int j=0;j<s[i].length;j++){
s[i][j]=null;
}
}
}
//get a random rectangle
public void getARandomRect(){
ArrayList list=new ArrayList();
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(rset[i][j]==null){
list.add(new Point(i,j));
}
}
}
if(list.size()==0 && !aDirAble()){
gameOver();
return;
}
Random rand=new Random();
int index=rand.nextInt(list.size());
Point loc=(Point)list.get(index);
index=rand.nextInt(2);
rset[loc.x][loc.y]=new RectObject();
if(index==1){
rset[loc.x][loc.y].value=4;
}else{
rset[loc.x][loc.y].value=2;
}
}
//detect whether there are other steps or not
public boolean aDirAble(){
CheckMode=true;
change=false;
moveLeft(true);
moveRight(true);
moveDown(true);
moveUp(true);
CheckMode=false;
if(change==true){
return true;
}else{
return false;
}
}
public void gameOver(){
gameOverFlag=true;
final JPanel jl=new GameOverPane(myp.getWidth(),myp.getHeight());
jl.setBounds(0, 0, 700, 700);
JButton jb1=new JButton("Again");
Font font=new Font("TimesRoman",Font.BOLD,30);
jb1.setOpaque(false);
jb1.setFont(font);
JButton jb2=new JButton("Close");
jb2.setSize(jb1.getSize());
jb2.setOpaque(false);
jb2.setFont(font);
jb1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
scoreLabel.setText("0");
myp.remove(jl);
clearList(rset);
myp.validate();
getARandomRect();
getARandomRect();
repaint();
gameOverFlag=false;
refreshBest();
}
});
jb2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
refreshBest();
File f=new File("LASTRECORD");
if(f.exists()){
f.delete();
}
System.exit(0);
}
});
jl.add(jb1);
jl.add(jb2);
myp.add(jl);
jl.validate();
}
public void gameSuccess(){
JPanel jl=new SuccessPane(myp.getWidth(),myp.getHeight());
jl.setOpaque(false);
jl.setBounds(0, 0, 700, 700);
JButton jb1=new JButton("Continue");
Font font=new Font("TimesRoman",Font.BOLD,30);
jb1.setOpaque(false);
jb1.setFont(font);
JButton jb2=new JButton("Close");
jb2.setSize(jb1.getSize());
jb2.setOpaque(false);
jb2.setFont(font);
jb1.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
myp.remove(jl);
myp.validate();
repaint();
}
});
jb2.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
refreshBest();
System.exit(0);
}
});
jl.add(jb1);
jl.add(jb2);
myp.add(jl);
jl.validate();
}
public void saveTheStep(){
if(saveList.size()<20){
ArrayList arr=new ArrayList();
int score=Integer.parseInt(scoreLabel.getText());
arr.add(score);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(rset[i][j]!=null){
arr.add(rset[i][j].value);
}else{
arr.add(0);
}
}
}
saveList.addLast(arr);
}else{
saveList.removeFirst();
saveTheStep();
}
}
public static String title(Object o){
String t=o.getClass().toString();
if(t.indexOf("class")!=-1){
t=t.substring(6);
}
return t;
}
public static void refreshBest(){
try {
int best=0;
File f=new File("BestRecord");
RandomAccessFile file;
if(f.exists()){
file=new RandomAccessFile(f,"rw");
best=file.readInt();
file.seek(0);
}else{
file=new RandomAccessFile(f,"rw");
}
//System.out.println("The Best score is "+best);
int cur=Integer.parseInt(scoreLabel.getText());
if(cur>best){
file.writeInt(cur);
}
file.close();
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}catch(IOException e2){
e2.printStackTrace();
}
}
public static void saveRecord(){
try{
RandomAccessFile file=new RandomAccessFile(new File("LASTRECORD"),"rw");
int score=Integer.parseInt(scoreLabel.getText());
file.writeInt(score);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++){
if(rset[i][j]!=null){
file.writeInt(rset[i][j].value);
}else{
file.writeInt(0);
}
}
}
}catch(FileNotFoundException e){
e.printStackTrace();
}catch(IOException e){
e.printStackTrace();
}
}
public static void run(JApplet applet,int width,int height){
JFrame frame=new JFrame(title(applet));
frame.addWindowListener(new WindowAdapter(){
public void windowClosing(WindowEvent e){
refreshBest();
saveRecord();
//System.out.println("The score is "+scoreLabel.getText());
}
});
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(applet);
frame.setSize(width,height);
applet.init();
applet.start();
frame.setVisible(true);
}
public static void main(String[] args){
run(new Test(), 900, 800);
}
}
运行结果截图:
当方块不能移动时,游戏结束
统计的PSP(Personal Software Process)时间
步骤 |
耗时(min) |
百分比 |
需求分析 |
20~30 |
10% |
设计 |
40~50 |
20% |
代码实现 |
90~100 |
40% |
测试 |
40~50 |
20% |
分析总结 |
20~25 |
10% |
4.l实验体会总结 :
通过本次课程设计,对java应用程序开发有了更多的了解,编程过程中,出现了运行结果不符合预期、代码设计错误等许多问题,因为结伴编程,我们分工合作,相互交流,共同提高 ,极大的减少了测试时间,提高了效率,所以深切认识到团队合作开发应用程序的重要性,同时我也发现我的好多不足之处,首先是自己编程粗心大意,经常出错,通过学习也有所改进;再有对java类库的一些标准方法不太熟悉,还以及对java语言中经常出现的错误也不了解,通过实践,使我在这几个方面的认识有所提高。 通过实践的学习,我认识到学好计算机要重视实践操作,所以以后在java学习过程中,我会更加注视实践操作,使自己更好地学好编程。