本次游戏的图形部分主要由JFrame类完成,包含三种主要功能:注册,登录以及游戏。游戏内包含菜单即游戏模式的切换以及各个控件的布局,登录部分主要是密码的判断,注册部分主要是判断是否重复用户名,还有密码输入的正确与否。
定义了一个用户类(用于登录注册)两个工具类(实现对密码的基本判断),以及针对上面的三个流程定义了三个对应的类,最后定义了一个启动类:
1.用户类
public class User {
String username;
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;
}
public String toString() {
return "User{username = " + username + ", password = " + password + "}";
}
}
2.工具类(1)验证注册类,注意工具类需要对构造方法私有化,因为创建对象无用:
import java.util.List;
public class Confirm {
private Confirm(){}
public static boolean adduser(List<User>list,String username,String password,String againpass){
if (username.length()!=0 && password.length()!=0 && againpass.length()!=0){
for (int i = 0; i < list.size(); i++)
if(list.get(i).getUsername().equals(username)){
System.out.println("用户已经存在,请直接登录或换个用户名");
return false;
}
if (!password.equals(againpass)) {
System.out.println("再次输入的密码不对");
return false;
} else
{
User u = new User();
u.setUsername(username);
u.setPassword(password);
list.add(u);
return true;
}
}
else
return false;
}
}
2.工具类(2):生成验证码:
import java.util.Random;
public class CodeUtil {
private CodeUtil(){}
public static String getCode(){
char[]arr = createAlpha();
int num = createNum();
String str = createVatifaction(arr,num);
str = toRandom(str);
return str;
}
private static Random r = new Random();
public static char[] createAlpha(){
char[] arr = new char[52];
for (int i = 0; i < arr.length; i++) {
if(i<26){
arr[i] = (char)('a' + i);
}
else
arr[i] = (char)('A'+ i -26);
}
return arr;
}
public static int createNum(){
int x = r.nextInt(10);
return x;
}
public static String createVatifaction(char[]arr,int num){
String str = "";
for (int i = 0; i < 4; i++) {
int index = r.nextInt(arr.length);
str += arr[index];
}
str += num;
return str;
}
public static String toRandom(String str){
char[]arr = str.toCharArray();
for (int i = 0; i < arr.length; i++) {
char temp = ' ';
int index = r.nextInt(arr.length);
temp = arr[i];
arr[i] = arr[index];
arr[index] = temp;
}
String newstr = new String(arr);
return newstr;
}
}
4.登录类:
效果图如下:
完整代码:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;
public class Login extends JFrame implements MouseListener {
static ArrayList<User> list = new ArrayList<>();
public Login() {
//初始化界面
initLogin();
//设置背景图:
setImage();
//设置是否显示窗口(建议放最后)
this.setVisible(true);
}
private String path = "game\\image\\login\\";
private String LoButton = path + "登录按钮.png";
private String ReButton = path + "注册按钮.png";
private JTextField usertext = new JTextField();
private JPasswordField passtext = new JPasswordField();
private JTextField codetext = new JTextField();
//添加实际需要输入的验证码
String codeStr = CodeUtil.getCode();
//登录按钮
private JButton loginButton = new JButton();
//注册按钮
private JButton registerButton = new JButton();
private JLabel username = new JLabel(new ImageIcon(path + "用户名.png"));
private JLabel password = new JLabel(new ImageIcon(path + "密码.png"));
private JLabel code = new JLabel(new ImageIcon(path + "验证码.png"));
JLabel jLabel = new JLabel(new ImageIcon(path + "background.png"));
//创建放置验证码的容器
JLabel rightCode = new JLabel();
private void setImage() {
this.getContentPane().removeAll();
//添加用户图片
username.setBounds(116, 135, 47, 17);
this.getContentPane().add(username);
//添加密码图片
password.setBounds(130, 195, 32, 16);
this.getContentPane().add(password);
//添加验证码图片
code.setBounds(133, 256, 50, 30);
this.getContentPane().add(code);
//添加用户文本框
usertext.setBounds(195, 134, 200, 30);
this.getContentPane().add(usertext);
//添加密码输入框
passtext.setBounds(195, 195, 200, 30);
this.getContentPane().add(passtext);
//添加验证码输入框
codetext.setBounds(195, 256, 100, 30);
this.getContentPane().add(codetext);
//设置验证码的内容
rightCode.setText(codeStr);
//设置验证码的大小
rightCode.setBounds(300, 256, 50, 30);
//将验证码放入界面
this.getContentPane().add(rightCode);
//将两个按钮插入界面
//登录按钮
loginButton.setBounds(123, 310, 128, 47);
loginButton.setIcon(new ImageIcon(LoButton));
//去除按钮的默认边框
loginButton.setBorderPainted(false);
//去除按钮的背景
loginButton.setContentAreaFilled(false);
this.getContentPane().add(loginButton);
//注册按钮
registerButton.setBounds(256, 310, 128, 47);
registerButton.setIcon(new ImageIcon(ReButton));
registerButton.setBorderPainted(false);
registerButton.setContentAreaFilled(false);
this.getContentPane().add(registerButton);
//背景图片
jLabel.setBounds(0, 0, 470, 390);
this.getContentPane().add(jLabel);
//刷新界面可要可不要
this.getContentPane().repaint();
}
private void initLogin() {
this.setSize(488, 430);
//设置软件的标题
this.setTitle("拼图 注册");
//设置是否覆盖其他软件
this.setAlwaysOnTop(true);
//设置在默认中间弹出窗口
this.setLocationRelativeTo(null);
//设置关闭游戏
this.setDefaultCloseOperation(3);
//监听
loginButton.addMouseListener(this);
registerButton.addMouseListener(this);
}
private boolean ifture() {
String username = usertext.getText();
String password = String.valueOf(passtext.getPassword());
String code = codetext.getText();
for (int i = 0; i < list.size(); i++) {
if (username.equals(list.get(i).username) && password.equals(list.get(i).password) && code.equalsIgnoreCase(codeStr)) {
new Game();
System.out.println("登录成功");
return true;
}
}
return false;
}
public static ArrayList<User> getList() {
return list;
}
@Override
//单机
public void mouseClicked(MouseEvent e) {
}
@Override
//按住不松
public void mousePressed(MouseEvent e){
Object obj = e.getSource();
if (obj == loginButton) {
LoButton = path + "登录按下.png";
setImage();
} else if (obj == registerButton) {
ReButton = path + "注册按下.png";
setImage();
}
}
@Override
//松开
public void mouseReleased(MouseEvent e) {
Object obj = e.getSource();
if (obj == loginButton) {
LoButton = path + "登录按钮.png";
setImage();
boolean flag = ifture();
if(flag){
System.out.println("登录成功!");
this.setVisible(false);
}else {
System.out.println("密码或账号或验证码错误!");
JDialog jDialog = new JDialog();
JLabel warning = new JLabel(" 登录失败!");
jLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
jDialog.getContentPane().add(warning);
//设置弹框的大小
jDialog.setSize(144,144);
//让弹框指定
jDialog.setAlwaysOnTop(true);
//让弹框居中
jDialog.setLocationRelativeTo(null);
//弹框不关闭则无法操作其他窗口
jDialog.setModal(true);
//让弹框显示
jDialog.setVisible(true);
}
}else if (obj == registerButton) {
ReButton = path + "注册按钮.png";
setImage();
new Register();
this.setVisible(false);
}
}
@Override
//划入
public void mouseEntered(MouseEvent e) {
}
@Override
//划出
public void mouseExited(MouseEvent e) {
}
}
4.注册类:
效果图如下:
完整代码如下:
import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
public class Register extends JFrame implements MouseListener {
private static ArrayList<User>list = Login.getList();
static {
User root = new User("root", "root");
list.add(root);
}
private String path = "game\\image\\register\\";
private JLabel background = new JLabel(new ImageIcon(path+"background.png"));
private JLabel username = new JLabel(new ImageIcon(path + "注册用户名.png"));
private JLabel password = new JLabel(new ImageIcon(path + "注册密码.png"));
private JLabel againword = new JLabel(new ImageIcon(path + "再次输入密码.png"));
private JTextField userText = new JTextField();
private JPasswordField passText = new JPasswordField();
private JPasswordField againpass = new JPasswordField();
private JButton registerButton = new JButton(new ImageIcon(path + "注册按钮.png"));
private JButton reset = new JButton(new ImageIcon(path + "重置按钮.png"));
public Register(){
initRegister();
setImage();
//设置是否显示窗口(建议放最后)
this.setVisible(true);
}
private void setImage() {
username.setBounds(116,175,79,17);
this.getContentPane().add(username);
password.setBounds(130,235,64,16);
this.getContentPane().add(password);
againword.setBounds(99,295,96,17);
this.getContentPane().add(againword);
userText.setBounds(210,170,160,30);
this.getContentPane().add(userText);
passText.setBounds(210,230,160,30);
this.getContentPane().add(passText);
againpass.setBounds(210,290,160,30);
this.getContentPane().add(againpass);
registerButton.setBounds(90,350,128,47);
//取消边框
registerButton.setBorderPainted(false);
//去除按钮的背景
registerButton.setContentAreaFilled(false);
this.getContentPane().add(registerButton);
reset.setBounds(240,350,128,47);
reset.setBorderPainted(false);
reset.setContentAreaFilled(false);
this.getContentPane().add(reset);
background.setBounds(0,0,470,600);
this.getContentPane().add(background);
}
private boolean adduser() {
boolean flag = false;
//获取输入
String username = userText.getText();
String password = String.valueOf(passText.getPassword());
String againword = String.valueOf(againpass.getPassword());
flag = Confirm.adduser(list,username,password,againword);
return flag;
}
private void initRegister() {
this.setSize(488,500);
//设置软件的标题
this.setTitle("拼图 注册");
//设置是否覆盖其他软件
this.setAlwaysOnTop(true);
//设置在默认中间弹出窗口
this.setLocationRelativeTo(null);
//设置关闭游戏
this.setDefaultCloseOperation(3);
registerButton.addMouseListener(this);
reset.addMouseListener(this);
}
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
Object obj = e.getSource();
if(obj == registerButton){
boolean flag = adduser();
if (flag){
new Login();
this.setVisible(false);
}
else{
JDialog jDialog = new JDialog();
JLabel jLabel = new JLabel(" 登录失败!");
jLabel.setFont(new Font("微软雅黑", Font.PLAIN, 18));
// jLabel.setText("<h1>登录失败!</h1>");
jLabel.setBounds(0,0,258,258);
//把图片添加到弹框
jDialog.getContentPane().add(jLabel);
//设置弹框的大小
jDialog.setSize(144,144);
//让弹框指定
jDialog.setAlwaysOnTop(true);
//让弹框居中
jDialog.setLocationRelativeTo(null);
//弹框不关闭则无法操作其他窗口
jDialog.setModal(true);
//让弹框显示
jDialog.setVisible(true);
System.out.println("失败");
}
} else if (obj == reset) {
new Login();
this.setVisible(false);
}
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
5.游戏主体类
效果图如下:
import javax.swing.*;
import javax.swing.border.BevelBorder;
import javax.xml.crypto.dsig.keyinfo.RetrievalMethod;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.Objects;
import java.util.Random;
public class Game extends JFrame implements KeyListener,ActionListener {
//创建一个二维数组,为了与游戏的布局相照应
//因为多个位置需要用到该二维数组
int[][] data = new int[4][4];
//定义一个图片路径
String path = "game\\image\\girl\\girl1\\";
//定义一个胜利的二维数组判断胜利
int[][] win = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12},
{13,14,15,0}
};
//统计步数
int step = 0;
//记录空白图片的位置
int x = 0;
int y = 0;
public Game() {
//初始化界面
initJFrame();
//初始化界面菜单
initJmenuBar();
//初始化数据(打乱)
initData();
//初始化图面
initImage();
//设置是否显示窗口(建议放最后)
this.setVisible(true);
}
//创建选项下面的条目对象
JMenuItem replayItem = new JMenuItem("重新游戏");
JMenuItem reLoginItem = new JMenuItem("重新登录");
JMenuItem closeItem = new JMenuItem("关闭游戏");
JMenuItem girls = new JMenuItem("美女");
JMenuItem animals = new JMenuItem("动物");
JMenuItem sport = new JMenuItem("运动");
JMenuItem accountItem = new JMenuItem("公众号");
private void initData() {
//1.定义一个数组
int[] tempArr = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//2.打乱数组中的数据顺序
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(ifwin()){
JLabel winJLabel = new JLabel(new ImageIcon("D:\\JavaProject1\\project1\\game\\image\\win.png"));
winJLabel.setBounds(203,283,197,73);
this.getContentPane().add(winJLabel);
}
//步数部分
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];
//创建图片IMageIcon对象
ImageIcon icon = new ImageIcon(path + num + ".jpg");
//创建一个JLabel的对象(管理容器)
JLabel jLabel = new JLabel(icon);
//指定图片位置
jLabel.setBounds(105 * j + 83, 105 * i + 134, 105, 105);
//给图片添加边框
//0:凸起来的效果
//1:凹下去的效果
jLabel.setBorder(new BevelBorder(1));
//把管理容器添加到界面当中
this.getContentPane().add(jLabel);
}
}
//添加背景图片
ImageIcon bg = new ImageIcon("game\\image\\background.png");
JLabel background = new JLabel(bg);
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(girls);
changeImage.add(animals);
changeImage.add(sport);
//将每一个选项下面的条目添加到选项中
functionJMenu.add(changeImage);
functionJMenu.add(replayItem);
functionJMenu.add(reLoginItem);
functionJMenu.add(closeItem);
aboutJmenu.add(accountItem);
//给条目绑定事件
girls.addActionListener(this);
animals.addActionListener(this);
sport.addActionListener(this);
replayItem.addActionListener(this);
reLoginItem.addActionListener(this);
closeItem.addActionListener(this);
accountItem.addActionListener(this);
//将菜单的里面的两个选项添加到菜单中
jMenuBar.add(functionJMenu);
jMenuBar.add(aboutJmenu);
//给整个界面设置菜单
this.setJMenuBar(jMenuBar);
}
private void initJFrame() {
//设置框高
this.setSize(603, 680);
//设置软件的标题
this.setTitle("拼图小游戏 v1.0.0");
//设置是否覆盖其他软件
this.setAlwaysOnTop(true);
//设置在默认中间弹出窗口
this.setLocationRelativeTo(null);
//设置关闭游戏
this.setDefaultCloseOperation(3);
//取消默认居中放置,关闭默认布局
this.setLayout(null);
//给整个添加一个键盘监听事件
this.addKeyListener(this);
}
@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 bg = new ImageIcon("game\\image\\background.png");
JLabel background = new JLabel(bg);
background.setBounds(40, 40, 508, 560);
//把背景图片添加到界面中
this.getContentPane().add(background);
//刷新界面
this.getContentPane().repaint();
}
}
@Override
public void keyReleased(KeyEvent e) {
if(ifwin()){
return;
}
//左:37 上:38 右:39 下 40
int code = e.getKeyCode();
// System.out.println(code);
if (code == 38) {
if(x == 3)
return;
data[x][y] = data[x + 1][y];
data[x + 1][y] = 0;
x++;
//每移动一步,就自加
step++;
initImage();
} else 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 == 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 ifwin(){
for(int i = 0;i<data.length;i++)
for (int j = 0; j < data[i].length; j++) {
if(data[i][j] != win[i][j]){
return false;
}
}
return true;
}
@Override
public void actionPerformed(ActionEvent e) {
//获取当前被点击的条目对象
Object obj = e.getSource();
if(obj == replayItem){
System.out.println("重新游戏");
//计数器清零
step = 0;
//打乱二维数组中的数据
initData();
//重新打乱图片
initImage();
} else if (obj == reLoginItem) {
System.out.println("重新登录");
this.setVisible(false);
new Login();
} 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("game\\image\\about.png"));
//设置位置和宽高
jLabel.setBounds(0,0,258,258);
//把图片添加到弹框
jDialog.getContentPane().add(jLabel);
//设置弹框的大小
jDialog.setSize(344,344);
//让弹框指定
jDialog.setAlwaysOnTop(true);
//让弹框居中
jDialog.setLocationRelativeTo(null);
//弹框不关闭则无法操作其他窗口
jDialog.setModal(true);
//让弹框显示
jDialog.setVisible(true);
} else if (obj == girls) {
System.out.println("点击了美女");
changeGirls();
}else if(obj == animals){
System.out.println("点击了动物");
changeAnimals();
}
else if(obj == sport){
System.out.println("点击了运动");
changeSports();
}
}
private void changeSports() {
Random r= new Random();
int num = r.nextInt(1,11);
path = "game\\image\\sport\\sport"+num+"\\";
initImage();
}
private void changeAnimals() {
Random r= new Random();
int num = r.nextInt(1,9);
path = "game\\image\\animal\\animal"+num+"\\";
initImage();
}
private void changeGirls() {
Random r= new Random();
int num = r.nextInt(1,14);
path = "game\\image\\girl\\girl"+num+"\\";
initImage();
}
}
6.游戏启动类:
public class Start {
public static void main(String[] args) {
// new Game();//用于测试
// new Register();//用于测试
new Login();
}
}