之前與小組同學合作過一起寫代碼,那時老師分工明确,寫兩部分代碼,一人負責一部分,剩下一個人做測試代碼,在老師詳盡的分工下,我們順利的完成了那次任務。
這次從無範圍自主選題,到熟練運用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的這些規則。這次實驗,我還是收獲良多。雖然界面也不是很美觀,有點功能間的連接配接做的也不是特别的好,但是我能認識到自己的不足,并且在跟隊友的交流中也學到了一些的設計思路,也知道今後要加強哪些方面的知識。