项目介绍:
使用Java编程语言来编写简单的UI程序,同时还要熟练JavaSwing的使用,以及对程序算法的设计。学习内容:
1、 掌握JavaSwing
2、 掌握 Java 基本语法
3、 设计游戏算法
项目功能:
本项目使用一个游戏界面,在游戏界面中实现人机对战功能,同时还需要有“重来一局”,“玩家先手”,“机器先手”,“退出游戏“的功能。
项目解析:
首先我们要设计一个游戏界面,定义一个类GameUI,用来作为游戏的界面。一般来讲,我们可以让GameUI类继承JFrame直接作为窗口的子类,但对于复杂的界面设计我们往往需要对布局管理器组合使用,达到较为复杂的布局效果。所以此时我们就需要借助容器类JPanel来达到这一目的。
使用语句:public class GameUI extends JPanel
在GameUI中有JFrame类成员变量frame,用来显示游戏界面,同时需要定义方法来初始化游戏界面。还需要在该窗口中设置菜单栏,用来控制游戏的先后顺序,重新开局以及退出游戏的功能菜单。
public void initUI() {
//GameUI继承自JPanel容器类,类似于JavaFX中的Scene
//在GameUI中创建一个JFrame,并让GameUI成为其容器,来显示容器中的节点
// 设置游戏窗口的尺寸
frame.setSize(800, 850);
// 设置居中显示
frame.setLocationRelativeTo(null);
// 设置退出进程,参数为3,仅在应用程序中使用,结束应用程序。
frame.setDefaultCloseOperation(3);
//边框布局
frame.setLayout(new BorderLayout());
//在JavaSwing中,要想能够不让节点占满整个窗口,必须设置布局类
//使用与JPanel相关的类时,使用的布局为BorderLayout(边框布局)
//北边的窗口默认是流式布局
JPanel northPanel = new JPanel();
//设置窗口上方容器的背景颜色
northPanel.setBackground(Color.green);
//在窗口中添加菜单栏
//菜单栏的结构为:子菜单(JMenuItem)-->菜单(JMenu)-->菜单栏(JMenuBar)
//注意,在菜单栏中,只有子菜单(JMenuItem)才可以添加事件监听器。
JMenuBar jbr = new JMenuBar();
JMenu menu1 = new JMenu("顺序");
JMenu menu2 = new JMenu("操作");
//这里是给菜单栏添加菜单
jbr.add(menu1);
jbr.add(menu2);
JMenuItem jm1 = new JMenuItem("玩家先手");
JMenuItem jm2 = new JMenuItem("机器先手");
JMenuItem jm3 = new JMenuItem("悔棋");
JMenuItem jm4 = new JMenuItem("重来");
//这里是给菜单添加子菜单
menu1.add(jm1);
menu1.add(jm2);
menu2.add(jm3);
menu2.add(jm4);
//使用边框布局将菜单栏设置在窗口的“北方”
frame.add(jbr, BorderLayout.NORTH);
this.setBackground(Color.YELLOW);
GameMouse mouse = new GameMouse(this,chessValue);
//给子菜单添加事件监听器,用于实现相应的功能
jm1.addActionListener(mouse);
jm2.addActionListener(mouse);
jm3.addActionListener(mouse);
jm4.addActionListener(mouse);
//给窗口添加容器,并设置容器在窗口中的位置,因为将该容器设置在窗口的上方,默认为流式布局
frame.add(northPanel,BorderLayout.NORTH);
// 设置游戏界面容器的尺寸
this.setPreferredSize(new Dimension(800, 700));
//设置GameUI容器类的背景颜色,用来与上面定义的窗口容器做区分。
this.setBackground(Color.YELLOW);
//给按钮添加事件监听器(这个事件监听器是我们自己重新定义的监听器的子类,在下方会讲解)
GameMouse mouse = new GameMouse(this,chessValue);
bt1.addActionListener(mouse);
bt2.addActionListener(mouse);
bt3.addActionListener(mouse);
//给窗口添加这个容器,并将该容器类放在窗口中间。
frame.add(this, BorderLayout.CENTER);
//设置窗体可见,必须有该语句,否则窗体将不可见,界面将没有意义。
frame.setVisible(true);
//画笔:图形画在那个组件上,画笔就从该组件上获取
//从窗体获取画笔对象,一定要在窗体显示可见之后
//在界面中,我们需要将棋盘和棋子显示出来,我们需要借助画笔来完成。
//将画笔定义在我们自定义的GameUI上,在容器中画图。
Graphics g = this.getGraphics();
//将棋盘传到GameUI中,获取当前棋局,用于画出棋盘以及判断输赢。
chess = mouse.setChess();
//用于获取当前棋子的坐标
xx = mouse.setX();
yy = mouse.setY();
//给窗体添加鼠标监听器方法
this.addMouseListener(mouse);
mouse.setGr(g);
在JavaSwing中,当我们改变窗口的状态,窗口将会重新绘制,而如果我们没有重新绘制棋盘和棋子,则一旦我们移动,或是拉伸游戏界面,游戏界面中相关的游戏元素(棋盘,棋子)都将会消失。所以为防止这个问题,我们需要重写绘制窗体的paint方法。(这个paint方法不是由用户调用的,而是由虚拟机自动调用的,所以当我们运行整个程序时,paint方法将会自动执行)
在paint方法中,我们需要绘制棋盘以及棋子。但在此之前,我们可以定义一个接口来存储一些棋盘大小,间隔以及棋子大小之类的参数,以便后续对棋盘大小进行修改。
public interface Config {
//定义棋盘最左上角顶点的坐标
public static final int X0 = 25;
public static final int Y0 = 25;
//定义棋盘线条之间的宽度
public static final int SIZE = 50;
//定义棋盘中线条个数
public static final int COUNT = 15;}
在paint方法中借助Config接口中的参数,来绘制棋局
public void paint(Graphics g){
//首先调用父类的绘图方法
super.paint(g);
//给窗口添加背景图片
//ImageIcon image = new ImageIcon("d:/res/1.jpg");
//g.drawImage(image.getImage(), 0, 0, 800, 780, null);
//借助Grapjics.drawLine(起点横坐标,起点纵坐标,终点横坐标,终点纵坐标)绘制棋盘
for(int i = 0; i < 15; i++) {
g.drawLine(X0, Y0 + SIZE * i, X0 + ( COUNT - 1) * SIZE, Y0 + SIZE * i);
}
for(int i = 0; i < 15; i++) {
g.drawLine(X0 + SIZE * i, Y0,