完整代码已上传到github上 地址 https://github.com/chenxin12138/repository 有需要的可以自取。
一、我们得实现一个15X15的界面
先使用顶级容器JFrame,然后经过重写重绘函数public void paint(Graphics g)实现,主要在GameMap类中实现
二、我们需要在棋盘上下黑白子,并进行记录那么就需要给整个棋盘添加响应函数并记录轮走方,并将电机为值通过计算始得棋子下到棋盘交叉处。在FrameListener函数中
实现五子棋界面需要的API类:
JFrame 顶级容器类
BorderLayout 框架布局类——把容器分为上北下南左西右东中间五个部分,每个部分只能添加一个组件。在这里我们需要把整个界面分为左右两部分。选择在框架布局的中间和右边两个部分。
这里我们还需要另一个容器类——JPanel 面板容器类。主要用来实现右边的部分,因为原本框架布局的右边部分只能添加一个组件,但是我们需要添加的组件不只一个,因此就先这个部分加上一个JPanel,然后再在JPanel上加我们需要的组件,包括按钮等等。
JFrame和JPanel的区别:JFrame是最底层的容器,JPanel放在它上面,同一个界面只有一个JFrame,但是一个JFrame上面可以有多个JPanel。相当于JFrame是一个大餐桌,JPanel是盘子,如果我们要对餐桌JFrame上的东西进行管理分类等,我们就需要使用这些JPanel盘子。
FlowLayout 流式布局类。因为我们右边的JPanel部分需要将按钮等组件由上到下进行排列。
JButton 按钮组件类
JComboBox 下拉列表框类——实现那个人人对战和人机对战的选择
Dimension 封装组件宽度和高度的类——组件类不能直接用setSize方法来设置
事件监听机制的类:
ActionListener 状态监听处理类
ActionEvent 状态监听事件,监听某个组件的状态是否有改变
MouseListener 鼠标监听处理类
MouseEvent 鼠标监听事件,里面包含鼠标被点击等事件的处理方法。当界面被点击时就放下一个棋子。
绘画所需要的类:
Graphics|Graphics2D 画笔类
Color 颜色类,需要设置画笔的颜色,实现黑白棋子
1、public void initUI()初始化函数,主要进行相框的绘制,采用BoardLayout 中间添加GameMap,GameMap的绘制主演实在paint重绘函数中,通过jf.add(this,BoardLayout.Center)添加到JFrame的中间位置。右侧添加JPanel实现按钮还有玩家信息。ButtonListener类实现三个按钮功能。setImage主要是设置图片大小
package Game;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
public class GameMap extends JPanel implements Image {
public int [][]board=new int[15][15];//存放棋盘落子
private int turn=0 ;//记录轮走方 1为玩家一,2位玩家二
public int []lastmove=new int[2];//记录最后一步位置
public ArrayList<Chessmove> chessmoves=new ArrayList<Chessmove>();//记录每一步棋子位置
public void initUI(){
//初始化一个界面,并设置标题大小等属性
Reset();//将board,turn置为初始值,进行新一句的棋局
JFrame jf=new JFrame();
jf.setTitle("五子棋");
jf.setSize(UIWIDTH,UIHIGHTH);
jf.setLocationRelativeTo(null);
jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
jf.setLayout(new BorderLayout());//设置顶级容器JFrame为框架布局
//实现左边的界面,把GoBangframe的对象添加到框架布局的中间部分
//已经有一个GameMap对象了,表示当前类的对象是this
this.setBackground(Color.WHITE);//设置下棋界面的颜色
//这里的话直接把左边的画板添加上去,指明是在框架布局的中间版块
jf.add(this,BorderLayout.CENTER);//添加到框架布局的中间部分
JPanel jp=new JPanel();
jp.setPreferredSize(dim1);//因采用了布局管理,不适用setsize,设置大小
jf.add(jp,BorderLayout.EAST);//添加到框架布局的东边部分
jp.setLayout(new FlowLayout());//设置JPanel为流式布局
//用户信息
String[] userMessage={"pic","昵称:尘心","性别:男","等级:新手"};
JLabel[] user =new JLabel[4];
//设置用户头像的大小
USERPICTURE.setImage(USERPICTURE.getImage().getScaledInstance(dim3.width, dim3.height, java.awt.Image.SCALE_DEFAULT ));
user[0]=new JLabel(USERPICTURE);
//设置Lable的大小
Dimension dim5=new Dimension(dim3.width,dim3.height+20);
user[0].setPreferredSize(dim5);
jp.add(user[0]);
for(int i=1;i<4;i++){
user[i]=new JLabel(userMessage[i]);
user[i].setPreferredSize(dim2);
/*
*利用setFont来设置TextField文本框输入信息的字体大小
*textx1.setFont(new Font(Font.DIALOG,Font.PLAIN,30));
*/
user[i].setFont(new Font(Font.MONOSPACED,Font.ITALIC,20));
jp.add(user[i]);
}
String []button_name={"开始新游戏","悔棋","认输"};
JButton []buttons=new JButton[3];
ImageIcon []BackGroundPictures={STARTBUTTON,BACKBUTTON,LOSEBUTTON};
for (int i = 0; i < 3; i++) {
BackGroundPictures[i].setImage(BackGroundPictures[i].getImage().getScaledInstance(dim4.width+20, dim4.height, java.awt.Image.SCALE_DEFAULT));
buttons[i]=new JButton(button_name[i],BackGroundPictures[i]);
buttons[i].setPreferredSize(dim4);
jp.add(buttons[i]);
}
ButtonLisener bu=new ButtonLisener(this);
for (int i = 0; i < 3; i++) {
buttons[i].addActionListener(bu);
}
FrameListener fl=new FrameListener(this);
this.addMouseListener(fl);
jf.setVisible(true);
}
//重写重绘方法
public void paint(Graphics g){
super.paint(g);
System.out.println(111111);
//引用图片
g.drawImage(CHESSBOARD, 0, 0,this.getWidth(), this.getHeight(), this);
//绘制棋盘
g.setColor(Color.BLACK);
for (int i = 0; i < 15; i++) {
g.drawLine(X,Y+SIZE*i,X+SIZE*14,Y+SIZE*i);
}
for (int i = 0; i < 15; i++) {
g.drawLine(X+SIZE*i,Y,X+SIZE*i,Y+SIZE*14);
}
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
if(board[i][j]==1){
int count_ai_x=i*SIZE+X;
int count_ai_y=j*SIZE+Y;
g.setColor(Color.BLACK);
g.fillOval(count_ai_x-15,count_ai_y-15,30,30);
}
else if(board[i][j]==2){
int count_ai_x=i*SIZE+X;
int count_ai_y=j*SIZE+Y;
g.setColor(Color.WHITE);
g.fillOval(count_ai_x-15,count_ai_y-15,30,30);
if(i==lastmove[0]&&j==lastmove[1]){
g.setColor(Color.RED);
g.drawRect(count_ai_x-15,count_ai_y-15,30,30);
}
}
}
}
}
public int getTurn(){
return turn;
}
public void ChangeTurn(){
if (turn==1)
turn=2;
else
turn=1;
}
public void Reset(){
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 15; j++) {
board[i][j]=0;
}
}
turn=0;
}
//对话框
public void PopUp(String top,String result) {
JOptionPane jo=new JOptionPane();
jo.showMessageDialog(null, result, top, JOptionPane.PLAIN_MESSAGE);
}
}
FrameListener为棋盘添加点击响应函数实现下棋。并计算出棋盘的交叉点,将其绘制在交叉点上。
package Game;
import javafx.css.Size;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
public class FrameListener implements MouseListener,Image {
private GameMap gm;
private ChessAI ai;
private static int step=0;
public FrameListener(GameMap gm){
this.gm=gm;//引用GameMap中的变量
this.ai=new ChessAI();
}
//下棋
@Override
public void mouseClicked(MouseEvent e) {
int x=e.getX();
int y=e.getY();
int count_x;
int count_y;
//计算交叉点
if((x-X)%SIZE>(int)(SIZE/2)){
count_x=X+SIZE*(int)((x-X)/SIZE+1);
}
else {
count_x=X+SIZE*(int)((x-X)/SIZE);
}
if((y-Y)%SIZE>(int)(SIZE/2)){
count_y=Y+SIZE*(int)((y-Y)/SIZE+1);
}
else {
count_y=Y+SIZE*(int)((y-Y)/SIZE);
}
Graphics g=gm.getGraphics();
int index_i=(count_x-X)/SIZE;
int index_j=(count_y-Y)/SIZE;
if((index_i<0)||(index_j<0)||(index_i>14)||(index_j>14))
return ;
//先手下棋为1,后手为2
if (gm.getTurn()==1){
if(gm.board[index_i][index_j]!=0){
gm.PopUp("错误提示","此处已经有棋子了,请下在其它地方");
}
else {
//gm.repaint();
g.fillOval(count_x-15,count_y-15,30,30);
Chessmove chessmove=new Chessmove(index_i,index_j);
gm.chessmoves.add(chessmove);
gm.board[index_i][index_j]=gm.getTurn();
step++;
g.setColor(Color.RED);
g.drawRect(count_x-15,count_y-15,30,30);
if(ai.CheckWin(gm.board,gm.getTurn())) {
gm.PopUp("胜者", "胜者黑方");
gm.repaint();
}
else
gm.ChangeTurn();
}
}
//智障通过FindBestmove(gm.board,gm.getTurn()函数通过博弈树算法得出最佳位置
if(gm.getTurn()==2)
{
gm.repaint();
int []bestmove=ai.FindBestmove(gm.board,gm.getTurn());
System.out.println("AIx+AIy"+bestmove[0]+" "+bestmove[1]);
g.setColor(Color.WHITE);
int count_ai_x=bestmove[0]*SIZE+X;
int count_ai_y=bestmove[1]*SIZE+Y;
g.fillOval(count_ai_x-15,count_ai_y-15,30,30);
Chessmove chessmove=new Chessmove(bestmove[0],bestmove[1]);
gm.chessmoves.add(chessmove);
System.out.println(11111);
gm.board[bestmove[0]][bestmove[1]]=gm.getTurn();
gm.lastmove=bestmove;
step++;
if(ai.CheckWin(gm.board,gm.getTurn())) {
gm.PopUp("胜者", "胜者白方");
gm.repaint();
gm.Reset();
}
else
gm.ChangeTurn();
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
idea jdk10.0.2
人工智障将在下一节细讲。
参考链接:https://blog.csdn.net/Alexwym/article/details/80847170