1. 程式人生 > >AI智慧人機對戰五子棋(Java實現圖形介面)

AI智慧人機對戰五子棋(Java實現圖形介面)

  • 簡述

這是本學期上完Java課後老師給出的課程設計題目,目的是:熟悉與掌握GUI程式設計;實現五子棋棋盤和棋子的繪製;實現遊戲AI以及對二維陣列的使用。

  • 介面效果圖

電腦先行,玩家輸贏圖:

玩家先行,玩家輸贏圖:

  • 整體設計

介面設計部分

這裡實現的是框架的主要介面設計(由4366中的線上五子棋修改而來),除棋盤之外的所有部分都在這裡完成,即標籤,圖片,按鈕的新增,框架邊框的去除,實現框架邊框去除後的拖動事件,按鈕的點選事件響應等。(這裡用到的圖片是在GoBang專案中的image資料夾中,後面用到的音樂是在GoBang專案中的music資料夾中,在編寫該程式時由程式設計師自己新增)

程式碼如下:

/**

* 2017年6月24日GoBang_main.java我和奧巴馬

*/

package GoBang;

import java.awt.Color;

import java.awt.Font;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.awt.event.MouseMotionAdapter;

import java.io.File;

import javax.swing.BorderFactory;

import

javax.swing.Icon;

import javax.swing.ImageIcon;

import javax.swing.JFrame;

import javax.swing.JLabel;

 

/**

*@author我和奧巴馬

*@date 2017年6月24日

* @filename GoBang_main.java

* @descriptionTODO

*/

public class GoBang_main extends JFrame{

    final

int X_LOCATION=300;

    finalint Y_LOCATION=5;

    finalint ROWS=16;

    finalint COLS=16;

    finalint R_SIZE=40;

    int xOld,yOld;

    static JLabel jl[]=new JLabel[9];

    static boolean FLAG=false;

    Icon icWhite=new ImageIcon("image/White.png");

    static IconicBlack=new ImageIcon("image/Black.png");

    Icon icst=new ImageIcon("image/stop.png");

    Icon icpl=new ImageIcon("image/play.png");

    String strmu="music"+File.separator+"IF YOU-BIGBANG.wav";

