MBTI测试系统——java课程设计

用Java做一个MBTI测试系统

前情:网上MBTI测试系统不是题量冗杂,就是一股脑写完最后要收费,介于需求,借此java课程设计设计了一个MBTI人格测试测试系统,没用数据库,全程靠JSON文件存数据,轻量又好部署。

目录

  1. 项目核心要点
  2. 核心代码实现
  3. 项目亮点
  4. 效果展示
  5. 学习心得

一、项目核心要点

1. 功能定位

  • 交互式MBTI答题(30道题,覆盖E/I/S/N/T/F/J/P维度)
  • 自动计算维度得分+生成人格类型(比如ISTP)
  • JSON文件存测试结果(替代数据库,免配置)
  • ECharts可视化:个人维度占比+总体人格分布

2. 技术栈

  • 语言:Java
  • 界面:Java Swing(GUI界面
  • 数据存储:JSON(Gson解析)
  • 可视化:ECharts 5.x
  • 工具:IDEA + Git

3. 包结构(分层解耦)

com.mbti
├─ entity    // 实体类:TestResult(测试结果)、MBTIDimension(维度得分)
├─ dao       // 数据层:ResultDao(JSON文件读写)
├─ gui       // 界面层:TestFrame(答题界面)、ResultFrame(结果界面)
├─ chart     // 可视化层:EChartsUtil(生成图表HTML)
└─ util      // 工具类:FileUtil(文件操作)

{E0B471A9-3E03-4C72-9337-FC4B794C4FCA}

图1.1项目具体分包结构

二、核心代码实现

1. JSON文件使用(替代数据库)

ResultDao类操作桌面的mbti_results.json文件,实现结果的增删查:

package com.mbti.dao;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.mbti.entity.TestResult;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class ResultDao {
    // 固定存桌面,跨环境通用
    private static final String JSON_PATH = 
        System.getProperty("user.home") + "/Desktop/mbti_results.json";
    private final Gson gson = new GsonBuilder().setPrettyPrinting().create();

    // 查:读取所有测试结果
    public List<TestResult> readAllResults() {
        File file = new File(JSON_PATH);
        if (!file.exists()) return new ArrayList<>();
        try (FileReader reader = new FileReader(file, StandardCharsets.UTF_8)) {
            return gson.fromJson(reader, new TypeToken<List<TestResult>>() {}.getType());
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    // 增:写入新测试结果
    public void writeResult(TestResult result) {
        List<TestResult> results = readAllResults();
        results.add(result);
        try (FileWriter writer = new FileWriter(JSON_PATH, StandardCharsets.UTF_8)) {
            gson.toJson(results, writer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2. 答题逻辑以及四个不同维度得分计算

TestFrame(答题界面)里收集答案,计算E/I/S/N/T/F/J/P得分:

package com.mbti.gui;

import com.mbti.entity.MBTIDimension;
import com.mbti.entity.TestResult;
import com.mbti.dao.ResultDao;
import com.mbti.chart.EChartsUtil;

import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;

public class TestFrame extends JFrame {
    private final List<String> answers = new ArrayList<>();
    // MBTI题目(示例,实际30题)
    private final String[][] questions = {
        {"你更爱独处?", "I", "E"},
        {"你关注细节?", "S", "N"}
    };
    private int currentQ = 0;

    public TestFrame() {
        initUI();
        showQuestion();
    }

    private void initUI() {
        setTitle("MBTI测试");
        setSize(600, 400);
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new BorderLayout());
    }

    // 展示题目
    private void showQuestion() {
        getContentPane().removeAll();
        JLabel qLabel = new JLabel((currentQ+1)+". "+questions[currentQ][0]);
        JButton opt1 = new JButton("选项A");
        JButton opt2 = new JButton("选项B");

        // 选项点击事件
        opt1.addActionListener(e -> {
            answers.add(questions[currentQ][1]);
            nextQuestion();
        });
        opt2.addActionListener(e -> {
            answers.add(questions[currentQ][2]);
            nextQuestion();
        });

        add(qLabel, BorderLayout.NORTH);
        add(opt1, BorderLayout.WEST);
        add(opt2, BorderLayout.EAST);
        revalidate();
    }

    // 下一题/提交
    private void nextQuestion() {
        currentQ++;
        if (currentQ < questions.length) {
            showQuestion();
        } else {
            // 计算得分
            MBTIDimension dim = calculateDimension();
            TestResult result = new TestResult(dim, getMbtiType(dim));
            // 存JSON
            new ResultDao().writeResult(result);
            // 展示结果+生成图表
            new ResultFrame(result).setVisible(true);
            EChartsUtil.showMyDimensionChart(dim.getScores());
            dispose();
        }
    }

    // 计算四大维度得分
    private MBTIDimension calculateDimension() {
        int ei = 0, sn = 0, tf = 0, jp = 0;
        for (String ans : answers) {
            switch (ans) {
                case "E" -> ei++; case "I" -> ei--;
                case "S" -> sn++; case "N" -> sn--;
                case "T" -> tf++; case "F" -> tf--;
                case "J" -> jp++; case "P" -> jp--;
            }
        }
        return new MBTIDimension(ei, sn, tf, jp);
    }

    // 生成MBTI类型(比如ISTP)
    private String getMbtiType(MBTIDimension dim) {
        String ei = dim.getEi() > 0 ? "E" : "I";
        String sn = dim.getSn() > 0 ? "S" : "N";
        String tf = dim.getTf() > 0 ? "T" : "F";
        String jp = dim.getJp() > 0 ? "J" : "P";
        return ei + sn + tf + jp;
    }
}

3. ECharts可视化(生成HTML即为跳转网页展示)

EChartsUtil拼HTML模板,生成维度占比图

package com.mbti.chart;

import javax.swing.*;
import java.awt.Desktop;
import java.io.File;
import java.io.FileWriter;
import java.nio.charset.StandardCharsets;

public class EChartsUtil {
    // 生成个人维度占比图
    public static void showMyDimensionChart(int[] scores) {
        String html = "<!DOCTYPE html><html>" +
            "<head><meta charset='UTF-8'><script src='https://cdn.jsdelivr.net/npm/echarts@5.4.3/dist/echarts.min.js'></script></head>" +
            "<body><div id='chart' style='width:800px;height:600px;margin:0 auto'></div>" +
            "<script>" +
            "var chart = echarts.init(document.getElementById('chart'));" +
            "var option = {" +
            "  title: {text: '你的MBTI维度占比'}, " +
            "  xAxis: {data: ['E/I', 'S/N', 'T/F', 'J/P']}, " +
            "  yAxis: {type: 'value'}, " +
            "  series: [{type: 'bar', data: ["+scores[0]+","+scores[1]+","+scores[2]+","+scores[3]+"]}]" +
            "};" +
            "chart.setOption(option);" +
            "</script></body></html>";

        // 写HTML到桌面
        String path = System.getProperty("user.home") + "/Desktop/my_mbti.html";
        try (FileWriter writer = new FileWriter(path, StandardCharsets.UTF_8)) {
            writer.write(html);
            // 自动打开
            Desktop.getDesktop().open(new File(path));
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, "图表生成失败:"+e.getMessage());
        }
    }
}

三、项目亮点

  1. JSON替代数据库:免安装、轻量,直接存桌面,IDEA/JAR运行都能读
  2. ECharts可视化:不用Java原生图表,前端可视化更美观
  3. Swing界面交互:答题流程丝滑,按钮/题目切换无卡顿
  4. 面向对象设计:分层包结构,后续修改代码定位更加便捷

四、效果展示

  • 答题界面:简洁选项,自动切换题目
  • 结果界面:显示人格类型+鼓励语
  • 图表界面:桌面生成HTML,打开是ECharts柱状图

{606447C4-5228-4008-AD9F-61E76E766371}

图2.1进入系统的首要介绍界面

{60443929-8E5C-4F08-966F-F2EA503B0503}

图2.2答题界面

{059DFE06-9B11-46AE-95C6-63F18CC9159C}

图2.3页面跳转,可视化人格各维度占比

{79642036-6625-4DC9-8397-102DE0E42DE1}

图2.4参与过测试的所有人的人格占比,不会有有信息显示,直观占比

五、学习心得

  1. 初步选择的是文件存储,用 JSON 直接存储在桌面,跨 Windows/macOS 系统运行无压力,Gson 解析更加简洁,更适合小型桌面单机程序的轻量化需求
  2. 分层设计:将实体、数据操作、界面、可视化模块分层解耦,后期作出修改,仅需在 dao 层扩展 JSON 读写方法,无需修改其他模块代码,效率与准确定位修改时效性大幅增加
  3. 可视化前端的设计:不同于以往课设,想追求一个美观的可视化前端,记得老师所提及的ECharts,我选择用 ECharts 生成 HTML 文件,跳转网页,满足我所想要的可视化美观呈现
  4. 异常处理阶段:最为难磨的时期,JSON 文件缺失、界面乱码各种问题,先找到问题根源,一步一步解决;后续通过补充文件,找到异常弹窗相关代码修改等逻辑体系,最后成功运行到理想化程度
  5. 优化提升用户体验:通过JAR打包至桌面直接应用程序,其中乱码以及页面跳转问题,编码的不一致的修改,以及网页的跳转可视化,解决在如今时代下,人们很难静下心做一件事;题量相对较少,言简意赅,
    可视化的面向互动,无论你是什么人格,我希望你都别被所谓的标签所束缚,做自己的主人!
posted @ 2026-01-15 11:38  Jbuckle  阅读(1)  评论(0)    收藏  举报