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
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
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