    public GoBang_main(){

        this.setBounds(X_LOCATION,Y_LOCATION, COLS*R_SIZE+170,ROWS*R_SIZE+90);

        this.setLayout(null);

        this.getContentPane().setBackground(new Color(51,51,51));

        

        //棋譜面板

        GoChessgochess=new GoChess();//中央黃色面板

        gochess.setBounds(25,70,COLS*R_SIZE,ROWS*R_SIZE);

        this.add(gochess);

        

        //五子棋標籤

        jl[0]=new JLabel("五子棋",JLabel.CENTER);//中央上方標籤

        jl[0].setFont(new Font("華文行楷",Font.BOLD,25));//字型

        jl[0].setForeground(Color.WHITE);//文字顏色

        jl[0].setBounds(25, 20,COLS*R_SIZE, 40);//位置大小

        jl[0].setOpaque(true);//設定背景透明

        jl[0].setBackground(new Color(156,102,31)); //設定背景色

        this.add(jl[0]);

        

        //右邊功能

        jl[1]=new JLabel(new ImageIcon("image/Computer.png"));//電腦圖片

        jl[1].setBounds(685, 100, 50, 50);

        jl[2]=new JLabel(icBlack);//黑棋

        jl[2].setBounds(745, 110, 30, 30);

     

        Fontf=new Font("華文楷體",Font.BOLD,15);//右邊文字顏色

        jl[3]=new JLabel("電腦黑棋,先行",JLabel.LEFT);

        jl[3].setBounds(685, 150, 115, 50);

     

        jl[4]=new JLabel(new ImageIcon("image/User.PNG"));//使用者圖片

        jl[4].setBounds(685, 230, 50, 50);

        JLabeljlw=new JLabel(icWhite);//白棋

        jlw.setBounds(745, 240, 30, 30);

         

        jl[5]=new JLabel("玩家白棋,後行",JLabel.LEFT);

        jl[5].setBounds(685, 280, 115, 50);

        

        jl[6]=new JLabel("開始遊戲",JLabel.CENTER);

        jl[6].setBounds(685, 360, 115, 30);

        jl[6].addMouseListener(new MouseAdapter(){ //是電腦先

            publicvoid mouseExited(MouseEvente){ //滑鼠移開事件監聽

                jl[6].setBackground(new Color(186,160,10));

            }

            publicvoid mouseEntered(MouseEvente){ //滑鼠進入事件監聽

                jl[6].setBackground(new Color(214,200,100));

            }

            publicvoid mouseClicked(MouseEvente){ //滑鼠點選事件監聽

                    for(inti=1;i<=COLS;i++){

                        for(intj=1;j<=ROWS;j++){

                            GoChess.blank(i,j); //棋譜置空

                        }

                    }

                    repaint();

                    FLAG=true;//給標誌給JPanel讓其響應滑鼠點選落點

                    jlw.setIcon(icWhite);

                    jl[2].setIcon(icBlack);

                    jl[3].setText("電腦黑棋,先行");

                    jl[5].setText("玩家白棋,後行");

                    GoChess.sureMove(COLS/2,ROWS/2,GoChess.computerColor);//電腦第一顆棋的位置

                    GoChess.audio(GoChess.strClick);

                    repaint();

                    jl[6].setText("重新開始");//點選開始後,換內容

            }

        });

        jl[7]=new JLabel("玩家先行",JLabel.CENTER);

        jl[7].setBounds(685, 430, 115, 30);

        jl[7].addMouseListener(new MouseAdapter(){ //玩家先

            publicvoid mouseExited(MouseEvente){

                jl[7].setBackground(new Color(186,160,10));

            }

            publicvoid mouseEntered(MouseEvente){

                jl[7].setBackground(new Color(214,200,100));

            }

            publicvoid mouseClicked(MouseEvente){

                for(inti=1;i<=COLS;i++){

                    for(intj=1;j<=ROWS;j++){

                        GoChess.blank(i,j); //棋譜置空

                    }

                }

                repaint();

                FLAG=true;//給標誌給JPanel讓其響應滑鼠點選落點

                jlw.setIcon(icBlack);//對應的棋色互換

                jl[2].setIcon(icWhite);

                jl[3].setText("電腦白棋,後行");//標籤提示互換

                jl[5].setText("玩家黑棋,先行");

            }

        });

        

        JLabeljlm=new JLabel(new ImageIcon("image/music.PNG"));//音樂圖片

        jlm.setBounds(685, 550, 50, 50);

        JLabeljlp=new JLabel(icst);//暫停圖片

        jlp.setBounds(745, 558, 40, 40);

        jlp.addMouseListener(new MouseAdapter(){

            publicvoid mouseClicked(MouseEvente){

                if(e.getClickCount()==1){

                    jlp.setIcon(icpl);//換成暫停圖示

                    GoChess.audio(strmu);

                }

            }

        });

        

        jl[8]=new JLabel("退出",JLabel.CENTER);//退出標籤

        jl[8].setBounds(685, 500, 115, 30);

        jl[8].addMouseListener(new MouseAdapter(){

            publicvoid mouseExited(MouseEvente){

                jl[8].setBackground(new Color(186,160,10));

            }

            publicvoid mouseEntered(MouseEvente){

                jl[8].setBackground(new Color(214,200,100));

            }

            publicvoid mouseClicked(MouseEvente){

                System.exit(0);

            }

        });

        for(inti=1;i<9;i++){//加元件

            jl[i].setFont(f);

            if(i==6||i==7||i==8){

                jl[i].setOpaque(true);

                jl[i].setBackground(new Color(186,160,10));

                //設定邊框

                jl[i].setBorder(BorderFactory.createMatteBorder(1, 1, 1, 1, new Color(186,160,10)));

            }

            this.add(jl[i]);

            this.add(jlp);

            this.add(jlm);        

            this.add(jlw);

            if(i==3||i==5)

                jl[i].setForeground(Color.WHITE);//設定字型白色

        }

        

        this.setUndecorated(true);

        this.setVisible(true);

        this.setResizable(false);

        this.addMouseListener(new MouseAdapter(){

            publicvoid mousePressed(MouseEvente){ //滑鼠壓監聽

                xOld=e.getX();//獲得x

                yOld=e.getY();//獲得y

            }

        });

        this.addMouseMotionListener(new MouseMotionAdapter(){ //框架拖動

            publicvoid mouseDragged(MouseEvente){

                intxOnScreen=e.getXOnScreen();//獲得螢幕上的點x座標

                intyOnScreen=e.getYOnScreen();//獲得螢幕上的點y座標

                intxNew=xOnScreen-xOld;//得到的新點x

                intyNew=yOnScreen-yOld;//得到的新點y

                GoBang_main.this.setLocation(xNew,yNew);//實現框架的拖動

            }

        });

    }

