package com.itheima.ui;
import com.itheima.ui.GameJFrame;
import com.itheima.ui.LoginJFrame;
import com.itheima.ui.RegisterJFrame;
public class App {
public static void main(String[] args) {
// 程序的启动入口
//如果我们想要开启一个界面,就创建谁的对象
new LoginJFrame();
// new RegisterJFrame();
// new GameJFrame();
}
}
package com.itheima.ui;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.util.Random;
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;
import javax.swing.border.BevelBorder;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class GameJFrame extends JFrame implements KeyListener,ActionListener{
//JFrame:界面,窗体
//规定:GameJFrame这个界面就是游戏的主界面
//创建一个二维数组:用来管理图片,加载图片时会根据二维数组中的数据进行加载
int [][] data=new int[4][4];
//记录空白方块的位置
int x=0;
int y=0;
//记录当前展示图片的路径
String path="image/animal/animal3/";
//判断胜利
int[][] win= {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,0}
};
// 标志位,表示游戏是否胜利
private boolean gameWon = false;
//计步器
int step=0;
private Clip c;
private AudioInputStream ais;
//添加一个标志,用于跟踪音乐的播放状态
private boolean musicPlaying = true;
//创建选项下面的条目对象
JMenuItem girl = new JMenuItem("我们");
JMenuItem animal = new JMenuItem("动物");
JMenuItem sport = new JMenuItem("运动");
JMenuItem pauseMusicItem = new JMenuItem("暂停音乐");
JMenuItem replayItem=new JMenuItem("重新游戏");
JMenuItem reLoginItem=new JMenuItem("重新登录");
JMenuItem closeItem=new JMenuItem("关闭游戏");
JMenuItem accountItem=new JMenuItem("联系作者");
public GameJFrame() {
//初始化界面
initJFrame();
//初始化菜单
initJMenuBar();
//初始化数据(打乱)
initData();
//初始化图片
initImage();
this.setVisible(true);//把窗口显示出来,默认false不显示
}
//初始化数据
private void initData() {
//定义一个一维数组
int[] tempArr= {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
//打乱顺序
//遍历数组,得到每一个元素,拿着每一个元素跟随机索引上的数据进行交换
Random r=new Random();
for(int i=0;i<tempArr.length;i++) {
//获取随机索引
int index =r.nextInt(tempArr.length);
//拿着遍历到的数据跟索引上的数据进行交换
int temp=tempArr[i];
tempArr[i]=tempArr[index];
tempArr[index]=temp;
}
//给二维数组添加数据
for(int i=0;i<tempArr.length;i++) {
if(tempArr[i]==0) {
x=i/4;
y=i%4;
}
data[i/4][i%4]=tempArr[i];
}
}
//初始化图片
//添加图片时需要按照二维数组中管理的数据添加图片
private void initImage() {
//清空原本出现的所有图片
this.getContentPane().removeAll();
if(victory()) {
//显示胜利图标
JLabel winLabel=new JLabel(new ImageIcon("image/win.png"));
winLabel.setBounds(203,283,197,73);
this.getContentPane().add(winLabel);
}
JLabel stepCount=new JLabel("步数"+step);
stepCount.setBounds(50,30,100,20);
this.getContentPane().add(stepCount);
//先加载的图片在上方,后加载的图片在下面
//外循环----四行
for(int i=0;i<4;i++) {
//内循环---在一行添加四张图片
for(int j=0;j<4;j++) {
//获取加载图片的序号
int num=data[i][j];
//创建一个JLabel对象
JLabel jLabel=new JLabel(new ImageIcon(path+num+".jpg"));
//指定图片位置
jLabel.setBounds(105*j+83,105*i+134,105,105);
//给图片添加边框
//0:让图片凸起来
//1:让图片凹下去
jLabel.setBorder(new BevelBorder(1));
//把管理容器添加到界面中
this.getContentPane().add(jLabel);
}
}
//添加背景图片
JLabel background =new JLabel(new ImageIcon("image/background.png"));
background.setBounds(40,40,508,560);
//把背景图片添加到界面中
this.getContentPane().add(background);
//刷新一下页面
this.getContentPane().repaint();
}
private void initJMenuBar() {
//创建整个菜单对象
JMenuBar jMenuBar =new JMenuBar();
//创建菜单上面的两个选项的对象(功能 关于我们)
JMenu functionJMenu =new JMenu("功能");
JMenu aboutJMenu =new JMenu("关于我们");
//创建更换图片
JMenu changeImage = new JMenu("更换图片");
//把动物,运动添加到更换图片当中
changeImage.add(girl);
changeImage.add(animal);
changeImage.add(sport);
//将每一个条目添加到选项
functionJMenu.add(changeImage);
functionJMenu.add(pauseMusicItem);
functionJMenu.add(replayItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
aboutJMenu.add(accountItem);
//给条目绑定事件
replayItem.addActionListener(this);
reLoginItem.addActionListener(this);
closeItem.addActionListener(this);
accountItem.addActionListener(this);
girl.addActionListener(this);
animal.addActionListener(this);
sport.addActionListener(this);
pauseMusicItem.addActionListener(this);
//将菜单里面的两个选项添加到菜单
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJMenu);
//给整个界面设置菜单
this.setJMenuBar(jMenuBar);
}
private void initJFrame() {
this.setSize(603, 680);//设置宽高
this.setTitle("拼图游戏 v1.0");//设置界面标题
this.setAlwaysOnTop(true);//设置界面置顶
this.setLocationRelativeTo(null);//设置界面居中
this.setDefaultCloseOperation(3);//设置关闭模式
this.setLayout(null);//取消内部默认居中方式
this.addKeyListener(this);//给整个界面添加键盘监听事件
File f = new File("music/bgmusic.wav");//不支持MP3,请用格式工厂或其他软件把MP3改为wav,直接改后缀名会报错
try {
ais = AudioSystem.getAudioInputStream(f);
c = AudioSystem.getClip();
c.open(ais);
c.setFramePosition(0);
c.start();
} catch (Exception e) {
e.printStackTrace();
}
//如果GUI是线程运行结束后,需要添加停止播放代码
// c.stop();
}
@Override
public void keyTyped(KeyEvent e) {
// TODO Auto-generated method stub
}
@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);
//加载背景图片
//添加背景图片
JLabel background =new JLabel(new ImageIcon("image/background.png"));
background.setBounds(40,40,508,560);
//把背景图片添加到界面中
this.getContentPane().add(background);
//刷新界面
this.getContentPane().repaint();
}
}
//松开按键时会调用这个方法
@Override
public void keyReleased(KeyEvent e) {
//判断游戏是否胜利,如果胜利则直接结束方法,不能再执行下面的移动代码
if(victory()) {
return;
}
//对上下左右进行判断
//左:37 上:38 右:39 下:40
int code =e.getKeyCode();
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) {
if(x==3) {
//空白方块已经在最下面了
return;
}
//把空白方块下方的数字往上移动
//x,y表示空白方块
//x+1,y表示空白方块下方的数字
data[x][y]=data[x+1][y];
data[x+1][y]=0;
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();
}
else if(code==65) {
initImage();
}
else if(code==87) {
data=new int[][] {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,0}
};
initImage();
}
}
//判断是否胜利
public boolean victory() {
for(int i=0;i<data.length;i++) {
for(int j=0;j<data[i].length;j++) {
if(data[i][j]!=win[i][j]) {
//只要有一个不一样返回false
return false;
}
}
}
gameWon = true;
return true;
}
@Override
public void actionPerformed(ActionEvent e) {
//获取条目对象
Object obj=e.getSource();
if (gameWon) {
// 如果游戏已经胜利,点击更换图片菜单项时给出提示
if (obj == girl || obj == animal || obj == sport) {
JOptionPane.showMessageDialog(this, "游戏已经胜利,请重新开始游戏!");
return;
}
}
// 判断事件源是哪个菜单项
if (obj == girl) {
// 从6组图片中随机选择一组
path = "image/girl/girl" + (new Random().nextInt(6) + 1) + "/";
} else if (obj == animal) {
// 从5组动物图片中随机选择一组
path = "image/animal/animal" + (new Random().nextInt(5) + 1) + "/";
} else if (obj == sport) {
// 从10组运动图片中随机选择一组
path = "image/sport/sport" + (new Random().nextInt(10) + 1) + "/";
}
else if(obj==replayItem) {
System.out.println("重新游戏");
gameWon=false;
//再次打乱二维数组
initData();
//计步器清零
step=0;
//重新加载图片
initImage();
}
else if(obj==reLoginItem) {
System.out.println("重新登录");
// 暂停音乐播放
if (musicPlaying) {
c.stop();
musicPlaying = false;
}
//关闭当前游戏界面
this.setVisible(false);
//打开登录界面
new LoginJFrame();
}
else if(obj==closeItem) {
System.out.println("关闭游戏");
//直接关闭虚拟机即可
System.exit(0);
}
else if(obj==accountItem) {
System.out.println("联系作者");
//创建一个弹窗对象
JDialog jDialog=new JDialog();
//创建一个管理图片的容器对象
JLabel jLabel=new JLabel(new ImageIcon("image/about.png"));
//设置位置和宽高
jLabel.setBounds(0,0,263,258);
jDialog.getContentPane().add(jLabel);
jDialog.setTitle("联系作者");
//设置弹框大小
jDialog.setSize(344, 344);
//让弹框置顶
jDialog.setAlwaysOnTop(true);
//让弹框居中
jDialog.setLocationRelativeTo(null);
//让弹框不关闭就无法操作下面的界面
jDialog.setModal(true);
//让弹框显示出来
jDialog.setVisible(true);
}
//在actionPerformed方法中处理暂停音乐菜单项的点击事件
else if(obj == pauseMusicItem) {
//切换音乐播放状态
musicPlaying = !musicPlaying;
if(musicPlaying) {
//如果音乐正在播放,恢复播放音乐,并将按钮文本设置为"暂停音乐"
c.start();
pauseMusicItem.setText("暂停音乐");
} else {
//如果音乐暂停,停止音乐播放,并将按钮文本设置为"播放音乐"
c.stop();
pauseMusicItem.setText("播放音乐");
}
}
//重新加载图片
initImage();
}
}
package com.itheima.ui;
import com.itheima.domain.User;
import com.itheima.util.CodeUtil;
import javax.swing.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
public class LoginJFrame extends JFrame implements MouseListener {
static ArrayList<User> allUsers = new ArrayList<>();
static {
allUsers.add(new User("admin","123456"));
allUsers.add(new User("lcx","210918"));
}
JButton login = new JButton();
JButton register = new JButton();
JTextField username = new JTextField();
//JTextField password = new JTextField();
JPasswordField password = new JPasswordField();
JTextField code = new JTextField();
//正确的验证码
JLabel rightCode = new JLabel();
public LoginJFrame() {
//初始化界面
initJFrame();
//在这个界面中添加内容
initView();
//让当前界面显示出来
this.setVisible(true);
}
public void initView() {
//1. 添加用户名文字
JLabel usernameText = new JLabel(new ImageIcon("image\\login\\用户名.png"));
usernameText.setBounds(116, 135, 47, 17);
this.getContentPane().add(usernameText);
//2.添加用户名输入框
username.setBounds(195, 134, 200, 30);
this.getContentPane().add(username);
//3.添加密码文字
JLabel passwordText = new JLabel(new ImageIcon("image\\login\\密码.png"));
passwordText.setBounds(130, 195, 32, 16);
this.getContentPane().add(passwordText);
//4.密码输入框
password.setBounds(195, 195, 200, 30);
this.getContentPane().add(password);
//验证码提示
JLabel codeText = new JLabel(new ImageIcon("image\\login\\验证码.png"));
codeText.setBounds(133, 256, 50, 30);
this.getContentPane().add(codeText);
//验证码的输入框
code.setBounds(195, 256, 100, 30);
this.getContentPane().add(code);
String codeStr = CodeUtil.getCode();
//设置内容
rightCode.setText(codeStr);
//绑定鼠标事件
rightCode.addMouseListener(this);
//位置和宽高
rightCode.setBounds(300, 256, 50, 30);
//添加到界面
this.getContentPane().add(rightCode);
//5.添加登录按钮
login.setBounds(123, 310, 128, 47);
login.setIcon(new ImageIcon("image\\login\\登录按钮.png"));
//去除按钮的边框
login.setBorderPainted(false);
//去除按钮的背景
login.setContentAreaFilled(false);
//给登录按钮绑定鼠标事件
login.addMouseListener(this);
this.getContentPane().add(login);
//6.添加注册按钮
register.setBounds(256, 310, 128, 47);
register.setIcon(new ImageIcon("image\\login\\注册按钮.png"));
//去除按钮的边框
register.setBorderPainted(false);
//去除按钮的背景
register.setContentAreaFilled(false);
//给注册按钮绑定鼠标事件
register.addMouseListener(this);
this.getContentPane().add(register);
//7.添加背景图片
JLabel background = new JLabel(new ImageIcon("image\\login\\background.png"));
background.setBounds(0, 0, 470, 390);
this.getContentPane().add(background);
}
public void initJFrame() {
this.setSize(488, 430);//设置宽高
this.setTitle("拼图游戏 v1.0登录");//设置标题
this.setDefaultCloseOperation(3);//设置关闭模式
this.setLocationRelativeTo(null);//居中
this.setAlwaysOnTop(true);//置顶
this.setLayout(null);//取消内部默认布局
}
//点击
@Override
public void mouseClicked(MouseEvent e) {
if (e.getSource() == login) {
System.out.println("点击了登录按钮");
//获取两个文本输入框中的内容
String usernameInput = username.getText();
String passwordInput = password.getText();
//获取用户输入的验证码
String codeInput = code.getText();
//创建一个User对象
User userInfo = new User(usernameInput, passwordInput);
System.out.println("用户输入的用户名为" + usernameInput);
System.out.println("用户输入的密码为" + passwordInput);
if (codeInput.length() == 0) {
showJDialog("验证码不能为空");
} else if (usernameInput.length() == 0 || passwordInput.length() == 0) {
//校验用户名和密码是否为空
System.out.println("用户名或者密码为空");
//调用showJDialog方法并展示弹框
showJDialog("用户名或者密码为空");
} else if (!codeInput.equalsIgnoreCase(rightCode.getText())) {
showJDialog("验证码输入错误");
} else if (contains(userInfo)) {
System.out.println("用户名和密码正确可以开始玩游戏了");
//关闭当前登录界面
this.setVisible(false);
//打开游戏的主界面
//需要把当前登录的用户名传递给游戏界面
new GameJFrame();
} else {
System.out.println("用户名或密码错误");
showJDialog("用户名或密码错误");
}
} else if (e.getSource() == register) {
System.out.println("点击了注册按钮");
} else if (e.getSource() == rightCode) {
System.out.println("更换验证码");
//获取一个新的验证码
String code = CodeUtil.getCode();
rightCode.setText(code);
}
}
public void showJDialog(String content) {
//创建一个弹框对象
JDialog jDialog = new JDialog();
//给弹框设置大小
jDialog.setSize(200, 150);
//让弹框置顶
jDialog.setAlwaysOnTop(true);
//让弹框居中
jDialog.setLocationRelativeTo(null);
//弹框不关闭永远无法操作下面的界面
jDialog.setModal(true);
//创建Jlabel对象管理文字并添加到弹框当中
JLabel warning = new JLabel(content);
warning.setBounds(0, 0, 200, 150);
jDialog.getContentPane().add(warning);
//让弹框展示出来
jDialog.setVisible(true);
}
//按下不松
@Override
public void mousePressed(MouseEvent e) {
if (e.getSource() == login) {
login.setIcon(new ImageIcon("image\\login\\登录按下.png"));
} else if (e.getSource() == register) {
register.setIcon(new ImageIcon("image\\login\\注册按下.png"));
}
}
//松开按钮
@Override
public void mouseReleased(MouseEvent e) {
if (e.getSource() == login) {
login.setIcon(new ImageIcon("image\\login\\登录按钮.png"));
} else if (e.getSource() == register) {
register.setIcon(new ImageIcon("image\\login\\注册按钮.png"));
}
}
//鼠标划入
@Override
public void mouseEntered(MouseEvent e) {
}
//鼠标划出
@Override
public void mouseExited(MouseEvent e) {
}
//判断用户在集合中是否存在
public boolean contains(User userInput){
for (int i = 0; i < allUsers.size(); i++) {
User rightUser = allUsers.get(i);
if(userInput.getUsername().equals(rightUser.getUsername()) && userInput.getPassword().equals(rightUser.getPassword())){
//有相同的代表存在,返回true,后面的不需要再比了
return true;
}
}
//循环结束之后还没有找到就表示不存在
return false;
}
}
package com.itheima.util;
import java.util.ArrayList;
import java.util.Random;
public class CodeUtil {
public static String getCode(){
//1.创建一个集合
ArrayList<Character> list = new ArrayList<>();//52 索引的范围:0 ~ 51
//2.添加字母 a - z A - Z
for (int i = 0; i < 26; i++) {
list.add((char)('a' + i));//a - z
list.add((char)('A' + i));//A - Z
}
//3.打印集合
//System.out.println(list);
//4.生成4个随机字母
String result = "";
Random r = new Random();
for (int i = 0; i < 4; i++) {
//获取随机索引
int randomIndex = r.nextInt(list.size());
char c = list.get(randomIndex);
result = result + c;
}
//System.out.println(result);//长度为4的随机字符串
//5.在后面拼接数字 0~9
int number = r.nextInt(10);
//6.把随机数字拼接到result的后面
result = result + number;
//System.out.println(result);//ABCD5
//7.把字符串变成字符数组
char[] chars = result.toCharArray();//[A,B,C,D,5]
//8.在字符数组中生成一个随机索引
int index = r.nextInt(chars.length);
//9.拿着4索引上的数字,跟随机索引上的数字进行交换
char temp = chars[4];
chars[4] = chars[index];
chars[index] = temp;
//10.把字符数组再变回字符串
String code = new String(chars);
//System.out.println(code);
return code;
}
}
package com.itheima.domain;
public class User {
private String username;
private String password;
public User() {
}
public User(String username, String password) {
this.username = username;
this.password = password;
}
/**
* 获取
* @return username
*/
public String getUsername() {
return username;
}
/**
* 设置
* @param username
*/
public void setUsername(String username) {
this.username = username;
}
/**
* 获取
* @return password
*/
public String getPassword() {
return password;
}
/**
* 设置
* @param password
*/
public void setPassword(String password) {
this.password = password;
}
}