Java编程进阶:打造专属于你的背单词软件V1.0

今天带大家从零实现背单词软件V1.0,涵盖文件数据读取、随机抽题、字符串处理等核心知识点,代码注释超详细,一看就会!

一、项目核心功能(对标文档需求)

(1) 读取本地单词文件(支持CET4/CET6词库)

(2) 随机抽取单词并隐藏一个字母

(3)接收用户输入,判断答案对错并反馈

(4)循环出题,直到手动退出

二、必备知识点预热(新手必看)

在写代码前,先搞懂这几个关键技术点:

  • ArrayList集合:存储单词和对应的中文翻译,比数组更灵活(支持动态添加元素)
  • 文件IO流:用FileReader+BufferedReader读取本地txt文件,实现"词库外置"
  • Random类:生成随机数,用于随机选单词、随机隐藏字母
  • String类方法:substring(截取字符串)、split(拆分字符串)、charAt(获取指定位置字符)
  • Scanner类:接收用户控制台输入

三、完整代码实现(逐行注释)

(1)准备词库文件

1. 在项目根目录创建 wordslib 文件夹
2. 新建 CET4.txt 和 CET6.txt,按"英文#中文"格式写单词(示例):

(2)完整代码展示

java 复制代码
// 导入所需工具类(新手记住:用到什么导什么)
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class WordsDemo {
    public static void main(String[] args) {
        // 1. 创建工具类对象
        Scanner sc = new Scanner(System.in); // 接收用户输入
        Random ran = new Random(); // 生成随机数
        ArrayList<String> words = new ArrayList<>(); // 存英文单词
        ArrayList<String> chineseWords = new ArrayList<>(); // 存中文翻译
        String wordsLib = ""; // 存储词库文件路径

        // 2. 让用户选择词库
        System.out.println("请选择对应的单词表编号:");
        System.out.println("=====1001-CET4=====");
        System.out.println("=====1002-CET6=====");
        int num = sc.nextInt(); // 读取用户选择的编号

        // 3. 根据选择确定词库路径
        if (num == 1001) {
            wordsLib = "wordslib/CET4.txt";
        } else if (num == 1002) {
            wordsLib = "wordslib/CET6.txt";
        } else {
            System.out.println("编号错误!默认使用CET4词库~");
            wordsLib = "wordslib/CET4.txt";
        }

        // 4. 读取词库文件(核心:文件IO流操作)
        File file = new File(wordsLib); // 创建文件对象,关联词库文件
        try {
            // FileReader:读取文件字符流;BufferedReader:缓冲流,提高读取效率
            FileReader fr = new FileReader(file);
            BufferedReader br = new BufferedReader(fr);

            String line; // 存储每次读取的一行数据
            // 循环读取每一行,直到文件末尾(line为null时结束)
            while ((line = br.readLine()) != null) {
                // 按"#"拆分字符串,得到英文和中文(比如"hello#你好"拆成["hello","你好"])
                String[] strs = line.split("#");
                String eng = strs[0]; // 英文单词
                String chinese = strs[1]; // 中文翻译
                words.add(eng); // 加入英文集合
                chineseWords.add(chinese); // 加入中文集合
            }
            br.close(); // 关闭缓冲流
            fr.close(); // 关闭文件流
        } catch (FileNotFoundException e) {
            // 捕获"文件找不到"异常(比如路径写错、文件删除了)
            throw new RuntimeException("词库文件找不到!请检查路径是否正确", e);
        } catch (IOException e) {
            // 捕获文件读取异常(比如文件损坏)
            throw new RuntimeException("文件读取失败!", e);
        }

        // 5. 循环出题(核心:随机抽题+字符串处理)
        int len = words.size(); // 获取单词总数
        while (true) { // 外层循环:一直出题,直到手动停止
            // 生成随机索引,从集合中选一个单词(0到len-1,避免数组越界)
            int index = ran.nextInt(len);
            String word = words.get(index); // 获取选中的英文单词
            String chinese = chineseWords.get(index); // 对应的中文翻译

            // 生成随机位置,隐藏该位置的字母(0到单词长度-1)
            int charIndex = ran.nextInt(word.length());
            char ch = word.charAt(charIndex); // 记录被隐藏的字母

            // 构建带下划线的单词(比如"hello"隐藏第2个字母变成"he_lo")
            // substring(0, charIndex):截取从开头到隐藏位置前的字符
            // substring(charIndex + 1):截取从隐藏位置后到结尾的字符
            String newWord = word.substring(0, charIndex) + "_" + word.substring(charIndex + 1);

            // 内层循环:直到用户猜对才换下一题
            while (true) {
                System.out.println("\n请猜出该单词缺失的字母: " + newWord);
                String nch = sc.next(); // 读取用户输入的字母
                char newCh = nch.charAt(0); // 转成字符(用户输入单个字母)

                // 判断答案是否正确
                if (newCh == ch) {
                    System.out.println("正确~! 完整单词:" + word + "  中文释义:" + chinese);
                    break; // 猜对了,跳出内层循环,换下一题
                } else {
                    System.out.println("错误!请重新输入!");
                }
            }
        }
    }
}

四、关键知识点详解(对应代码)

1. 集合与数组的区别

  • 代码中用ArrayList而不是数组,因为数组长度固定,而ArrayList可以动态添加元素(读取多少单词就存多少)
  • 常用方法:add(元素)添加数据、get(索引)获取数据、size()获取元素个数

