package com.itheima.ui;
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表示 界面 窗体
//规定 GameJFrame这个界面表示的就是游戏的主界面
//以后根义序相关的所有逻辑都写在这个类中
//构造器 此处相当于空参构造 那么这里的his就找到APP中的当前对象new GameFrame 的地址值
//创建二维数组 目的 用来管理数据
int[][] data = new int[][]//正确数组 用于打乱
{{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
private int [] [] getWin(){//定义win数组总是会被修改 只好设置了GetWin方法 来防止数组被修改
return new int[][]//正确数组 用于胜利判断
{{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12},
{13, 14, 15, 0}
};
}
//创建选项下面的条目对象
JMenuItem replayItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登陆");
JMenuItem CloseItem = new JMenuItem("关闭游戏 ");
JMenuItem accountItem = new JMenuItem("微信号");
//换图功能
JMenuItem level_1 = new JMenuItem("换图——动物");
JMenuItem level_2 = new JMenuItem("换图——姐姐");
boolean CUse;
//定义一个图片 ;记录当前展示图片的路径
Random r = new Random();
String path = "image\\animal\\animal"+(r.nextInt(8)+1) +"\\";
//记录空白方块在二维数组中的位置
int x = 3;
int y = 3;
//定义变量 用来统计步数
int step = 0;
public GameJFrame() {//setRootPane(createRootPane());空参中制动创建了一个隐藏的容器 在创建JFrame就自动创建了
System.out.println(path);
//初始化界面
initJFrame();
//初始化菜单
initJMenuBar();
//初始化数据 (打乱 )
InitDate();
//初始化图片
InitImage();
Victory();
//显示界面 写在最后
this.setVisible(true);//改变界面默认隐藏为显示 的属性
}
private void initJFrame() {//this也可以省略
//设置宽高
this.setSize(603, 680);//单位是像素
//设置标题
setTitle("拼图单鸡版 V1.0");
//设置界面置顶
this.setAlwaysOnTop(true);
//设置窗口居中
this.setLocationRelativeTo(null);
//设置游戏的关闭模式
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);//点击一个界面所有的界面都会关闭
//取消默认的居中放置,只有取消了才会按照xy轴形式添加组件
this.setLayout(null);
//给整个界面添加键盘监听事件 !绑定
this.addKeyListener(this);
}
//初始化菜单
private void initJMenuBar() {
//1.创建整个的菜单对象
JMenuBar jMenuBar = new JMenuBar();
//创建菜单上面的两个选项的对象
JMenu funcJMenu = new JMenu("功能 ");
JMenu change = new JMenu("换图 ");
JMenu aboutJMenu = new JMenu("关于zky");
//将每一个选项下面的条目添加到选项当中
funcJMenu.add(replayItem);//重新游戏
funcJMenu.add(reLoginItem);//重新登陆
funcJMenu.add(CloseItem);//关闭游戏
//换图
change.add(level_1);
change.add(level_2);
aboutJMenu.add(accountItem);//微信号
//给条目绑定事件
replayItem.addActionListener(this);
reLoginItem.addActionListener(this);
CloseItem.addActionListener(this);
accountItem.addActionListener(this);
level_1.addActionListener(this);
level_2.addActionListener(this);
//将菜单里面两个选项添加到菜单当中
jMenuBar.add(funcJMenu);
jMenuBar.add(aboutJMenu);
jMenuBar.add(change);
//给整个界面设置菜单
this.setJMenuBar(jMenuBar);
}
private void InitDate() {
Random r = new Random();
for (int i = 0; i < 5000; i++) {//随机操作5000次后取得随机二维数组
int a = r.nextInt(4);//通过(random 0-3)来随机操作空白块
if (a == 0) {//上
//防止图片index超出的bug
if (x == 3) {
continue;//边界数组超过范围直接跳出当前循环
}
//把要替换的图片赋值给空白
data[x][y] = data[x + 1][y];
//把被替换的图片变成空白 0
data[x + 1][y] = 0;
//空白已经被替换 所以坐标x轴++
x++;
} else if (a == 1) {//下
if (x == 0) {
continue;
}
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;
} else if (a == 2) {//左
if (y == 3) {
continue;
}
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
} else {//右
if (y == 0) {
continue;
}
data[x][y] = data[x][y - 1];
data[x][y - 1] = 0;
y--;
}
}
}
//初始化图片
// int number = 0;
private void InitImage() {
//清空已经清空的所有图片
this.getContentPane().removeAll();
if (Victory()) {
JLabel winJLabel = new JLabel(new ImageIcon("image//win.png"));
winJLabel.setBounds(203,283,197,73);
this.getContentPane().add(winJLabel);
}
//绝对路径 :盘符开始
//相对路径:相对当前项目而言
//外循环
for (int j = 0; j < 4; j++) {//统一修改某变量名称 shift+F6
//内循环
for (int i = 0; i < 4; i++) {
//获得随机二维数组内的索引值用来打开图片
int number = data[j][i];
//创建一个图片ImageIcon的对象
// ImageIcon icon = new ImageIcon("C:\\Users\\11135\\Desktop\\javawork\\game\\image\\animal\\animal3\\1.jpg");
//创建一个JLabel对象
JLabel jLabel1 = new JLabel(new ImageIcon //每迭代一次后number需要自增 第16张图找不到会自动生成空白
(path + number + ".jpg"));
jLabel1.setBounds(105 * i + 83, 105 * j + 134, 105, 105);//加一些坐标偏移 让图片为中间偏下
//给图片添加边界 raised凸起 LOWERED凹陷
jLabel1.setBorder(new BevelBorder(BevelBorder.LOWERED));
//最后把管理容器添加到界面里
// add(jLabel1);//默认把图片放在最中间
this.getContentPane().add(jLabel1);//已经自动创建了 所以直接获取就可以了
}
}
//添加背景图片
ImageIcon bj = new ImageIcon("image\\background.png");//相对路径
JLabel background = new JLabel(bj);//交给JLabel管理
background.setBounds(40, 40, 508, 560); //坐标 默认图片的坐标点都在左上角
this.getContentPane().add(background);
if(CUse){
JLabel cheat_words = new JLabel("步数:都这样了你还要看步数?");
cheat_words.setBounds(50,30,300,20);
add(cheat_words);
}
else {
JLabel stepCount = new JLabel("步数:" + step);
stepCount.setBounds(50, 30, 100, 20);
add(stepCount);
}
//刷新图片
this.getContentPane().repaint();
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == 65) {//查看原图
//把界面中所有的图片删除
this.getContentPane().removeAll();
JLabel all = new JLabel(new ImageIcon(path + "all.jpg"));
all.setBounds(83, 134, 420, 420);
this.getContentPane().add(all);
ImageIcon bj = new ImageIcon("image\\background.png");//相对路径
JLabel background = new JLabel(bj);//交给JLabel管理
background.setBounds(40, 40, 508, 560); //坐标 默认图片的坐标点都在左上角
this.getContentPane().add(background);
this.getContentPane().repaint();
}
if (Victory()){
return;
}
//对上下左右进项进行判断
if (code == 37) {//←
if (y == 3) {
return;
}
data[x][y] = data[x][y + 1];
data[x][y + 1] = 0;
y++;
//每移动一次步数++
step++;
InitImage();
} else if (code == 38) {//↑ now/original
//防止图片移除的bug
if (x == 3) {
return;
}
//把要替换的图片赋值给空白
data[x][y] = data[x + 1][y];
//把被替换的图片变成空白 0
data[x + 1][y] = 0;
//空白已经被替换 所以坐标x轴++
x++;
step++;
//调用方法 用最新的方法加载图片
InitImage();
} else if (code == 39) {//→
if (y == 0) {
return;
}
data[x][y] = data[x][y - 1];
data[x][y - 1] = 0;
y--;
step++;
InitImage();
} else if (code == 40) {//↓
if (x == 0) {
return;
}
data[x][y] = data[x - 1][y];
data[x - 1][y] = 0;
x--;
step++;
InitImage();
}
//查看全部图片的功能
}
@Override
public void keyReleased(KeyEvent e) {
int code = e.getKeyCode();
//对于这个e的理解 : 这个方法是重写了接口KeyListener内的抽象方法
// 抽象方法传入的参数是KeyEvent类的e ,e就用来调用KeyEvent 里面的方法
// System.out.println(code);//上下左右 38 40 37 39
if (code == 65) {//松开A后正常显示全部图片
InitImage();
}
else if (!Victory() &&code == 87) {//一键完成 松开W之后白块发生位移 重置白块位置
data = getWin();
CUse = true;
//更改空白方块记录的位置
// 不调整会导致重新开局时实际白块位置和加载不同步(直接重置了数组)
x = 3;
y = 3;
InitImage();
}
}
public boolean Victory() {
//判断数组中的数据和data是否相同
for (int i = 0; i < data.length; i++) {
for (int j = 0; j < data[i].length; j++) {
if (data[i][j] != getWin()[i][j]) {
return false;//只要有一个数据不一样 返回false
}
}
}
return true;
}
@Override
public void actionPerformed(ActionEvent e) {
Object obj = e.getSource();
if (obj == replayItem){
//重新游戏
//再次打乱二维数组中的数据 重新加载图片 计步器 作弊器常量请0
step = 0;
CUse = false;
InitDate();
InitImage();
} else if (obj == reLoginItem) {
//重新登陆
this.setVisible(false);
//打开登陆界面
new LoginJFrame();
} else if (obj == CloseItem) {
//关闭游戏\
System.exit(1);
} else if (obj == accountItem) {
//微信号
/*
关于JDialog的思考·
JDialog是一个页面 (弹窗)
设置了JLabel 后把JLabel(容器)添加到JDialog这个页面中 而后可以通过JLabel管理图片
通过JDialog来设置页面 下来多都是用JDialog来管理页面的操作
*/
JDialog jDialog = new JDialog();
JLabel jLabel = new JLabel(new ImageIcon("image//mamam.jpg"));
//位置和宽高设置
jLabel.setBounds(0,0,258,258);
//乞丐
jDialog.setTitle("赏俺一毛钱");
//把图片添加到弹框之中
jDialog.getContentPane().add(jLabel);//jDialog.add(jLabel);
//弹框大小设置
jDialog.setSize(344,344);
//弹框置顶
jDialog.setAlwaysOnTop(true);
//弹框居中
jDialog.setLocationRelativeTo(null);
//弹框不关闭则无法关闭下面的界面
jDialog.setModal(true);
//让弹框显示出来
jDialog.setVisible(true);
} else if (obj == level_1) {//动物
path = "image\\animal\\animal"+(r.nextInt(8)+1) +"\\";
//传入路径后重新加载
InitDate();
InitImage();
} else if (obj == level_2) {//姐姐
path = "image\\girl\\girl"+(r.nextInt(13)+1) + "\\";
InitDate();
InitImage();
}
}
}
在主程序中 new GameJFrame();运行
后续的打包用了 exe4j和inno setup compiler
jdk调整成了jdk11
java的代码量感觉太大了 ...