24点游戏
使用技术:JDBC相关数据库技术,GUI页面设计,相应算法等
算法部分是借鉴以下链接的:(也自我进行了很多修改)
24点算法原创<···点击进入
【实验名称】
利用swing技术,数据库技术(JDBC),算法等来实现24点小游戏
【实验目的】
1.掌握面向对象程序设计基本要素;
2.掌握Java语言常用类包及其常用方法和Java语言基本语法;
3.掌握图形用户界面设计,包括常用标准控件的使用、事件处理机制、布局管理和对话框的使用;
4.掌握利用JDBC对数据库的基本操作,包括连接数据库,关闭数据库,顺序查询,预处理语句,和添加,修改删除记录等。
5.掌握数据库与图形界面的连接,以及游戏框架与游戏算法的连接。
【实验内容】
主页面(游戏界面):
主体页面,有6个按钮:分别为提交、登录/注册、排行榜、规则、开始游戏、退出。这些按钮实现了对各个其他界面的交互,而且24点整个游戏的游玩也是通过这个界面进行的。在登陆和注册之后,点击开始游戏,便开始游玩,在下面的文本框中输入内容,并点击提交按钮,就会进行计算,正确进入下一关并获得分数并加到历史分数中,关卡越高相对应的分数也就越高,错误则返回第一关重新开始。
登录/注册页面:
(1)若要登陆,必须要填写正确的用户名和密码,然后点击登录,若与数据库中的信息不相匹配,则会弹出密码/用户名错误的信息并返回当前登录/注册页面重新输入,若正确,则登入时的用户就为当前用户并进入主页面。
(2)若要注册,必须要填写数据库中没有的用户和自定义的密码进行注册,若已经存在该用户,那么会弹出已存在该用户并返回当前登录/注册页面重新输入,若为新用户,则立即登入该新用户并进入主页面。
排行榜页面:(历史排行榜)
连接数据库并实时更新数据,只显示数据库中历史成绩排名前10的用户以及他们的得分。
规则页面:
告诉用户该游戏的规则。
以下是代码:(写在同一个文件,可能有点乱)
import java.awt.*;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.Vector;
//算法部分
class suanfa {
//存放可能的情况
static Vector<String> vector = new Vector<String>();
//定义随机产生的四个数
static int[] poker = new int[4];
//转换后的四个数
static int m[]=new int [4];
static String n[] = new String[4];
//用来判断是否有解
static boolean flag = false;
//存放操作符
static char[] operator = { '+', '-', '*', '/' };
public void startsuanfa(){
Random rand = new Random();
//"随机产生四个数字,使用+,-,*,/进行计算,使最后计算结果为24"
for(int i=0;i<4;i++){
//随机生成四个不同的int型数
while(true){
int number = rand.nextInt(13)+1;
if(!contains(poker,number)){
poker[i] = number;
break;
}
}
}
calculate();
if(vector.size()==0){//如果vector中没有元素,说明当前这四个数是不能变成24(生成一定能转化为24的四个随机数)
startsuanfa();//出现该种情况,则重新调用,重新生成四个随机数
}
}
//清除vector中所有的值
public void clearvec(){
vector.clear();
}
//返回相应的四个随机数的值
public String getN(int i){
return n[i];
}
//判断用户是否对
public boolean isVecnum(String s) {
for (int i = 0; i < vector.size(); i++) {
if (s.equals(vector.get(i))){
return true;
}
}
return false;
}
//判断是否有重复
public static boolean contains(int[] arr, int key) {
for (int i=0; i<arr.length; i++) {
//如果相等返回true
if (arr[i] == key){
return true;
}
}
return false;
}
//计算生成24的函数
public static void calculate(){
Map<Integer, Integer> map = new HashMap<Integer, Integer>();
//存放数字,用来判断输入的4个数字中有几个重复的,和重复的情况
for (int i = 0; i < poker.length; i++) {
if(map.get(poker[i]) == null){
map.put(poker[i], 1);
}
else {
map.put(poker[i], map.get(poker[i]) + 1);
}
}
if(map.size() == 4){
//4个数都不同的情况
int i,j,k,l;
for (i=0; i<4; i++) //4的排列 4!=24,每种情况调用calculation
for (j=0; j<4; j++)
if (j!=i) //第2数和第1个数不能重复
for (k=0; k<4; k++)
if (k!=j && k!=i) //第3数和第1,2个数不能重复
for (l=0; l<4; l++)
if (l!=i && l!=j && l!=k) //第4数和第1,2,3个数不能重复
{
calculation(poker[i],poker[j],poker[k],poker[l]);//调用calculation函数,进行进行加、减、乘、除运算
}
}
}
//进行转换
public static void show(int[] m, int p){
if(m[p]==1){
n[p]="A";}
if(m[p]==2){
n[p]="2";}
if(m[p]==3){
n[p]="3";}
if(m[p]==4){
n[p]="4";}
if(m[p]==5){
n[p]="5";}
if(m[p]==6){
n[p]="6";}
if(m[p]==7){
n[p]="7";}
if(m[p]==8){
n[p]="8";}
if(m[p]==9){
n[p]="9";}
if(m[p]==10){
n[p]="10";}
if(m[p]==11){
n[p]="J";}
if(m[p]==12){
n[p]="Q";}
if(m[p]==13){
n[p]="K";}
}
//把这四个数能成为24的所有例子存到可变数组Vector中
public static void calculation(int num1, int num2, int num3, int num4){
for (int i = 0; i < 4; i++){
//第1次计算,先从四个数中任意选择两个进行计算
char operator1 = operator[i];
int firstResult = calcute(num1, num2, operator1);//先选第一,和第二个数进行计算
int midResult = calcute(num2, num3, operator1);//先选第二和第三两个数进行计算
int tailResult = calcute(num3,num4, operator1);//先选第三和第四俩个数进行计算
for (int j = 0; j < 4; j++){
//第2次计算,从上次计算的结果继续执行,这次从三个数中选择两个进行计算
char operator2 = operator[j];
int firstMidResult = calcute(firstResult, num3, operator2);
int firstTailResult = calcute(num3,num4,operator2);
int midFirstResult = calcute(num1, midResult, operator2);
int midTailResult= calcute(midResult,num4,operator2);
int tailMidResult = calcute(num2, tailResult, operator2);
for (int k = 0; k < 4; k++){
//第3次计算,也是最后1次计算,计算两个数的结果,如果是24则输出表达式
char operator3 = operator[k];
//在以上的计算中num1,num2,num3,num4都是整型数值,但若要输出为带有A,J,Q,K的表达式,则要将这四个数都变为String类型,下同
if(calcute(firstMidResult, num4, operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
vector.add("((" + n[0] + operator1 + n[1] + ")" + operator2 + n[2] + ")" + operator3 + n[3]);
flag = true;//若有表达式输出,则将说明有解,下同
}
if(calcute(firstResult, firstTailResult, operator3) == 24){
vector.add("(" + n[0] + operator1 + n[1] + ")" + operator3 + "(" + n[2] + operator2 + n[3] + ")");
flag = true;
}
if(calcute(midFirstResult, num4, operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
vector.add("(" + n[0] + operator2 + "(" + n[1] + operator1 + n[2] + "))" + operator3 + n[3]);
flag = true;
}
if(calcute(num1,midTailResult, operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
vector.add( n[0] + operator3 + "((" + n[1] + operator1 + n[2] + ")" + operator2 + n[3] + ")");
flag = true;
}
if(calcute(num1,tailMidResult,operator3) == 24){
m[0]=num1;
m[1]=num2;
m[2]=num3;
m[3]=num4;
for(int p=0;p<4;p++){
show(m, p);
}
vector.add( n[0] + operator3 + "(" + n[1] + operator2 + "(" + n[2] + operator1 + n[3] + "))");
flag = true;
}
}
}
}
}
//给定2个数和指定操作符的计算
public static int calcute(int count1, int count2, char operator) {
if (operator == '+') {
return count1 + count2;
}
else if (operator == '-') {
return count1 - count2;
}
else if (operator == '*') {
return count1 * count2;
}
else if ((operator == '/' )&& (count2 != 0) && (count1%count2==0)) {
return count1 / count2;
}
else {
return -1000;//返回一个比较大的负数,则就不会变成24,说明不成立
}
}
}
//游戏规则窗口
class mydialog1 extends JDialog {
public mydialog1(xiangmu frame) {
super(frame, "规则", true);
Container container = getContentPane();
JTextArea jTextArea = new JTextArea();
container.add(jTextArea);
jTextArea.append("本游戏为:24点" +
"\n排行榜为:历史排行榜" +
"\n具体规则如下:" +
"\n给出4个不同的数字(牌),所给数字均为有整数 (1至13之间,一般用扑克牌拿掉王最好),用加、减、乘、" +
"\n除四种方法并且用()将每一步计算步骤都套进去,把给出的数算成24,答对者会相应加分,连续答对会提高" +
"\n难度,相应的也会得到更高的分数,答错便会从第一关重新开始。所得分数会相应的加进当前账号的历史成绩"+
"\n中。列算式例如这样:((K-A)*4)/2");
jTextArea.setFont(new Font("微软雅黑",Font.PLAIN,14));
setLayout(new FlowLayout());
setBounds(250, 250, 700, 240);
}
}
//排行榜窗口
class mydialog2 extends JDialog {
public mydialog2(xiangmu frame) {
super(frame, "排行榜", true);
setLayout(new FlowLayout());
setBounds(250, 250, 250, 250);
}
}
//登录和注册
class mydialog3 extends JDialog {
public mydialog3(xiangmu frame) {
super(frame, "登录/注册", true);
Container container = getContentPane();
//用户名框
JLabel jLabel1 = new JLabel("用户名:");
jLabel1.setBounds(20, 20, 60, 25);
JTextField jTextField = new JTextField();
jTextField.setBounds(120, 20, 100, 25);
//密码框
JLabel jLabel2 = new JLabel("密码:");
jLabel2.setBounds(20, 60, 60, 25);
JPasswordField jPasswordField = new JPasswordField();
jPasswordField.setEchoChar('*');
jPasswordField.setBounds(120, 60, 100, 25);
//登录按钮
JButton jButton = new JButton("登录");
jButton.setBounds(90, 100, 120, 25);
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
xiangmu xiangmu = new xiangmu();
String name = jTextField.getText();
char ch[] = jPasswordField.getPassword();
String password = new String(ch);
if (xiangmu.isuser(password, name)) {
dispose();
JOptionPane.showMessageDialog(null,
"登陆成功",
"登陆界面",
JOptionPane.INFORMATION_MESSAGE);
xiangmu.dispose();
new xiangmu();
} else {
JOptionPane.showMessageDialog(null,
"密码/账号错误",
"发生错误",
JOptionPane.ERROR_MESSAGE);
xiangmu.dispose();
}
}
});
//注册按钮
JButton jButton1 = new JButton("注册");
jButton1.setBounds(90, 140, 120, 25);
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
xiangmu xiangmu = new xiangmu();
String name = jTextField.getText();
char ch[] = jPasswordField.getPassword();
String password = new String(ch);
if (xiangmu.isname(name)){
JOptionPane.showMessageDialog(null,
"用户已存在",
"发生错误",
JOptionPane.ERROR_MESSAGE);
xiangmu.dispose();
}else {
xiangmu.add(name, password, 0);
dispose();
JOptionPane.showMessageDialog(null,
"注册成功",
"成功注册新用户",
JOptionPane.INFORMATION_MESSAGE);
xiangmu.dispose();
new xiangmu();
}
}
});
setLayout(null);
container.add(jLabel1);
container.add(jTextField);
container.add(jLabel2);
container.add(jPasswordField);
container.add(jButton);
container.add(jButton1);
setBounds(250, 250, 250, 230);
}
}
//项目
public class xiangmu extends JFrame {
public static String nowuser = "";//当前用户名
public static int score = 0;//当前分数
public static int guanka=1;
//数据库
static Connection connection;
//连接数据库
static public void initConnection() {
try {
Class.forName("com.mysql.cj.jdbc.Driver");
} catch (Exception e) {
e.printStackTrace();
}
try {
connection = DriverManager.getConnection("jdbc:mysql://localhost:3306/24dian", "root", "123456");
} catch (Exception e) {
e.printStackTrace();
}
}
//关闭数据库
static public void closeConnection() {
if (connection != null) {
try {
connection.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
//判断用户的用户名和密码是否正确
public boolean isuser(String password, String name) {
try {
nowuser = name;
Statement stmt = connection.createStatement();
ResultSet res = stmt.executeQuery("select * from users where password = '" + password + "' and name = '" + name + "'");
if (res.next()) {
score=res.getInt("grade");
return true;
} else {
return false;
}
} catch (Exception e) {
return false;
}
}
//是否存在该用户
public boolean isname(String name){
try {
Statement stmt = connection.createStatement();
ResultSet res = stmt.executeQuery("select * from users where name = '" + name + "'");
if (res.next()) {
return true;
}else {
return false;
}
}catch (Exception e){
return false;
}
}
//向数据库添加新用户信息
public void add(String name, String password, int grade) {
try {
nowuser = name;//设置当前用户
String sql = "insert into users values(?,?,?)";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setString(1, name);
ps.setString(2, password);
ps.setInt(3, grade);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
//排行榜
public void rankusers(xiangmu frame) {
try {
Statement stmt = connection.createStatement();
ResultSet res = stmt.executeQuery("select name,grade from users order by grade desc;");
mydialog2 mydialog2 = new mydialog2(frame);
Container container = mydialog2.getContentPane();
JTextArea jTextArea = new JTextArea();
container.add(jTextArea);
jTextArea.append("排行榜:");
int rank = 0;
while (res.next()&&rank<=9) {
String name = res.getString("name");
int grade = res.getInt("grade");
rank++;
jTextArea.append("\n" + rank + "." + name + ": " + grade);
}
mydialog2.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
//向数据库中当前用户加分
public static void addgrade(){
score+=guanka*5;
try {
PreparedStatement ps = connection.prepareStatement("update users set grade =? where name ='"+nowuser+"'");
ps.setInt(1,score);
ps.executeUpdate();
}catch (Exception e){
e.printStackTrace();
}
}
public xiangmu() {
//连接算法
suanfa suanfa = new suanfa();
//主框架jFrame
Container container = getContentPane();
setLayout(null);
setTitle("24点游戏");
setBounds(200, 200, 500, 450);
//显示用户名字
JLabel jLabel1 = new JLabel("用户:" + nowuser);
container.add(jLabel1);
jLabel1.setBounds(10, 10, 80, 25);
//显示分数
JLabel jLabel2 = new JLabel("分数:" + score);
container.add(jLabel2);
jLabel2.setBounds(390, 10, 80, 25);
//显示关卡
JLabel jLabel3=new JLabel("第"+guanka+"关");
container.add(jLabel3);
jLabel3.setBounds(210,10,90,25);
//游戏内容
JTextArea jTextArea1 = new JTextArea();
container.add(jTextArea1);
jTextArea1.setFont(new Font("微软雅黑",Font.PLAIN,12));
jTextArea1.setBounds(10, 50, 460, 70);
//扑克牌
JPanel jPanel = new JPanel();
container.add(jPanel);
jPanel.setBounds(10,120,460,105);
jPanel.setLayout(new GridLayout(1,4,5,5));
JLabel j1 = new JLabel();
Icon icon1 = new ImageIcon("src/images/bg.png");
j1.setIcon(icon1);
j1.setHorizontalAlignment(SwingConstants.CENTER);
j1.setOpaque(true);
JLabel j2 = new JLabel();
Icon icon2 = new ImageIcon("src/images/bg.png");
j2.setIcon(icon2);
j2.setHorizontalAlignment(SwingConstants.CENTER);
j2.setOpaque(true);
JLabel j3 = new JLabel();
Icon icon3 = new ImageIcon("src/images/bg.png");
j3.setIcon(icon3);
j3.setHorizontalAlignment(SwingConstants.CENTER);
j3.setOpaque(true);
JLabel j4 = new JLabel();
Icon icon4 = new ImageIcon("src/images/bg.png");
j4.setIcon(icon4);
j4.setHorizontalAlignment(SwingConstants.CENTER);
j4.setOpaque(true);
jPanel.add(j1);
jPanel.add(j2);
jPanel.add(j3);
jPanel.add(j4);
//用户输入
JTextArea jTextArea2 = new JTextArea();
container.add(jTextArea2);
jTextArea2.setFont(new Font("微软雅黑",Font.PLAIN,12));
jTextArea2.setBounds(10, 230, 460, 50);
//提交按钮
JButton jButton1 = new JButton("提交");
container.add(jButton1);
jButton1.setBounds(10, 285, 80, 40);
jButton1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String ans = jTextArea2.getText();
if (suanfa.isVecnum(ans)){
JOptionPane.showMessageDialog(null,
"你对了,你这关得了"+guanka*5+"分",
"成功进入下一关",
JOptionPane.INFORMATION_MESSAGE);
addgrade();
jLabel2.setText("分数:" + score);
guanka++;
jLabel3.setText("第"+guanka+"关");
jTextArea1.setText("");
jTextArea2.setText("");
jTextArea1.append(nowuser+"用户。现在是第"+guanka+"关。" +
"\n使用下面的牌,用加、减、乘、除四种方法,把给出的数算成24并写在下面的文本框中:\n");
}else{
JOptionPane.showMessageDialog(null,
"你错了",
"返回第一关",
JOptionPane.ERROR_MESSAGE);
guanka=1;
jLabel3.setText("第"+guanka+"关");
jTextArea1.setText("");
jTextArea2.setText("");
jTextArea1.append(nowuser+"用户。上次你输了,现在变回到是第"+guanka+"关。" +
"\n使用下面的牌,用加、减、乘、除四种方法,把给出的数算成24并写在下面的文本框中:\n");
}
suanfa.clearvec();
suanfa.startsuanfa();
jTextArea1.append(suanfa.getN(0)+" "+suanfa.getN(1)+" "+suanfa.getN(2)+" "+suanfa.getN(3));
Icon icon1 = new ImageIcon("src/images/"+suanfa.getN(0)+".png");
j1.setIcon(icon1);
j1.setHorizontalAlignment(SwingConstants.CENTER);
j1.setOpaque(true);
Icon icon2 = new ImageIcon("src/images/"+suanfa.getN(1)+".png");
j2.setIcon(icon2);
j2.setHorizontalAlignment(SwingConstants.CENTER);
j2.setOpaque(true);
Icon icon3 = new ImageIcon("src/images/"+suanfa.getN(2)+".png");
j3.setIcon(icon3);
j3.setHorizontalAlignment(SwingConstants.CENTER);
j3.setOpaque(true);
Icon icon4 = new ImageIcon("src/images/"+suanfa.getN(3)+".png");
j4.setIcon(icon4);
j4.setHorizontalAlignment(SwingConstants.CENTER);
j4.setOpaque(true);
}
});
//开始按钮
JButton jButton = new JButton("开始游戏");
container.add(jButton);
jButton.setBounds(10, 340, 140, 40);
jButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
jTextArea1.setText("");
jTextArea2.setText("");
jTextArea1.append("你好!\n"+nowuser+"用户,游戏开始了。现在是第"+guanka+"关。" +
"\n使用下面的牌,用加、减、乘、除四种方法,把给出的数算成24并写在下面的文本框中:\n");
suanfa.startsuanfa();
jTextArea1.append(suanfa.getN(0)+" "+suanfa.getN(1)+" "+suanfa.getN(2)+" "+suanfa.getN(3));
Icon icon1 = new ImageIcon("src/images/"+suanfa.getN(0)+".png");
j1.setIcon(icon1);
j1.setHorizontalAlignment(SwingConstants.CENTER);
j1.setOpaque(true);
Icon icon2 = new ImageIcon("src/images/"+suanfa.getN(1)+".png");
j2.setIcon(icon2);
j2.setHorizontalAlignment(SwingConstants.CENTER);
j2.setOpaque(true);
Icon icon3 = new ImageIcon("src/images/"+suanfa.getN(2)+".png");
j3.setIcon(icon3);
j3.setHorizontalAlignment(SwingConstants.CENTER);
j3.setOpaque(true);
Icon icon4 = new ImageIcon("src/images/"+suanfa.getN(3)+".png");
j4.setIcon(icon4);
j4.setHorizontalAlignment(SwingConstants.CENTER);
j4.setOpaque(true);
}
});
//登录和注册按钮
JButton jButton2 = new JButton("登录/注册");
container.add(jButton2);
jButton2.setBounds(120, 285, 120, 40);
jButton2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
mydialog3 mydialog3 = new mydialog3(xiangmu.this);
mydialog3.setVisible(true);
}
});
//排行榜按钮
JButton jButton3 = new JButton("排行榜");
container.add(jButton3);
jButton3.setBounds(260, 285, 80, 40);
jButton3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
dispose();
xiangmu xiangmu = new xiangmu();
xiangmu.rankusers(xiangmu);
}
});
//规则按钮
JButton jButton4 = new JButton("规则");
container.add(jButton4);
jButton4.setBounds(370, 285, 80, 40);
jButton4.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
mydialog1 mydialog1 = new mydialog1(xiangmu.this);
mydialog1.setVisible(true);
}
});
//退出按钮
JButton jButton5 = new JButton("退出");
container.add(jButton5);
jButton5.setBounds(370, 340, 80, 40);
jButton5.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
closeConnection();
dispose();
}
});
this.getContentPane().setBackground(Color.orange);
setVisible(true);
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
//主函数
public static void main(String[] args) {
initConnection();//开启数据库连接
new xiangmu();//启动项目
}
}
这是我的整个项目的代码,建议不要整篇照搬,尽量理解并进行自己修改。
(PS:数据库的库名和表名别忘记改,还有就是我用的是MYSQL,如果用其他的去使用相应的加载数据库的驱动器)
下面是我数据库的截图:
主题页面:(页面有点丑,请见谅=-=)
图片文件:(自己去网上找) :)
此项目是本人原创,严禁照搬发布!!!