天天看點

結對實踐項目——“五子棋”小遊戲

之前與小組同學合作過一起寫代碼,那時老師分工明确,寫兩部分代碼,一人負責一部分,剩下一個人做測試代碼,在老師詳盡的分工下,我們順利的完成了那次任務。

這次從無範圍自主選題,到熟練運用GUI,實作了人人對戰。

【功能分析】

(1)程式在設計初就定義黑棋先行,白棋随後。一個玩家通過w,a,s,d鍵控制落子位置,按Space落子,另一個玩家通過控制方向鍵up,down,left,right控制位置,按Enter落子,從第一個棋子開始開始互相順 序落子。  

(2)通過坐标索引算出最先在棋盤的橫向、豎向、斜向形成連續的相同色五棋子的一方為勝利。 

(3)初始界面潔淨無子設為遊戲固定界面。 

(4)在遊戲過程中單擊重新開局按鈕或下完時可選擇重新開始。 

(5)遊戲結束,會出現赢家對話框提示。 

(6)遊戲實作了基本的人人對戰。

【分工情況】

蘆暢:GUI設計及代碼規範

蘇正生:棋子勝負判斷

【代碼連結】

隊友蘇正生的報告:http://www.cnblogs.com/suzhengsheng/p/4549516.html

源代碼連結:http://git.shiyanlou.com/szs20135333/shiyanlou_cs212

【總體設計】

主要包括的類有四個:GameFrame、GamePanel、ChessMan、Player

1、  GamePanel類  

 GamePanel類是java版五子棋的主架構,程式的啟動類。 

其中包括遊戲界面的建立、按鈕的設定、相關的事件監聽器設定、遊戲的啟動  

2、GameFrame類  

 GameFrame類主要實作的是棋盤的繪制、建立數組存放棋子的坐标、設定隻能在棋盤内可以落子、實作判斷黑白棋的輸赢、實作重新遊戲。  

3、ChessMan類  

 Point類主要就是實作棋子的功能

4、Player類

Player類主要實驗玩家的功能

【過程分析】

這次實驗,我主要負責

這次我主要負責的是GUI設計以及代碼規範,我來大概說下GUI。

GUI程式設計規範總結:

1、首先就是建立菜單欄。在GUI控件使用時所有的控件都是層層嵌套的,就是控件依托,最終整合到面闆上,進而再添加事件監聽器,已響應事件的發生;

①首先要建立主架構:GamePanel Gpanel=new GamePanel();

②取得架構的内容窗格 

③在制作複雜的使用者界面時,常常需要使用多個JPanel将複雜的界面分解為先對建大的子界面,然後再對每個JPanel進行布局:

package WuZiGame;

import java.awt.*;
import javax.swing.*;
import java.awt.event.*;


class GameFrame extends JFrame {

    private static final int Width=570;
    private static final int Height=470;
    
    GameFrame(){
        setTitle("五子棋遊戲");
        CenteredFrame();
        setSize(Width,Height);        
        GamePanel Gpanel=new GamePanel();
        add(Gpanel);       
    }
    
    void CenteredFrame(){
        Toolkit kit=Toolkit.getDefaultToolkit();
        Dimension screenSize=kit.getScreenSize();
        int screenHeight=screenSize.height;
        int screenWidth=screenSize.width;
        
        int Xposition=(screenWidth-Width)/2;
        int Yposition=(screenHeight-Height)/2;
        setLocation(Xposition,Yposition);
    }
}      

⑤處理控件的依賴關系,及消息的定義,各種細節的設計

⑥控件的逐級加入

⑦将面闆加入到架構的内容窗格中

package WuZiGame;

import javax.swing.*;


public class Game {

    
    public static void main(String[] args) {
        
        GameFrame GFrame=new GameFrame();
        GFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GFrame.setVisible(true);
    }

}      
package WuZiGame;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;




class GamePanel extends JPanel {