2. 文件读取为什么用两个流?

  • **FileReader:**基础文件读取流,只能逐个字符读,效率低
  • **BufferedReader:**缓冲流,先把文件数据读到缓冲区,再批量处理,效率高
  • **注意:**流使用后必须关闭(close()),否则会占用系统资源

3. 字符串处理核心方法

  • split("#"):按指定字符拆分字符串,返回字符串数组(比如处理"英文#中文"格式)
  • substring(start, end):截取字符串,包含start索引,不包含end索引(比如"hello".substring(0,2)得到"he")
  • charAt(index):获取字符串指定索引位置的字符(索引从0开始,比如"hello".charAt(1)得到'e')

4. 随机数生成注意事项

  • ran.nextInt(len):生成0到len-1的随机数,刚好对应ArrayList的索引范围,避免"数组越界"错误
  • 随机数用于两个地方:随机选单词、随机隐藏字母,让出题更灵活

五、运行效果展示

六、常见问题与解决方法

(1)运行时报 FileNotFoundException(文件找不到)

原因:

词库文件路径写错、文件没放在指定位置,或文件夹名称拼写错误(比如把 wordslib 写成 wordlib)。

解决:
  • 确认项目根目录下有 wordslib 文件夹,且里面有 CET4.txt/CET6.txt;
  • 检查代码中路径字符串 wordslib/CET4.txt 的拼写,和文件夹、文件名完全一致;
  • 如果是 IDEA/Eclipse 等工具,可右键文件选择 Copy Path 直接复制绝对路径替换(比如 D:/project/wordslib/CET4.txt)。

(2)读取文件后中文翻译乱码

原因:

文件编码格式和程序读取编码不匹配(默认 FileReader 用系统编码,而 txt 文件可能是 UTF-8 编码)。

解决:

FileReader 换成 InputStreamReader 并指定编码,同时将txt文件的编码设置为UTF-8,代码修改如下:

java 复制代码
// 替换原来的 FileReader fr = new FileReader(file);
InputStreamReader isr = new InputStreamReader(new FileInputStream(file), "UTF-8");
BufferedReader br = new BufferedReader(isr);

(3)程序一直循环出题,无法退出

原因:

外层 **while(true)**是死循环,没有退出条件。

解决:

添加退出逻辑,比如输入exit时结束程序,代码修改如下:

java 复制代码
// 在内层循环读取输入的位置修改
String nch = sc.next();
// 新增:输入exit则退出整个程序
if (nch.equalsIgnoreCase("exit")) {
    System.out.println("退出背单词,下次加油!");
    sc.close();
    System.exit(0); // 终止程序
}
if (nch.length() != 1) {
    System.out.println("请输入单个字母!");
    continue;
}

(4)单词长度为1时,隐藏后只剩下划线,用户体验感较差

原因:

比如单词 a ,隐藏后变成 _ ,用户不知道该填什么。

解决:

代码中增加单词长度判断,跳过长度为1的单词,代码修改如下:

java 复制代码
while (true) {
    int index = ran.nextInt(len);
    String word = words.get(index);
    // 跳过长度小于2的单词
    if (word.length() < 2) {
        continue;
    }
    String chinese = chineseWords.get(index);
    // 后续代码不变...
}

(5)用户输入多个字符时,程序报错 StringIndexOutOfBoundsException

原因:

代码中用 nch.charAt(0) 获取输入字符,如果用户输入多个字符(比如 ab),不会报错,但如果输入空字符串会崩溃;更合理的做法是限制用户只能输入单个字符。

解决:

增加输入长度校验,代码修改如下:

java 复制代码
String nch = sc.next();
// 校验输入是否为单个字符
if (nch.length() != 1) {
    System.out.println("请输入单个字母!");
    continue;
}
char newCh = nch.charAt(0);

七、下节版本预告

以上是单词软件V1.0的基础功能展示,覆盖了Java必学的核心知识点:集合、文件IO、字符串处理、异常捕获。下一篇我们会升级到V2.0,即创建窗体,添加给出中文翻译输入单词等功能。新手可以跟着代码逐行敲,遇到不懂的地方对照"知识点详解",跑通后再尝试升级功能。如果现在运行代码遇到问题(比如文件找不到、中文乱码),或者想提前了解V2.0的核心知识点,随时留言告诉我!

相关推荐
定义小花3 小时前
c++ cmake qt
开发语言·c++·qt
软件开发技术深度爱好者3 小时前
Python + Ursina设计3D小游戏
开发语言·python
黑客思维者3 小时前
Python 3.14(2025最新版)的核心语法特性分析
服务器·开发语言·python·多线程
蚊子爱喝水3 小时前
PHP/ThinkPHP 最佳实践:DeepSeek/OpenAI API 实时流式输出 (Streaming) 完整指南
开发语言·php
7ioik3 小时前
什么是栈帧?
java
路边草随风3 小时前
java实现发布flink k8s application模式作业
java·大数据·flink·kubernetes
whltaoin3 小时前
【Java SE】Java IO 类常用方法大全:从字节流到 NIO 的核心 API 汇总
java·开发语言·api·nio
编程修仙3 小时前
第二篇 SpringBoot项目启动流程
java·spring boot·后端
张较瘦_3 小时前
Springboot3 | MyBatis-Plus 多表查询极简实践:宠物管理系统场景落地
java·mybatis·宠物