    publicstaticvoid main(Stringargs[]){

        new GoBang_main();

    }

}

五子棋繪製部分

這裡包括給出棋譜的繪製(在Jpanel 子類中完成),棋子的繪製,評估函式(給每種情況打分,然後可以統計棋盤上的優劣情況),判斷輸贏等一系列函式,是整個專案中最重要部分。(繪製棋盤和棋子,棋盤分為15行15列,棋子分黑白兩種,用顏色去區分,用paint函式去繪製棋盤和棋子,再用一個2維陣列去儲存棋盤中的棋子的顏色值(在這裡空子為0,黑色為1,白色為2))。

程式碼如下:

/**

* 2017年6月24日.java我和奧巴馬

*/

package GoBang;

import java.io.File;

import java.awt.Color;

importjava.awt.Dimension;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.event.MouseAdapter;

import java.awt.event.MouseEvent;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

importjava.net.MalformedURLException;

import javax.swing.JPanel;

importsun.audio.AudioPlayer;

importsun.audio.AudioStream;

 

/**

*@author我和奧巴馬

*@date 2017年6月24日

* @fileROWSame GoChess.java

* @descriptionTODO

*/

publicclassGoChessextends JPanel{

    finalstaticint ROWS=16;

    finalstaticint COLS=16;

    finalint R_SIZE=40;

    staticint BLACK=1;

    staticint WHITE=2;

    staticint EMPTY=0;

    staticint userColor=WHITE;

    staticint computerColor=BLACK;

    staticint table[][]=newint[COLS+1][ROWS+1];   

    staticint i,j;

    booleanFLAG1=false;

    booleanFLAG2=false;

    static StringstrClick="music"+File.separator+"sale.wav";

    String strSuccess="music"+File.separator+"success.wav";

    String strFailure="music"+File.separator+"failure.wav";

    public GoChess(){

        this.addMouseListener(new MouseAdapter(){

            publicvoid mouseClicked(MouseEvente){

                intx=e.getX();

                inty=e.getY();

                if(x>=20&&x<COLS*R_SIZE-20&&y>=20&&y<ROWS*R_SIZE-20){//設定滑鼠響應範圍==左半邊和右半邊點選時沒反應

                    i=(x-20)/40+1;//對映成相應的x座標

                    j=(y-20)/40+1;//對映成相應的y座標

                }

                mouseClick();//新增響應函式

            }    

        });

    }

    publicvoid mouseClick(){

        if(GoBang_main.FLAG){//必須點選《開始遊戲》或者《玩家先行》才有效

            if(isEmpty(i,j)){    

                sureMove(i,j,userColor);//使用者落子

                intyn=isEnd(i,j,userColor);//判斷使用者贏

                if(yn!=0){

                    FLAG1=true;//響應paint裡的畫字串

                    repaint();

                    GoBang_main.jl[6].setText("開始遊戲");//贏了就把重新開始換為開始遊戲

                    return;

                }

                repaint();

                intcomputer[]=Computer.getNext(computerColor);//電腦落子位置

                sureMove(computer[0],computer[1],computerColor);//電腦落子

                audio(strClick);//提示電腦落子聲音 ===海浪

                yn=isEnd(computer[0],computer[1],computerColor);

                if(yn!=0){

                    FLAG2=true;

                    repaint();

                    GoBang_main.jl[6].setText("開始遊戲");

                    return;

                }

                repaint();

            }

        }

    }

    publicstaticvoid audio(Stringstr){ //新增音樂函式

        FileInputStreamfile=null;

        try {

            file=new FileInputStream(str);

            AudioStreamas=new AudioStream(file);    

            AudioPlayer.player.start(as);

        } catch (FileNotFoundException e) {

            e.printStackTrace();

        } catch (IOException e) {

            e.printStackTrace();

        }

    }

    

    publicstaticboolean isEmpty(inti,intj){//判斷是否為空

        returntable[i][j]==EMPTY;

    }

    publicstaticvoid sureMove(inti,intj,intcolor){//落棋子

        table[i][j]=color;

    }

    publicstaticvoid blank(inti,intj){//撤回棋子

        table[i][j]=EMPTY;

    }        

    

    publicvoid drawPieces(intcolor,intx,inty,Graphicsg){ //畫棋子

        if(GoBang_main.jl[2].getIcon()==GoBang_main.icBlack){//電腦黑棋,顏色為1

            if(color==BLACK){

                g.setColor(new Color(0,0,0));

                //左右半徑19,上下為39/2

                g.fillArc(x*R_SIZE-19,y*R_SIZE-19, 39, 39, 0, 360); //((x-20)/40+1)*RIZE-19

            }                

        }

        else{//電腦白棋,顏色為2

            if(color==BLACK){

                g.setColor(new Color(255,255,255));

                g.fillArc(x*R_SIZE-19,y*R_SIZE-19, 39, 39, 0, 360);

            }

        }

        if(GoBang_main.jl[2].getIcon()!=GoBang_main.icBlack){//電腦白棋,白色

            if(color==WHITE){

                g.setColor(new Color(0,0,0));

                g.fillArc(x*R_SIZE-19,y*R_SIZE-19, 39, 39, 0, 360);

            }                

        }

        else{//電腦黑棋,顏色黑

            if(color==WHITE){

                g.setColor(new Color(255,255,255));

                g.fillArc(x*R_SIZE-19,y*R_SIZE-19, 39, 39, 0, 360);

            }

        }

    }

    

    publicvoid paint(Graphicsg){

        g.setColor(new Color(208,152,69));

        g.fillRect(0,0,COLS*R_SIZE,ROWS*R_SIZE);

        g.setColor(Color.DARK_GRAY);

        for(inti=1;i<COLS;i++){

            g.drawLine(R_SIZE*i,R_SIZE,R_SIZE*i, (ROWS-1)*R_SIZE);//畫豎線

        }

        for(intj=1;j<ROWS;j++){

            g.drawLine(R_SIZE,R_SIZE*j,(COLS-1)*R_SIZE,R_SIZE*j);//畫橫線

        }

        g.setColor(new Color(0,0,0));

        //畫五個定位點

        g.fillArc(8*R_SIZE-5, 8*R_SIZE-5, 10, 10, 0, 360); //

        g.fillArc(4*R_SIZE-5, 4*R_SIZE-5, 10, 10, 0,360); //左上

        g.fillArc(12*R_SIZE-5, 4*R_SIZE-5, 10, 10, 0, 360); //右上

        g.fillArc(4*R_SIZE-5, 12*R_SIZE-5, 10, 10, 0, 360); //左下

        g.fillArc(12*R_SIZE-5, 12*R_SIZE-5, 10, 10, 0, 360); //右下

        

        for(inti=1;i<=COLS;i++){

            for(intj=1;j<=ROWS;j++){

                if(!isEmpty(i,j))

                    drawPieces(table[i][j],i,j,g);//畫棋子

            }

        }

        if(FLAG1){

            g.setColor(Color.RED);

            g.setFont(new Font("隸書",Font.BOLD,50));//紅色提示贏

            g.drawString("贏了", 1*R_SIZE-5,8*R_SIZE-5);

            audio(strSuccess);//贏了的wav