    private Point cursor=new Point(40,60); //棋盤坐标
    private int[][] ChessState=new int[18][18];//棋盤狀态    
    private int i=0;//橫坐标   
    private int j=0;//縱坐标
    private final static int testnum=5;//五子棋的規定棋子數
    private Player Black=new Player(1,Color.BLACK,"黑方");//黑方棋子
    private Player White=new Player(2,Color.WHITE,"白方");//白方棋子
    private Player Cplayer=null;//目前使用者的引用
    private JTextField textBlack=new JTextField("",5);//黑方文本提示框對象和文本長度設定
    private JTextField textWhite=new JTextField("",5);//白方文本提示框對象和文本長度設定
    private String Nothing="";
    private String textblack="請黑方下子";//黑方提示文本
    private String textwhite="請白方下子";//白方提示文本
    
    
    GamePanel(){
        setLayout(null);
        Initialization();
        setFocusable(true);
        
         JButton Rutton=new JButton("重新開局");
        Rutton.setBounds(20,14,100,26);
        RestartListener restart=new RestartListener();
        Rutton.addActionListener(restart);
        add(Rutton);
        
        
        textBlack.setHorizontalAlignment(JTextField.CENTER);
        textBlack.setBounds(150,14,110,26);
        textBlack.setEditable(false);
        add(textBlack);
       

        textWhite.setHorizontalAlignment(JTextField.CENTER);
        textWhite.setBounds(290,14,110,26);
        textWhite.setEditable(false);
        add(textWhite);
        
        JTextArea gInstruction=new JTextArea();
        gInstruction.setSelectedTextColor(new Color(238,238,238));
        String gSInstruction=
        "Play1(黑方) Key \nup--------W \ndown----S \nleft--------A   \nright------D \n\n"+
        "Play2(白方) Key \nup--------up \ndown----down \nleft--------left \nright------right \n\n"+
        "Exit game: \nPress Esc";
         gInstruction.setText(gSInstruction);
         gInstruction.setEditable(false);
         gInstruction.setBounds(440,60,100,340);
         add(gInstruction);
        
        ChessManPerformListener Perform=new ChessManPerformListener();
        addKeyListener(Perform);
        
    }
    
//    設定第一個JTextField輸出"請黑方下棋",坐标為(40,60)
     void Initialization(){        
        for(int i=0,j;i<18;i++)
            for(j=0;j<18;j++){
                ChessState[i][j]=0;                
             }
        cursor.setLocation(40,60);
        Cplayer=Black;
        textBlack.setText(textblack);
        textWhite.setText(Nothing);
    }
    
    
    //畫棋盤和初始化棋局狀态
    protected void paintComponent(Graphics g){
        super.paintComponent(g);
        Graphics2D g2=(Graphics2D) g;
         
        for(int i=60;i<=400;i+=20){
            g2.drawLine(40,i,380,i);
        }
        for(int j=40;j<=380;j+=20){
            g2.drawLine(j,60,j,400);
        }
        g2.drawString("_",cursor.x-6,cursor.y);
        g2.drawString("_",cursor.x,cursor.y);
        
        for(i=0;i<18;i++)
            for(j=0;j<18;j++){
                if(ChessState[i][j]!=0){
                if(ChessState[i][j]==1){
                    g2.setPaint(Black.getplayerChessManColor());        
            }
                if(ChessState[i][j]==2){
                g2.setPaint(White.getplayerChessManColor());
            }
            g2.fillOval(j*20+40-10, i*20+60-10, ChessMan.getChessManSize(), ChessMan.getChessManSize());
            }
        }
    }
    
   
    
