记得第一天是完成了页面,棋子没完成
我们需要先知道
JFrame是最底层,JPanel是置于其面上,同一个界面只有一个JFrame,一个JFrame可以放多个JPanelJFrame是窗口,JPanel是面板,窗口可以有最大最小化,标题栏图标,面板没有。JFrame是界面组件的容器,JPanel也是容器,但是任何组件包括Panel的显示都依赖于JFrame
一 绘制左侧的棋盘
使用一个叫作JPanel来实现,棋盘的尺寸委650*700,背景颜色是Color.ORANGE
把棋盘这个JPanel添加到JFrame的西侧:
this.add(new GoBangPanel(),BorderLayout.WEST);
绘制一下内容,需要重写JPanelpaintComponent(Graphics g)进行绘制,把g转换Graphics2D g2d对象,进行2d画画。
** 绘制棋盘线,**
定义偏移量是40,单元格的宽度为40,分别
绘制横线 x不变,y变
绘制竖线 x变,y不变
设置线的宽度g2D.setStroke(new BasicStroke(2));
绘制天元和星,
天元:棋盘的中心点
星:4个,每个距角向内的第三个。
天元和星的宽度为8
使用g2D.fiilOval()的方法,找到点的坐标减去宽度的一半
绘制预选框
预选框坐标的偏移量是单元格的一半,线长为单元格的1/4,在某点绘制预选框;
规则:在(x,y)点的向外(上下左右)移出一半的距离,然后绘制1/4线坐标和实际坐标之间的转换:
g2D.setColor(Color.RED);
g2D.setColor(Color.BLACK);
绘制左侧数字和底部的字母(15)
给棋子添加序号
二.绘制右侧功能区
1.添加显示棋子估值信息的区域
模式:人人,人机
智能:估值函数
估值函数+搜索树
2. 搜素
搜索深度
每层结点
其他
显示落棋子顺序
悔棋
---------------------------------------------------------------------------------------------
public class Text {
public static void main(String args[]){
GameFrame gameFrame=new GameFrame();
gameFrame.start();
}
}
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.net.URL;
import javax.swing.*;
import javax.swing.border.TitledBorder;
import javax.swing.plaf.basic.BasicBorders.RadioButtonBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.LinkedList;
import javax.swing.ImageIcon;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
public class GameFrame extends JFrame {
//棋盘宽度650*700 偏移量 40*40 单元格象素 天元和星
//左边为BorderLayout、右边为BoxLayout
GamePanel gamePanel=new GamePanel();
JButton huiQi=new JButton("悔棋");
JRadioButton renren=new JRadioButton("人人");
JRadioButton renji=new JRadioButton("人机");
JRadioButton guzhi=new JRadioButton("估值函数");
JRadioButton guzhiAndTree=new JRadioButton("估值函数+搜索树");
JComboBox<Integer>depth=new JComboBox<Integer>(new Integer[]{1,3,5});
JComboBox<Integer>nodeCount=new JComboBox<Integer>(new Integer[]{3,5,10});
JCheckBox showOrder=new JCheckBox("显示落子顺序");
JButton newGame=new JButton("新游戏");
JButton openMusic=new JButton("开启音效");
JButton closeMusic=new JButton("关闭音效");
// JTextArea area=new JTextArea();
public static JTextArea area=new JTextArea(20,100);
public void start(){
this.setTitle("五子棋");
this.setIconImage(Toolkit.getDefaultToolkit().createImage(
"F:\\IntellijIdea_workplace\\untitled6\\img\\Neogeo Logo.png"));// 给窗体添加一个图标
this.add(gamePanel,BorderLayout.WEST);
this.setResizable(true);
this.setSize(900,700);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//添加控键
JPanel rightPanel=new JPanel();
rightPanel.setLayout(new BoxLayout(rightPanel,BoxLayout.Y_AXIS));
JPanel panel1=new JPanel();
area.setEditable(true);
add(new JScrollPane (area));
panel1.setBorder(new TitledBorder("右键单击显示可参考的棋子坐标"));
panel1.add(area);
rightPanel.add(panel1);
JPanel panel2=new JPanel();
panel2.setBorder(new TitledBorder("模式"));
ButtonGroup group=new ButtonGroup();
panel2.add(renren);
panel2.add(renji);
group.add(renren);group.add(renji);
JPanel panel3=new JPanel();
panel3.setBorder(new TitledBorder("智能"));
ButtonGroup group1=new ButtonGroup();
group1.add(guzhi);
group1.add(guzhiAndTree);
panel3.add(guzhi);
panel3.add(guzhiAndTree);
rightPanel.add(panel3);
JPanel panel4 = new JPanel();
panel4.setBorder(new TitledBorder("搜索树"));
panel4.add(new JLabel("搜索深度"));
panel4.add(depth);
panel4.add(new JLabel("每层结点数"));
panel4.add( nodeCount);
rightPanel.add(panel4);
JPanel panel5 = new JPanel();
//border显示标题
panel5.setBorder(new TitledBorder("其他"));
panel5.add(huiQi);
panel5.add(showOrder);
rightPanel.add(panel5);
rightPanel.add(newGame);
rightPanel.add(openMusic);
rightPanel.add(closeMusic);
add(rightPanel);
this.setVisible(true);
}
}
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Image;
import java.util.LinkedList;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class GamePanel extends JPanel {
private int tx,ty;
public GamePanel(){
this.setBackground(Color.ORANGE);
this.setPreferredSize(new Dimension(650,700));
tx=0;ty=0;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;//将基本的绘图强转为2D绘图
//绘制棋盘线
g2d.setStroke(new BasicStroke(3.0f));//设定外圈粗细,将原有线条的粗细放大为原来的三倍大小
drawLine(g2d);
drawStar(g2d);
drawTips(g2d,(15/2)*40+40,(15/2)*40+40);
drawNumber( g2d );
}
//绘制棋盘线
private void drawLine(Graphics g2d){
//偏移量 x,y都为40
int offset=40;
//2条线之间的距离
int cell_width=40;
//从(x1,y1)到(x2,y2)之间画一条线
//水平方向为x轴,竖直方向为y轴
//画横线x,y1,y2同
//这里(15-1)不能换成14
for (int i=0;i<15;i++){
g2d.drawLine(offset,offset+i*cell_width,offset+(15-1)*cell_width,offset+i*cell_width);
}
//画竖线
for (int i=0;i<15;i++){
g2d.drawLine(offset+i*cell_width,offset,offset+i*cell_width,offset+(15-1)*cell_width);
}
}
//绘制天元和星 半径为8
private void drawStar( Graphics2D g2d ) {
//在x,y绘制一个点,drawOval绘制的是一个空心(到圆心距离)
//计算天元的点的坐标是40
//计算天元的星
g2d.fillOval((15/2)*40+40-4,(15/2)*40+40-4,8,8);
//左上角的星
g2d.fillOval((15/4)*40+40-4,(15/4)*40+40-4,8,8);
//左下角的星
g2d.fillOval((15/4)*40+40-4,(15-15/4-1)*40+40-4,8,8);
//右上角的星
g2d.fillOval((15-15/4-1)*40+40-4,(15/4)*40+40-4,8,8);
//右下角的星
g2d.fillOval((15-15/4-1)*40+40-4,(15-15/4-1)*40+40-4,8,8);
}
//绘制预选框
private void drawTips(Graphics g2d,int x,int y){
g2d.setColor(Color.red);
//左上角向右
g2d.drawLine(x-40/2,y-40/2,x-40/4,y-40/2);
//左上角向下
g2d.drawLine(x-40/2,y-40/2,x-40/2,y-40/4);
//右上角向左
g2d.drawLine(x+40/2,y-40/2,x+40/4,y-40/2);
//右上角向下
g2d.drawLine(x+40/2,y-40/2,x+40/2,y-40/4);
//左下角向右
g2d.drawLine(x-40/2, y+40/2, x-40/4, y+40/2);
//左下角向上
g2d.drawLine(x-40/2, y+40/2, x-40/2, y+40/4);
//右下角向左
g2d.drawLine(x+40/2,y+40/2,x+40/4,y+40/2);
//右下角向上
g2d.drawLine(x+40/2,y+40/2,x+40/2,y+40/4);
}
//绘制边缘的数字和字母
private void drawNumber( Graphics2D g2d ) {
Font font = new Font("微软雅黑", Font.BOLD, 14);
g2d.setFont(font);
g2d.setColor(Color.BLACK);
FontMetrics fm = g2d.getFontMetrics();
int heigth = fm.getAscent();//获取文本的高度
//绘制数字,列方向
for (int i = 0; i < 15; i++) {
int x = 9;//Game.OFFSET;
int y = i * 40 +40+ heigth / 2;
g2d.drawString((15 - i) + " ", x, y);
}
//绘制字母
for (int i = 0; i < 15; i++) {
int base = (int) 'A';
int x = i * 40 +40;
int y =15 * 40 + 30;
g2d.drawString((char) (base + i) + "", x, y);
}
}
}
效果
未来方便后期修改,改变一些变量值,我们需要设置一些与棋盘页面有关的规定为常数。
定义了一个与棋盘有关的类GameUtil:
public class GameUtil { //工具类
//下面定义一些常量
//游戏界面的宽度
public static final int GAME_WINDTH=900;
public static final int GAME_HEIGHT=700;
public static final int PANEL_WIDTH=650;
public static final int PANEL_HEIGHT=700;
public static final int OFFSET=40;
public static final int CELL_WIDTH=40;//线框
public static final int LINE_COUNT= 15;
public static final int STAR_WIDTH=8;
}
相应的GamePanel里的数值要变
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.MouseMotionListener;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Image;
import java.util.LinkedList;
import javax.swing.ImageIcon;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
public class GamePanel extends JPanel {
private int tx,ty;
public GamePanel(){
this.setBackground(Color.ORANGE);
this.setPreferredSize(new Dimension(GameUtil.PANEL_WIDTH, GameUtil.PANEL_HEIGHT));
tx=0;ty=0;
}
protected void paintComponent(Graphics g){
super.paintComponent(g);
Graphics2D g2d=(Graphics2D)g;//将基本的绘图强转为2D绘图
//绘制棋盘线
g2d.setStroke(new BasicStroke(3.0f));//设定外圈粗细,将原有线条的粗细放大为原来的三倍大小
drawLine(g2d);
drawStar(g2d);
drawTips(g2d ,(GameUtil.LINE_COUNT/2+1)*GameUtil.OFFSET,(GameUtil.LINE_COUNT/2+1)*GameUtil.OFFSET);
drawNumber( g2d );
}
//绘制棋盘线
private void drawLine(Graphics g2d){
//偏移量 x,y都为40
int offset=40;
//2条线之间的距离
int cell_width=40;
//从(x1,y1)到(x2,y2)之间画一条线
//水平方向为x轴,竖直方向为y轴
//画横线x,y1,y2同
//这里(15-1)不能换成14
for (int i=0;i<15;i++){
g2d.drawLine(offset,offset+i*cell_width,offset+(15-1)*cell_width,offset+i*cell_width);
}
//画竖线
for (int i=0;i<15;i++){
g2d.drawLine(offset+i*cell_width,offset,offset+i*cell_width,offset+(15-1)*cell_width);
}
}
//绘制天元和星 半径为8
private void drawStar( Graphics2D g2d ) {
//在x,y绘制一个点,drawOval绘制的是一个空心(到圆心距离)
//计算天元的点的坐标是40
//计算天元的星
g2d.fillOval((GameUtil.LINE_COUNT / 2) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
(GameUtil.LINE_COUNT / 2) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
GameUtil.STAR_WIDTH, GameUtil.STAR_WIDTH
);
// g2d.fillOval((15/2)*40+40-4,(15/2)*40+40-4,8,8);
//左上角的星
g2d.fillOval((GameUtil.LINE_COUNT / 4) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
(GameUtil.LINE_COUNT / 4) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
GameUtil.STAR_WIDTH, GameUtil.STAR_WIDTH
);
//左下角的星
g2d.fillOval((GameUtil.LINE_COUNT / 4) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
(GameUtil.LINE_COUNT - GameUtil.LINE_COUNT / 4 - 1) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
GameUtil.STAR_WIDTH, GameUtil.STAR_WIDTH
);
//右上角的星
/* 空心椭圆
g2d.drawOval((GameUtil.LINE_COUNT-GameUtil.LINE_COUNT / 4-1) * GameUtil.CELL_WIDTH+GameUtil.OFFSET-GameUtil.STAR_WIDTH/2,
(GameUtil.LINE_COUNT/4)*GameUtil.CELL_WIDTH+GameUtil.OFFSET-GameUtil.STAR_WIDTH/2,
GameUtil.STAR_WIDTH,GameUtil.STAR_WIDTH
);
*/
g2d.fillOval((GameUtil.LINE_COUNT - GameUtil.LINE_COUNT / 4 - 1) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
(GameUtil.LINE_COUNT / 4) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
GameUtil.STAR_WIDTH, GameUtil.STAR_WIDTH
);
//右下角的星
g2d.fillOval((GameUtil.LINE_COUNT - GameUtil.LINE_COUNT / 4 - 1) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
(GameUtil.LINE_COUNT - GameUtil.LINE_COUNT / 4 - 1) * GameUtil.CELL_WIDTH + GameUtil.OFFSET - GameUtil.STAR_WIDTH / 2,
GameUtil.STAR_WIDTH, GameUtil.STAR_WIDTH
);
}
//绘制预选框
private void drawTips( Graphics2D g2D, int tx, int ty ) {
g2D.setColor(Color.RED);
//x=(GameUtil.LINE_COUNT / 2) * GameUtil.CELL_WIDTH+GameUtil.OFFSET;
//y=(GameUtil.LINE_COUNT/2)*GameUtil.CELL_WIDTH+GameUtil.OFFSET;
int x = tx, y = ty;
//x=chessBeans[tx][ty].getX();
//y=chessBeans[tx][ty].getY();
//左上角向右的线
g2D.drawLine(x - GameUtil.CELL_WIDTH / 2,
y - GameUtil.CELL_WIDTH / 2,
x - GameUtil.CELL_WIDTH / 4,
y - GameUtil.CELL_WIDTH / 2);
//绘制左上角向下的线
g2D.drawLine(x - GameUtil.CELL_WIDTH / 2,
y - GameUtil.CELL_WIDTH / 2,
x - GameUtil.CELL_WIDTH / 2,
y - GameUtil.CELL_WIDTH / 4);
// 绘制左下角向上
g2D.drawLine(x - GameUtil.CELL_WIDTH / 2, y + GameUtil.CELL_WIDTH / 2,
x - GameUtil.CELL_WIDTH / 2, y + GameUtil.CELL_WIDTH / 4);
//绘制左下角向右
g2D.drawLine(x - GameUtil.CELL_WIDTH / 2, y + GameUtil.CELL_WIDTH / 2,
x - GameUtil.CELL_WIDTH / 4, y + GameUtil.CELL_WIDTH / 2);
//右上角向左的线
g2D.drawLine(x + GameUtil.CELL_WIDTH / 2, y - GameUtil.CELL_WIDTH / 2,
x + GameUtil.CELL_WIDTH / 4, y - GameUtil.CELL_WIDTH / 2);
//绘制右上角向下的线
g2D.drawLine(x + GameUtil.CELL_WIDTH / 2, y - GameUtil.CELL_WIDTH / 2,
x + GameUtil.CELL_WIDTH / 2, y - GameUtil.CELL_WIDTH / 4);
// 绘制右下角向上
g2D.drawLine(x + GameUtil.CELL_WIDTH / 2, y + GameUtil.CELL_WIDTH / 2,
x + GameUtil.CELL_WIDTH / 2, y + GameUtil.CELL_WIDTH / 4);
//绘制右下角向左
g2D.drawLine(x + GameUtil.CELL_WIDTH / 2, y + GameUtil.CELL_WIDTH / 2,
x + GameUtil.CELL_WIDTH / 4, y + GameUtil.CELL_WIDTH / 2);
g2D.setColor(Color.BLACK);
}
//绘制边缘的数字和字母
private void drawNumber( Graphics2D g2d ) {
Font font = new Font("微软雅黑", Font.BOLD, 14);
g2d.setFont(font);
FontMetrics fm = g2d.getFontMetrics();
int heigth = fm.getAscent();//获取文本的高度
//int width=fm.stringWidth(str1[0]);
//绘制数字,列方向
for (int i = 0; i < GameUtil.LINE_COUNT; i++) {
int x = 9;//GameUtil.OFFSET;
int y = i * GameUtil.CELL_WIDTH + GameUtil.OFFSET + heigth / 2;
g2d.drawString((GameUtil.LINE_COUNT - i) + " ", x, y);
}
//绘制字母
for (int i = 0; i < GameUtil.LINE_COUNT; i++) {
int base = (int) 'A';
int x = i * GameUtil.CELL_WIDTH + GameUtil.OFFSET;
int y = GameUtil.LINE_COUNT * GameUtil.CELL_WIDTH + GameUtil.OFFSET*3/4;
g2d.drawString((char) (base + i) + "", x, y);
}
}
}