• 題目簡介
1.棋盤是10乘以10的方框。
2.棋盤處於滑鼠監聽狀態,當滑鼠在棋盤上有點選操作的時候,程式會獲得滑鼠點選的座標然後換算成對應的棋盤的位置,在判斷此處是否有棋子,假如沒有,那麼在此處畫出對應顏色的實心棋子,假如已經有棋子了,則提示玩家此處已經有棋子請重新下棋。
3.無論黑白雙方哪一方有五個棋子沿著橫豎斜連在一起是,系統自動判斷輸贏,並顯示黑方或者白方勝利。
本程式共有3個類,下載後將三個類複製到三個記事本里然後重名記事本(為了閱讀方便分三個檔案,其中main()方法在StartChessJFrame類中。
• 程式碼地址
徐敏https://github.com/xumin1994/cooperation
韓爽https://github.com/hanshuangshuang/HEZUO
import java.awt.Color;
public class Point {
private int x;
//棋盤中X的索引
private int y;
//棋盤中Y的索引
private Color color;//顏色
public static final int DIAMETER = 30;
//直徑
public Point(int x,int y,Color color){
this.x=x;
this.y=y;
this.color =color;
}
//拿到棋盤中的Y索引
public int getX(){
return x;
}
public int getY(){
return y;
}
//得到顏色
public Color getColor(){
return color;
}
}
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseEvent;
/*
五子棋-棋盤類
*/
public class ChessBoard extends JPanel implements MouseListener {
public static final int MARGIN = 30;
//邊距
protected static final int GRID_SPAN = 35;
//網格間距
public static final int ROWS = 10;
//棋盤行數
public static final int COLS = 10;
//棋盤列數
Point[] chessList = new Point[(ROWS+1)*(COLS+1)];
//初始化每個陣列元素為null
boolean isBlack = true;
//預設開始是黑棋先下
boolean gameOver = false;
//遊戲是否結束
int chessCount;
//當前棋盤棋子的個數
int xIndex,yIndex;
//當前剛下的棋子的索引
public ChessBoard(){
super.setBackground(Color.ORANGE);
//setBackground(Color.ORANGE);//設定背景顏色為橘黃色
addMouseListener(this);//新增監聽器
addMouseMotionListener(new MouseMotionListener(){//匿名內部類
public void mouseDragged(MouseEvent e){
}
public void mouseMoved(MouseEvent e){
int x1 = (e.getX()- MARGIN +GRID_SPAN/2)/GRID_SPAN;
//將滑鼠單擊的座標位置轉換成網格索引
int y1 = (e.getY()- MARGIN +GRID_SPAN/2)/GRID_SPAN;
//遊戲已經結束,落在棋盤外,x、y位置已經有棋子存在,不能下
if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1))
setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
//設定成預設形狀
else
setCursor(new Cursor(Cursor.HAND_CURSOR));
//設定成手型
}
});
}
//繪製
public void paintComponent(Graphics g){
super.paintComponent(g);
//畫棋類
for(int i=0;i<=ROWS;i++){//畫橫線
g.drawLine(MARGIN,MARGIN+i*GRID_SPAN,MARGIN+COLS*GRID_SPAN,MARGIN+i*GRID_SPAN);
}
for(int i=0;i<=COLS;i++){//畫直線
g.drawLine(MARGIN+i*GRID_SPAN,MARGIN,MARGIN+i*GRID_SPAN,MARGIN+ROWS*GRID_SPAN);
}
//畫棋子
for(int i=0;i<chessCount;i++) {
int xPos = chessList[i].getX()*GRID_SPAN+MARGIN;
//網路交叉點的x座標
int yPos = chessList[i].getY()*GRID_SPAN+MARGIN;
//網路交叉點的y座標
g.setColor(chessList[i].getColor());//設定顏色
g.fillOval(xPos-Point.DIAMETER/2, yPos-Point.DIAMETER/2, Point.DIAMETER, Point.DIAMETER);
//標記最後一個棋子的紅矩形框
if(i == chessCount -1){
//最後一個棋子
g.setColor(Color.red);
g.drawRect(xPos - Point.DIAMETER/2,yPos-Point.DIAMETER/2,Point.DIAMETER,Point.DIAMETER);
}
}
}
//滑鼠按鍵在組建上按下時呼叫
public void mousePressed(MouseEvent e){
//遊戲已經結束,不能下
if(gameOver)
return;
String colorName = isBlack ?"黑棋":"白棋";
xIndex = (e.getX() - MARGIN + GRID_SPAN/2)/GRID_SPAN;
//將滑鼠單擊的座標位置轉換成網格索引
yIndex = (e.getY() - MARGIN + GRID_SPAN/2)/GRID_SPAN;
//落在棋盤外,不能下
if(xIndex <0 || xIndex > ROWS || yIndex < 0 || yIndex > COLS)
return;
//x、y位置都已經有棋子存在,不能下
if(findChess(xIndex , yIndex))
return;
Point ch = new Point(xIndex,yIndex,isBlack ? Color.black:Color.white);
chessList[chessCount++] = ch;
repaint();//通知系統重新繪製
if(isWin()){
//給出勝利資訊,不能再繼續下棋
String msg = String.format("恭喜,%s贏了!", colorName);
JOptionPane.showMessageDialog(this, msg);
gameOver = true;
}
isBlack = !isBlack;
}
//覆蓋MouseListener的方法
public void mouseClicked(MouseEvent e){
}//滑鼠按鍵在元件上單擊(按下並釋放)時呼叫
public void mouseEntered(MouseEvent e){
}//滑鼠進入到元件上時呼叫
public void mouseExited(MouseEvent e){
}//滑鼠離開元件時呼叫
public void mouseReleased(MouseEvent e){
}//滑鼠離開元件時呼叫
//在棋子陣列中查詢是否有索引為x、y的棋子存在
private boolean findChess(int x, int y){
for(Point c : chessList){
if(c !=null && c.getX() == x && c.getY() == y)
return true;
}
return false;
}
//判定哪方贏
private boolean isWin(){
int continueCount =1;
//連續棋子的個數
//橫向向西尋找
for(int x = xIndex-1; x>=0;x--){
Color c = isBlack ? Color.black : Color.white;
if(getChess(x,yIndex,c) !=null){
continueCount++;
}else
break;
}
//橫向向東尋找
for(int x =xIndex+1;x<=ROWS;x++){
Color c = isBlack ? Color.black : Color.white;
if(getChess(x,yIndex,c) !=null){
continueCount++;
}else
break;
}
//判定記錄數大於等於五,即表示此方取勝
if(continueCount>=5){
return true;
}else
continueCount =1;
//繼續另一種情況的搜尋:縱向
//縱向向上尋找
for(int y = yIndex - 1; y >= 0; y--){
Color c =isBlack ? Color.black : Color.white;
if(getChess(xIndex,y,c) !=null){
continueCount++;
}else
break;
}
//縱向向下尋找
for(int y = yIndex + 1; y<=ROWS; y++){
Color c = isBlack ? Color.black : Color.white;
if(getChess(xIndex,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount>=5){
return true;
}else
continueCount =1;
//繼續另一種情況的搜尋:斜向
//東北尋找
for(int x = xIndex + 1,y=yIndex-1; y>=0 && x<=COLS; x++,y--){
Color c = isBlack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
//西南尋找
for(int x = xIndex - 1,y=yIndex+1; y<=ROWS && x>=0; x--,y++){
Color c = isBlack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount >=5){
return true;
}else
continueCount = 1;
//繼續另一種情況的搜尋:斜向
//西北尋找
for(int x = xIndex - 1,y = yIndex-1; y>=0 && x>=0; x--,y--){
Color c = isBlack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
//西南尋找
for(int x = xIndex + 1,y=yIndex+1; y<=ROWS && x<=COLS; x++,y++){
Color c = isBlack ? Color.black : Color.white;
if(getChess(x,y,c)!=null){
continueCount++;
}else
break;
}
if(continueCount >=5){
return true;
}else
continueCount = 1;
return false;
}
private Point getChess(int xIndex, int yIndex, Color color){
for(Point c: chessList){
if(c !=null && c.getX() == xIndex && c.getY() == yIndex && c.getColor() == color)
return c;
}
return null;
}
public void restartGame(){
//清除棋子
for(int i=0; i< chessList.length; i++)
chessList[i]=null;
//恢復遊戲相關的變數值
isBlack = true;
gameOver = false;//遊戲是否結束
chessCount = 0;//當前棋盤的棋子個數
//System.out.println(this.toString());
//repaint();
}
//悔棋
public void goback(){
if (chessCount == 0)
return;
chessList[chessCount-1]=null;
chessCount--;
if(chessCount >0){
xIndex = chessList[chessCount -1].getX();
yIndex = chessList[chessCount -1].getY();
}
isBlack = !isBlack;
//repaint();
}
//Dimension:矩形
public Dimension getPreferredSize(){
return new Dimension (MARGIN*2 + GRID_SPAN*COLS,MARGIN*2 + GRID_SPAN*ROWS);
}
}
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
public class StartChessJFrame extends JFrame {
private ChessBoard chessBoard;
//對戰皮膚
private JPanel toolbar;
//工具條皮膚
private JButton startButton;
private JButton backButton;
private JButton exitButton;
//“重新開始”按鈕,“悔棋”按鈕,“退出”按鈕
private JMenuBar menuBar;
//選單欄
private JMenu sysMenu;
//系統選單
private JMenuItem startMenuItem;
private JMenuItem exitMenuIatem;
private JMenuItem backMenuItem;
//“重新開始”,“退出”和“悔棋”選單項
public StartChessJFrame(){
setTitle("單機版五子棋");
//設定標題
chessBoard =new ChessBoard();
//初始化皮膚物件
//建立和新增選單
menuBar = new JMenuBar();
//初始化選單欄
sysMenu = new JMenu("系統");
//初始化選單
startMenuItem = new JMenuItem("重新開始");
exitMenuIatem = new JMenuItem("退出");
backMenuItem = new JMenuItem("悔棋");
//初始化選單項
sysMenu.add(startMenuItem);
//將三個選單項新增到選單上
sysMenu.add(backMenuItem);
sysMenu.add(exitMenuIatem);
MyItemListener lis = new MyItemListener();
//初始化按鈕事件監聽器內部類
this.startMenuItem.addActionListener(lis);
//將三個選單項註冊到事件監聽器上
backMenuItem.addActionListener(lis);
exitMenuIatem.addActionListener(lis);
menuBar.add(sysMenu);
//將“系統”選單新增到選單欄上
setJMenuBar(menuBar);
//將menuBar設定為選單欄
toolbar =new JPanel();
//工具皮膚例項化
startButton = new JButton("重新開始");
//三個按鈕初始化
backButton = new JButton("悔棋");
exitButton = new JButton("退出");
toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));
//將工具皮膚按鈕用FlowLayout佈局
toolbar.add(startButton);
//將三個按鈕新增到工具皮膚上
toolbar.add(backButton);
toolbar.add(exitButton);
startButton.addActionListener(lis);
//將三個按鈕註冊監聽事件
backButton.addActionListener(lis);
exitButton.addActionListener(lis);
add(toolbar,BorderLayout.SOUTH);
//將工具皮膚佈局到介面“南”方也就是下面
add(chessBoard);//將皮膚物件新增到窗體上
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//設定介面關閉事件
//setSize(600,650);
pack();
//自適應大小
}
//事件監聽器內部類
private class MyItemListener implements ActionListener{
public void actionPerformed(ActionEvent e){
Object obj = e.getSource();
//取得事件源
if(obj == StartChessJFrame.this.startMenuItem || obj ==startButton){
//重新開始
//JFiveFrame.this //內部類引用外部類
System.out.println("重新開始...");
chessBoard.restartGame();
repaint();
}else if (obj == exitMenuIatem || obj == exitButton){
System.exit(0);
//結束應用程式
}else if (obj == backMenuItem || obj == backButton){
//悔棋
System.out.println("悔棋...");
chessBoard.goback();
repaint();
}
}
}
public static void main(String[] args){
StartChessJFrame f = new StartChessJFrame();
//建立主框架
f.setVisible(true);
//顯示主框架
}
}
• 結對分工情況
韓爽負責JUnit4的測試部分,徐敏負責程式碼編寫。
• 結對實踐過程
(1)對局雙方各執一色棋子。
(2)空棋盤開局。
(3)黑先、白後,交替下子,每次只能下一子。
(4)棋子下在棋盤的空白點上,棋子下定後,不得向其它點移動,不得從棋盤上拿掉或拿起另落別處。
(5)黑方的第一枚棋子可下在棋盤任意交叉點上。
(6)輪流下子是雙方的權利,但允許任何一方放棄下子權(即:PASS權)。
• 測試情況
• 問題及心得
通過這次綜合實驗,我們將Java程式設計語言所要掌握的基本知識加以貫穿,把分散的知識點提高到對java程式設計的整體認識,全面體驗java物件導向程式設計的特點,提高綜合應用能力。由對語言的基本理解向程式設計層面上轉變。