    //判斷棋盤的目前位置是否已有棋子
    boolean isChessState(){ 
        this.j=(cursor.x-40)/20;
        this.i=(cursor.y-60)/20;
        if(ChessState[this.i][this.j]!=0)
            return true;
        else
            return false;        
    }
    
    
    
       
    //記錄落子後棋盤的目前位置的狀态
     void RecordChessState(){
         this.j=(cursor.x-40)/20;
        this.i=(cursor.y-60)/20;
        ChessState[this.i][this.j]=Cplayer.getCurrentIdentify();
    }
    
    
     
     
     
     
    //判斷目前玩家落子後是否赢了
    void JudgeWin(){
        for(int i=0;i<4;i++)
            if(JudgeWinLine(i)){
            //提示目前玩家已經獲得勝利
                try{
                    String Ginformation="GameInformation";
                    String Message="恭喜玩家"+Cplayer.getsIdentify()+"獲勝!"+"\n"+"繼續遊戲還是退出遊戲?";
                    String[] options = {"繼續","退出"};
                    int selection=JOptionPane.showOptionDialog(null,Message,Ginformation,
                         JOptionPane.YES_NO_OPTION,JOptionPane.INFORMATION_MESSAGE ,null,options,options[0]);//throws HeadlessException
                    if(selection==JOptionPane.OK_OPTION){                    
                           Initialization();
                           repaint();
                           return;
                      }
                    if(selection==JOptionPane.NO_OPTION){
                          System.exit(0);//退出程式
                     }
                
                  }catch(HeadlessException e){
                 e.printStackTrace();
             }
                }
        //如果目前方沒有赢棋則雙方輪換
        ChangeCurrentPlayer();
    }
     
     
     
    
    
    //在目前方向上是否有連續的五隻棋子
    boolean JudgeWinLine(int direction){
        int i,j,di,dj,count;
        i=j=di=dj=count=0;
        switch(direction){
        case 0:
            j=this.j-(testnum-1);
            i=this.i;
            dj=1;
            di=0;
            break;
        case 1:
            j=this.j;
            i=this.i-(testnum-1);
            dj=0;
            di=1;
            break;
        case 2:
            j=this.j-(testnum-1);
            i=this.i+(testnum-1);
            dj=1;
            di=-1;
            break;
        case 3:
            j=this.j-(testnum-1);
            i=this.i-(testnum-1);
            dj=1;
            di=1;
            break;
        }
        
       for(int k=0;k<testnum*2+1;k++){
           if(j>=0&&j<18&&i>=0&&i<18){
               if(ChessState[i][j]==Cplayer.getCurrentIdentify()){
                   count++;
                   if(count>=testnum)
                       return true;
               }
               else
                   count=0;
           }
           j+=dj;
           i+=di;
      } 
       return false;
}
    
    
    
    
    //更換目前玩家
    void ChangeCurrentPlayer(){
        if(Cplayer==Black){
            Cplayer=White;
            textBlack.setText(Nothing);
            textWhite.setText(textwhite);
        }
        else{
            Cplayer=Black;
            textBlack.setText(textblack);
            textWhite.setText(Nothing);
        }
    }
    
    
    
    
    
    
    //重新開局監聽器
private class RestartListener implements ActionListener{

        public void actionPerformed(ActionEvent arg0) {
            
            Initialization();
            repaint();
            requestFocus();
        } 
       }
    

       
       
       
       
       //棋盤、棋局狀态監聽器
private class ChessManPerformListener implements KeyListener{

      
      //玩家2的按鍵
           public void keyPressed(KeyEvent event) {
               int keyCode=event.getKeyCode();
                  if(keyCode==KeyEvent.VK_ESCAPE)
                        System.exit(0);
                  if(Cplayer.getCurrentIdentify()==2){//判别目前玩家
                       if(keyCode==KeyEvent.VK_LEFT){
                          if(cursor.x>40)
                            cursor.x-=20;
                       }
                   else if(keyCode==KeyEvent.VK_RIGHT){
                       if(cursor.x<380)
                           cursor.x+=20;
                       }
                   else if(keyCode==KeyEvent.VK_UP){
                       if(cursor.y>60)
                           cursor.y-=20;
                       }
                   else if(keyCode==KeyEvent.VK_DOWN){
                       if(cursor.y<400)
                            cursor.y+=20;
                       }
                   else if(keyCode==KeyEvent.VK_ENTER){
                            if(!isChessState()){
                         Cplayer.PerformChessMan();
                         RecordChessState();
                         repaint();
                         JudgeWin();//判定目前落子後是否赢棋
                         
                         }
                        
               }                      
                     repaint();                    
             }
       }

           
           
          

           
           
