這個小遊戲是我和我姐們儿的JAVA課程設計,也是我做的第一個JAVA項目,適合初學者,希望能幫到那些被JAVA課設所困擾的孩紙們~~~
一、該遊戲需要實現
1、設計主框架,界面。
2、利用ActionListener接口實現按鈕事件的監聽。
3、重新開始功能的實現。
4、悔棋功能的實現。
5、退出功能的實現。
6、棋盤中棋子點類的定義。
7、利用MouseListener接口實現事件監聽,並實現接口裡的所有方法。
8、當鼠標移動到棋盤上的交點上,且該點上無棋子時能夠變成小手形狀。
9、點擊棋盤時,利用if語句判斷該點是否點在交點上,並利用foreach語句和棋子類中的getX(),getY()方法遍歷每一個棋子的位置判斷該點是否有棋子。
10、當判斷到可以在所點擊的點上下子時,畫棋子時利用for循環遍歷已有的每一個點並利用Graphics類的setColor設置顏色,利用Graphics類的fillOval方法設置形狀大小。
11、當畫完棋子時要及時判斷輸贏,用棋子所在索引和for循環遍歷最後一個棋子的各個方向,如果有在同一條直線上的棋子個數大於等於五的即當前棋子所代表的那方贏。
12、勝負已定的時候,能夠彈出相應的信息。
二、功能代碼實現
2.1進入遊戲
public static void main(String[] args) { StartChessJFrame f=new StartChessJFrame();//創建主框架f.setVisible(true);//顯示主框架}2.2初始化,定義一些要用到的量。
private ChessBoard chessBoard;//對戰面板private Panel toolbar;//工具條面板private Button startButton;//設置開始按鈕private Button backButton;//設置悔棋按鈕private Button exitButton;//設置退出按鈕
2.3界面的構造方法(遊戲的框架)
public StartChessJFrame(){ setTitle("單機版五子棋");//設置標題chessBoard=new ChessBoard();//初始化面闆對象,創建和添加菜單MyItemListener lis=new MyItemListener();//初始化按鈕事件監聽器內部類toolbar=new Panel();//工具面板欄實例化startButton=new Button("重新開始"); backButton=new Button("悔棋"); exitButton=new Button("退出");//三個按鈕初始化toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));//將工具面板按鈕用FlowLayout佈局toolbar.add(backButton); toolbar.add(startButton); toolbar.add(exitButton);//將三個按鈕添加到工具面板上startButton.addActionListener(lis); backButton.addActionListener(lis); exitButton.addActionListener(lis);//將三個按鈕事件註冊監聽事件add(toolbar,BorderLayout.SOUTH);//將工具面板佈局到界面南方也就是下面add(chessBoard);//將面闆對象添加到窗體上setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置界面關閉事件pack();//自適應大小}2.4按鈕的實現與監聽(構造方法內部)
MyItemListener lis=new MyItemListener();//初始化按鈕事件監聽器內部類toolbar=new Panel();//工具面板欄實例化startButton=new Button("重新開始"); backButton=new Button("悔棋"); exitButton=new Button("退出");//三個按鈕初始化toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));//將工具面板按鈕用FlowLayout佈局toolbar.add(backButton); toolbar.add(startButton); toolbar.add(exitButton);//將三個按鈕添加到工具面板上startButton.addActionListener(lis); backButton.addActionListener(lis); exitButton.addActionListener(lis);//將三個按鈕事件註冊監聽事件2.5按鈕事件的監聽
private class MyItemListener implements ActionListener{ public void actionPerformed(ActionEvent e) { Object obj=e.getSource();//獲取事件源if(obj==startButton){ System.out.println("重新開始...");//重新開始//JFiveFrame.this內部類引用外部類chessBoard.restartGame(); }else if(obj==exitButton){ System.exit(0);//結束應用程序}else if(obj==backButton){ System.out.println("悔棋...");//悔棋chessBoard.goback(); } } }2.6重新開始按鈕的功能實現
public void restartGame(){//清除棋子for(int i=0;i<chessList.length;i++) chessList[i]=null; /*恢復遊戲相關的變量值*/ isBack=true; gameOver=false;//遊戲是否結束chessCount=0;//當前棋盤的棋子個數repaint(); }2.7悔棋按鈕的功能實現
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(); } isBack=!isBack; repaint(); }2.8當棋盤根據需要變大或變小時窗口應隨之發生改變
//Dimension:矩形ChessBoard類內部public Dimension getPreferredSize(){ return new Dimension(MARGIN*2+GRID_SPAN*COLS,MARGIN*2+GRID_SPAN*ROWS); } pack();//自適應大小StartChessBoard類內部2.9定義棋子類
import java.awt.*; public class Point { private int x;//棋子在棋盤中的x索引值private int y;//棋子在棋盤中的y索引值private Color color;//顏色public static int DIAMETER=30;//直徑public Point(int x,int y,Color color){ this.x=x; this.y=y; this.color=color; } //得到棋子在棋盤中的x索引值public int getX(){ return x; } //得到棋子在棋盤中的y索引值public int getY(){ return y; } //得到棋子顏色public Color getColor(){ return color; } }三、功能部分代碼實現
3.1初始化,定義一些要用到的量。
public static int MARGIN=30;//邊距public static int GRID_SPAN=35;//網格間距public static int ROWS=18;//棋盤行數public static int COLS=18;//棋盤列數Point[] chessList=new Point[(ROWS+1)*(COLS+1)];//初始化每個數組元素為null boolean isBack=true;//默認開始是黑棋先下boolean gameOver=false;//遊戲是否結束int chessCount;//當前棋盤的棋子個數int xIndex,yIndex;//當前剛下棋子的索引
3.2棋盤對象的構造方法
public ChessBoard(){ setBackground(Color.LIGHT_GRAY);//設置背景顏色為灰色addMouseListener(this);//添加事件監聽器addMouseMotionListener(new MouseMotionListener() {//匿名內部類@Override 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;//將鼠標單擊的坐標位置轉化為網格索引if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1)){//遊戲已經結束,不能下;落在棋盤外,不能下;x,y位置已經有棋子存在,不能下setCursor(new Cursor(Cursor.DEFAULT_CURSOR));//設置成默認形狀}else{ setCursor(new Cursor(Cursor.HAND_CURSOR));//設置成手型} } @Override public void mouseDragged(MouseEvent e) { } }); }3.3設置鼠標監聽器,變小手(在構造方法內部)
addMouseMotionListener(new MouseMotionListener() {//匿名內部類@Override 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;//將鼠標單擊的坐標位置轉化為網格索引if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1)){//遊戲已經結束,不能下;落在棋盤外,不能下;x,y位置已經有棋子存在,不能下setCursor(new Cursor(Cursor.DEFAULT_CURSOR));//設置成默認形狀}else{ setCursor(new Cursor(Cursor.HAND_CURSOR));//設置成手型} } @Override public void mouseDragged(MouseEvent e) { } });3.4點擊棋盤時的鼠標按壓事件
public void mousePressed(MouseEvent e) {//鼠標按鍵在組件上按下時調用if(gameOver)//遊戲已經結束,不能下return ; String colorName=isBack ? "黑棋" : "白棋"; 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 ; if(findChess(xIndex,yIndex))//x,y位置已經有棋子存在,不能下return ; Point ch=new Point(xIndex,yIndex,isBack ? Color.black : Color.white); chessList[chessCount++]=ch; repaint();//通知系統重新繪製if(isWin()){ String msg=String.format("恭喜,%s贏啦~", colorName); JOptionPane.showMessageDialog(this, msg); gameOver=true; } else if(chessCount==(COLS+1)*(ROWS+1)) { String msg=String.format("棋鼓相當,棒棒噠~"); JOptionPane.showMessageDialog(this,msg); gameOver=true; } isBack=!isBack; }3.5繪製棋盤,棋子還有紅框框
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); } } }3.6判斷輸贏
/*判斷哪方贏*/ private boolean isWin(){ int continueCount=1;//連續棋子的個數for(int x=xIndex-1;x>=0;x--){//橫向向左尋找Color c=isBack ? Color.black : Color.white; if(getChess(x,yIndex,c)!=null){ continueCount++; }else break; } for(int x=xIndex+1;x<=ROWS;x++){//橫向向右尋找Color c=isBack ? 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=isBack ? Color.black : Color.white; if(getChess(xIndex,y,c)!=null){ continueCount++; }else break; } for(int y=yIndex+1;y<=ROWS;y++){//縱向向下尋找Color c=isBack ? 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=isBack ? 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=isBack ? 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=isBack ? 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=isBack ? Color.black : Color.white; if(getChess(x,y,c)!=null){ continueCount++; }else break; } if(continueCount>=5){//判斷記錄數大於等於五,即表示此方獲勝return true; }else continueCount=1; return false; }3.7彈出相應消息框(在鼠標按壓函數內部)
if(isWin()){ String msg=String.format("恭喜,%s贏啦~", colorName); JOptionPane.showMessageDialog(this, msg); gameOver=true; } else if(chessCount==(COLS+1)*(ROWS+1))//平局{ String msg=String.format("棋鼓相當,棒棒噠~"); JOptionPane.showMessageDialog(this,msg); gameOver=true; }3.8上面用到的一個判斷某點是否有棋子的函數
private boolean findChess(int x,int y){ for(Point c:chessList){ if(c!=null&&c.getX()==x&&c.getY()==y) return true; } return false; }3.9因為該棋盤類實現了鼠標監聽接口MonseListener,所以要重寫該接口內的所有方法,其它方法如下
@Override public void mouseClicked(MouseEvent e) {//鼠標按鍵在組件上單擊(按下並釋放)時調用} @Override public void mouseReleased(MouseEvent e) {////鼠標按鍵在組件上釋放時調用} @Override public void mouseEntered(MouseEvent e) {//鼠標進入組件時調用} @Override public void mouseExited(MouseEvent e){//鼠標離開組件時調用}四、運行結果
五、代碼匯總
該遊戲總共建了三個類,一個是界面StartChessJFrame,一個是棋盤類ChessBoard,一個是棋子類Point
5.1StartChessJFrame類
package chess.lcc.com; import javax.swing.*; import java.awt.event.*; import java.awt.*; /* * 五子棋的主框架,程序啟動類*/ public class StartChessJFrame extends JFrame { private ChessBoard chessBoard;//對戰面板private Panel toolbar;//工具條面板private Button startButton;//設置開始按鈕private Button backButton;//設置悔棋按鈕private Button exitButton;//設置退出按鈕public StartChessJFrame(){ setTitle("單機版五子棋");//設置標題chessBoard=new ChessBoard();//初始化面闆對象,創建和添加菜單MyItemListener lis=new MyItemListener();//初始化按鈕事件監聽器內部類toolbar=new Panel();//工具面板欄實例化startButton=new Button("重新開始"); backButton=new Button("悔棋"); exitButton=new Button("退出");//三個按鈕初始化toolbar.setLayout(new FlowLayout(FlowLayout.LEFT));//將工具面板按鈕用FlowLayout佈局toolbar.add(backButton); toolbar.add(startButton); toolbar.add(exitButton);//將三個按鈕添加到工具面板上startButton.addActionListener(lis); backButton.addActionListener(lis); exitButton.addActionListener(lis);//將三個按鈕事件註冊監聽事件add(toolbar,BorderLayout.SOUTH);//將工具面板佈局到界面南方也就是下面add(chessBoard);//將面闆對象添加到窗體上setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);//設置界面關閉事件pack();//自適應大小} private class MyItemListener implements ActionListener{ public void actionPerformed(ActionEvent e) { Object obj=e.getSource();//獲取事件源if(obj==startButton){ System.out.println("重新開始...");//重新開始//JFiveFrame.this內部類引用外部類chessBoard.restartGame(); }else if(obj==exitButton){ System.exit(0);//結束應用程序}else if(obj==backButton){ System.out.println("悔棋...");//悔棋chessBoard.goback(); } } } public static void main(String[] args) { StartChessJFrame f=new StartChessJFrame();//創建主框架f.setVisible(true);//顯示主框架} } 5.2ChessBoard類
package chess.lcc.com; 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 int MARGIN=30;//邊距public static int GRID_SPAN=35;//網格間距public static int ROWS=15;//棋盤行數public static int COLS=15;//棋盤列數Point[] chessList=new Point[(ROWS+1)*(COLS+1)];//初始化每個數組元素為null boolean isBack=true;//默認開始是黑棋先下boolean gameOver=false;//遊戲是否結束int chessCount;//當前棋盤的棋子個數int xIndex,yIndex;//當前剛下棋子的索引public ChessBoard(){ setBackground(Color.LIGHT_GRAY);//設置背景顏色為黃色addMouseListener(this);//添加事件監聽器addMouseMotionListener(new MouseMotionListener() {//匿名內部類@Override 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;//將鼠標單擊的坐標位置轉化為網格索引if(x1<0||x1>ROWS||y1<0||y1>COLS||gameOver||findChess(x1,y1)){//遊戲已經結束,不能下;落在棋盤外,不能下;x,y位置已經有棋子存在,不能下setCursor(new Cursor(Cursor.DEFAULT_CURSOR));//設置成默認形狀}else{ setCursor(new Cursor(Cursor.HAND_CURSOR));//設置成手型} } @Override public void mouseDragged(MouseEvent e) { } }); } /*繪製*/ 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); } } } @Override public void mousePressed(MouseEvent e) {//鼠標按鍵在組件上按下時調用if(gameOver)//遊戲已經結束,不能下return ; String colorName=isBack ? "黑棋" : "白棋"; 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 ; if(findChess(xIndex,yIndex))//x,y位置已經有棋子存在,不能下return ; Point ch=new Point(xIndex,yIndex,isBack ? Color.black : Color.white); chessList[chessCount++]=ch; repaint();//通知系統重新繪製if(isWin()){ String msg=String.format("恭喜,%s贏啦~", colorName); JOptionPane.showMessageDialog(this, msg); gameOver=true; } else if(chessCount==(COLS+1)*(ROWS+1)) { String msg=String.format("棋鼓相當,棒棒噠~"); JOptionPane.showMessageDialog(this,msg); gameOver=true; } isBack=!isBack; } @Override public void mouseClicked(MouseEvent e) {//鼠標按鍵在組件上單擊(按下並釋放)時調用} @Override public void mouseReleased(MouseEvent e) {////鼠標按鍵在組件上釋放時調用} @Override public void mouseEntered(MouseEvent e) {//鼠標進入組件時調用} @Override public void mouseExited(MouseEvent e){//鼠標離開組件時調用} 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=isBack ? Color.black : Color.white; if(getChess(x,yIndex,c)!=null){ continueCount++; }else break; } for(int x=xIndex+1;x<=ROWS;x++){//橫向向右尋找Color c=isBack ? 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=isBack ? Color.black : Color.white; if(getChess(xIndex,y,c)!=null){ continueCount++; }else break; } for(int y=yIndex+1;y<=ROWS;y++){//縱向向下尋找Color c=isBack ? 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=isBack ? 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=isBack ? 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=isBack ? 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=isBack ? 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; /*恢復遊戲相關的變量值*/ isBack=true; gameOver=false;//遊戲是否結束chessCount=0;//當前棋盤的棋子個數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(); } isBack=!isBack; repaint(); } //Dimension:矩形public Dimension getPreferredSize(){ return new Dimension(MARGIN*2+GRID_SPAN*COLS,MARGIN*2+GRID_SPAN*ROWS); } } 5.3Point類
package chess.lcc.com; import java.awt.*; public class Point { private int x;//棋子在棋盤中的x索引值private int y;//棋子在棋盤中的y索引值private Color color;//顏色public static int DIAMETER=30;//直徑public Point(int x,int y,Color color){ this.x=x; this.y=y; this.color=color; } //得到棋子在棋盤中的x索引值public int getX(){ return x; } //得到棋子在棋盤中的y索引值public int getY(){ return y; } //得到棋子顏色public Color getColor(){ return color; } }以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。