Java中的图形化界面使用得是比较少的,但是可以用来结合前期学习的面向对象编程的思想,通过图形化的呈现,创造一个拼图小游戏。
主要用的到的包:
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
类的继承和实现:
public class GameJFrame extends JFrame implements KeyListener, ActionListener
主要思想:JFrame 、JMenu、JMenuBar、JMenuItem、JLabel、ImageIcon;数组、随机数、面向对象、键盘、鼠标监视、动作监视……
游戏主体代码:
package GameUI;
import javax.swing.*;
import javax.swing.border.BevelBorder;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Random;
public class GameJFrame extends JFrame implements KeyListener, ActionListener {
int x = 0; // 用x来记录空白块的数组行标
int y = 0; // 用y来记录空白快数组的列标
int[][] imageArray = new int[4][4];
// 创建胜利数组,当imageArray和胜利数组完全一样的时候,代表游戏胜利
int[][] winArray = new int[][] {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,0}
};
// 用字符串来记录图片的路径,方便修改
String path = "Game\\image\\animal\\animal3\\";
// 用以记录移动步数
int step = 0;
// 创建功能中条目
JMenuItem replayItem = new JMenuItem("重新开始");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
// 创建关于制作人员中条目
JMenuItem accountItem = new JMenuItem("Rose");
public GameJFrame() {
// 设置界面
setJFrame();
// 设置菜单
setMenu();
// 初始化数组
initArray();
// 设置图片
setImage();
// 设置界面可见
this.setVisible(true);
}
private void setJFrame() {
// 设置界面大小
this.setSize(603, 680);
// 设置界面标题
this.setTitle("Puzzle version 1.0");
// 设置界面居中
this.setLocationRelativeTo(null);
// 设置界面永远在上
this.setAlwaysOnTop(true);
// 设置界面关闭模式
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
// 取消默认放置(JFrame只是一个框架,真正存放组件的是其中的ContentPanel
// ,必须要取消默认放置的设定才可以自定义坐标放置)
this.setLayout(null);
// 添加键盘监听
this.addKeyListener(this);
}
private void setMenu() {
// 创建整个菜单对象
JMenuBar jMenuBar = new JMenuBar();
// 创建选项功能
JMenu functionJMenu = new JMenu("功能 ");
JMenu aboutJMenu = new JMenu("制作人员");
// 给条目绑定事件
replayItem.addActionListener(this);
reLoginItem.addActionListener(this);
closeItem.addActionListener(this);
accountItem.addActionListener(this);
// 在功能中加入条目
functionJMenu.add(replayItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
// 在关于我们中加入条目
aboutJMenu.add(accountItem);
// 在菜单中加入选项
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);
// 在JFrame中创建菜单
this.setJMenuBar(jMenuBar);
}
public void setImage() {
// 清空本来已经出现的图片
this.getContentPane().removeAll();
if (victory()) {
JLabel victoryImage = new JLabel(new ImageIcon("D:\\codes\\Java\\PuzzleGame\\Game\\image\\win.png"));
victoryImage.setBounds(203, 283, 197, 73);
this.getContentPane().add(victoryImage);
}
JLabel stepImage = new JLabel("步数:" + step);
stepImage.setBounds(50, 30, 100, 20);
this.getContentPane().add(stepImage);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
int number = imageArray[i][j];
// 创建新的图片对象(构造方法可以传入图片文件的路径)
ImageIcon image = new ImageIcon(path + number + ".jpg");
// JLabel是一个图片容器,可以将ImageIcon创造出来的图片对象加入这个容器
JLabel jLabel = new JLabel(image);
/*设置图片在界面中的显示位置,每个小图片的像素是105*105;通过双重循环
可以达到将不同的图片,按行列放置到对应位置的效果*/
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
// 给每张图片设置一个边框,增强美观性
jLabel.setBorder(new BevelBorder(BevelBorder.LOWERED));
/*JFrame实际上只是一个框架,真正的组件实际上是“放置”于JFrame中的
ContentPanel中的,可以通过JFrame的getContentPanel方法得到,并且
在其中添加JLabel对象*/
this.getContentPane().add(jLabel);
}
}
// 添加背景图片
ImageIcon background = new ImageIcon("Game\\image\\background.png");
JLabel bg = new JLabel(background);
bg.setBounds(40, 40, 508, 560);
this.getContentPane().add(bg);
// 刷新界面
this.getContentPane().repaint();
}
public void initArray() {
int[] arr = new int[16];
for (int i = 0; i < arr.length; i++) {
arr[i] = i;
}
Random r = new Random();
int randomNumber;
for (int i = 15; i >= 0; i--) {
randomNumber = r.nextInt(i + 1);
int temp = arr[randomNumber];
arr[randomNumber] = arr[i];
arr[i] = temp;
}
// 初始化时必须将二维数组全部设置为0
// 如果不全部设置为0,上一次的数据会遗留
for (int i = 0; i < imageArray.length; i++) {
for (int j = 0; j < imageArray.length; j++) {
imageArray[i][j] = 0;
}
}
for(int i = 0; i < arr.length; i++) {
if (arr[i] == 0) {
this.x = i / 4;
this.y = i % 4;
} else{
imageArray[i / 4][i % 4] = arr[i];
}
}
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == 65) {
this.getContentPane().removeAll();
JLabel allImage = new JLabel(new ImageIcon(path + "all.jpg"));
allImage.setBounds(83,134,420,420);
this.getContentPane().add(allImage);
// 添加背景图片
ImageIcon background = new ImageIcon("Game\\image\\background.png");
JLabel bg = new JLabel(background);
bg.setBounds(40, 40, 508, 560);
this.getContentPane().add(bg);
// 刷新界面
this.getContentPane().repaint();
}
}
@Override
public void keyReleased(KeyEvent e) {
if (victory()) {
return;
}
int code = e.getKeyCode();
// 左移
if (code == 37) {
if (y == 3) {
return;
} else {
imageArray[x][y] = imageArray[x][y + 1];
imageArray[x][y + 1] = 0;
y++;
step++;
setImage();
}
}
// 上移
else if (code == 38) {
if (x == 3) {
return;
} else {
imageArray[x][y] = imageArray[x + 1][y];
imageArray[x + 1][y] = 0;
x++;
step++;
setImage();
}
}
// 右移
else if (code == 39) {
if (y == 0) {
return;
} else {
imageArray[x][y] = imageArray[x][y - 1];
imageArray[x][y - 1] = 0;
y--;
step++;
setImage();
}
}
// 下移
else if (code == 40) {
if (x == 0) {
return;
} else {
imageArray[x][y] = imageArray[x - 1][y];
imageArray[x - 1][y] = 0;
x--;
step++;
setImage();
}
} else if (code == 65) {
setImage();
} else if (code == 87) {
for (int i = 0; i < imageArray.length* imageArray.length; i++) {
if (i == 15) {
imageArray[3][3] = 0;
break;
}
imageArray[i / 4][i % 4] = i + 1;
}
setImage();
}
}
public boolean victory() {
for (int i = 0; i < imageArray.length; i++) {
for (int j = 0; j < imageArray.length; j++) {
if (imageArray[i][j] != winArray[i][j]) {
return false;
}
}
}
return true;
}
@Override
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if(obj == replayItem) {
// 重开游戏
// 步数清零
step = 0;
// 初始化图片数组
initArray();
// 展示打乱的图片
setImage();
} else if (obj == reLoginItem) {
System.out.println("重新登录(待开发)");
} else if (obj == accountItem) {
// 制作者
System.out.println("rose");
// 创建一个新的JFrame对象
JFrame rose = creatRose();
// 创建玫瑰图像的对象
ImageIcon roseImage = new ImageIcon("D:\\codes\\Java\\PuzzleGame\\Game\\image\\rose.jpg");
// 创建JLabel容器存放玫瑰图像
JLabel roseJB = new JLabel(roseImage);
// 设置图像的位置和大小
roseJB.setBounds(40, 40, 1080, 1080);
// 将图像容器加入JFrame中
rose.getContentPane().add(roseJB);
} else if (obj == closeItem) {
// 退出游戏
// 直接关闭JVM虚拟机
System.exit(0);
}
}
public JFrame creatRose() {
JFrame rose = new JFrame();
// 设置宽高为1080*1080
rose.setSize(1080, 1080);
// 设置窗口可见
rose.setVisible(true);
// 设置窗口标题
rose.setTitle("制作人员");
// 设置窗口默认在屏幕中央
rose.setLocationRelativeTo(null);
// 设置窗口总是在最上层
rose.setAlwaysOnTop(true);
// 设置窗口关闭模式(只关闭当前JFrame窗口(默认关闭的方式))
rose.setDefaultCloseOperation(HIDE_ON_CLOSE);
// 返回JFrame对象
return rose;
}
}
游戏的测试
import GameUI.GameJFrame;
import GameUI.LoginJFrame;
import GameUI.RegisterJFrame;
public class Application {
public static void main(String[] args) {
// 注册
RegisterJFrame rj = new RegisterJFrame();
// 登录
LoginJFrame lj = new LoginJFrame();
// 游戏
GameJFrame gj = new GameJFrame();
}
}
还剩下的坑:登录、注册,等到日后有时间再把这个坑填上
package GameUI;
import javax.swing.*;
public class LoginJFrame extends JFrame {
public LoginJFrame() {
// 设置界面大小
this.setSize(488, 430);
// 设置界面标题
this.setTitle("Login");
// 设置界面居中
this.setLocationRelativeTo(null);
// 设置界面永远在上
this.setAlwaysOnTop(true);
// 设置界面关闭模式
this.setDefaultCloseOperation(3);
// 设置界面可见
this.setVisible(true);
}
}
package GameUI;
import javax.swing.*;
public class RegisterJFrame extends JFrame{
public RegisterJFrame() {
// 设置界面大小
this.setSize(488, 500);
// 设置界面标题
this.setTitle("Register");
// 设置界面居中
this.setLocationRelativeTo(null);
// 设置界面永远在上
this.setAlwaysOnTop(true);
// 设置界面关闭模式
this.setDefaultCloseOperation(3);
// 设置界面可见
this.setVisible(true);
}
}