           public void keyReleased(KeyEvent event) {}

           
           
           
          //玩家1的按鍵
           public void keyTyped(KeyEvent event) {
               
               char keyChar=event.getKeyChar();
               if(Cplayer.getCurrentIdentify()==1){//判别目前玩家
               if(keyChar=='a'){
                   if(cursor.x>40)//對移動光标超界現象做判别
                        cursor.x-=20;
                   }
               else if(keyChar=='d'){
                   if(cursor.x<380)            
                       cursor.x+=20;
                   }
               else if(keyChar=='w'){
                   if(cursor.y>60)
                        cursor.y-=20;
                   }
               else if(keyChar=='s'){
                   if(cursor.y<400)
                        cursor.y+=20;
                   }    
               else if(keyChar==' '){
                   if(!isChessState()){      //落子前先判斷目前位置上是否已有棋子
                       Cplayer.PerformChessMan();//落子                     
                       RecordChessState();//記錄目前落子後棋盤狀态
                       repaint();
                          JudgeWin();//判定目前落子後是否赢棋
                       
                       } 
                }
            
        }
               repaint();    
           }

        }
          
}      
package WuZiGame;


import java.awt.Color;

class ChessMan {

    private static final int ChessManSize=20;
    private Color ChessManColor;
    
    ChessMan(Color c){
        ChessManColor=c;
    }

    
    
    static int getChessManSize(){
        return ChessManSize;
    }

    
    Color getChessManColor(){
        return ChessManColor;
    }
    
    
}      
package WuZiGame;

import java.awt.Color;


class Player {

    private int identify;
    private ChessMan pChessMan;
    private String PlayerStringIdentify;

    
    Player(int identify,Color c,String sIdentify){
        this.identify=identify;
        pChessMan=new ChessMan(c);
        this.PlayerStringIdentify=sIdentify;
    }
   

    
    int getCurrentIdentify(){
        return identify;
    }

    
    
    String getsIdentify(){
        return PlayerStringIdentify;
    }

    
    void PerformChessMan(){}
   

    
    Color getplayerChessManColor(){
        return pChessMan.getChessManColor();
    }
}      

【設計結果】

初始界面

結對實踐項目——“五子棋”小遊戲

下棋中

結對實踐項目——“五子棋”小遊戲

結束界面

結對實踐項目——“五子棋”小遊戲

【統計時間】

步驟 耗時 百分比
需求分析   1.5h  13.6%
設計  2h  18.2%
代碼實作  3h  27.3%
測試
分析總結  2.5h  22.7%

【實驗心得】

通過這次對Java的學習,讓我漸漸體會到了Java的博大精深。以及怎麼學習Java,怎麼學習計算機語言,怎樣對問題進行解決和運用Java GUI,查找的使用都用了更進一步的了解。而且這次兩人團隊工作,也讓我體會到合作的重要意義,兩個人的想法經過商讨,研究總會比一個人的好很多,兩個人事先做好分工工作再彙總整合也大大提高了效率。剛開始學習Java時我并不是非常的了解,知道就如何做能實作相應的功能,并沒有很深刻的去了解它為什麼要這麼做。這次實驗使我明白,真正的用Java去做一個東西不了解它是不行的,而且這個遊戲涉及到了Java 中許多的知識點,如Java圖形使用者界面設計、Java的異常處理機制、Java中的多線程程式設計、Java輸入輸出流,要應用這些東西更要求我去好好了解Java的這些規則。這次實驗,我還是收獲良多。雖然界面也不是很美觀,有點功能間的連接配接做的也不是特别的好,但是我能認識到自己的不足,并且在跟隊友的交流中也學到了一些的設計思路,也知道今後要加強哪些方面的知識。