纯java打字游戏/QuickHit/java课程阶段练习

压缩包可以去我的github下载
https://github.com/CienYu/QucikHit/tree/master

项目结构图

使用说明

#测试环境: jdk1.8

#测试软件: idea

#编码格式: utf-8

#version: 2.0

#version note:
    2.0
        no和role的功能存在重复,将no和role分开,no为玩家等级,role为玩家段位,游戏难度由role决定
        no改为玩家等级的提升通过题数,role的提升通过积分,两者相辅相成
        role
            0: Rookie
            1: credit>getCreditLimit() && no>getNoLimit()
        no
            0: 0
            1: queSum>getQueLimit(this.role.getValue)
    1.0
        no与枚举值绑定,游戏难度随着角色变化而变化

#游戏配置和参数请在config中的Setting中修改

#主要涉及知识: 字符串的处理,文件I/O操作,常用数据结构,java反射知识,java计时器,异常处理,枚举类

#本项目仅作学期java课程总结,且存在部分为了使用而使用的代码结构,代码不一定没有bug,欢迎反馈

#by:Cien

config文件夹下的Setting类

package day411.project.config;

/**
 * @Author Cien
 * @Date 2022/4/11 15:36
 * @Version 2.0
 * @Note 游戏配置类
 */
public class Setting {

    //存档目录
    private static final String catalogue = "F:\\存档.txt";

    //中文开关
    private static final boolean havachinese = false;

    //趣味开关
    private static final boolean Comment = false;

    //段位对应时间规定
    private static final Long[] TimeLimit = new Long[]{3l,5l,7l,10l,15l,20l,10l};

    //段位对应字符串长度
    private static final Integer[] StrLimit = new Integer[]{3,5,10,10,15,20,50};

    //段位对应积分要求
    private static final Integer[] CreditLimit = new Integer[]{10,40,90,130,210,310,460};

    //段位对应加分
    private static final Integer[] InCreditLimit = new Integer[]{1,3,5,7,9,10,15};

    //段位对应等级要求
    private static final Integer[] NoLimit = new Integer[]{0,1,2,3,4,5,6};

    //等级对应题数要求
    private static final Integer[] QueLimit = new Integer[]{3,5,7,9,10,13,15};


    public static Integer getQueLimit(Integer roleNo){
        return QueLimit[roleNo];
    }

    public static Integer getNoLimit(Integer roleNo){
        return NoLimit[roleNo];
    }
    public static Long getTime(Integer roleNo){
        return TimeLimit[roleNo];
    }

    public static Integer getStrLength(Integer roleNo){
        return StrLimit[roleNo];
    }

    public static Integer getCreditLimit(Integer roleNo){
        return CreditLimit[roleNo];
    }

    public static Integer getInCredit(Integer roleNo){
        return InCreditLimit[roleNo];
    }
    public static Boolean gethavachinese(){
        return havachinese;
    }
    public static Boolean getComment(){
        return Comment;
    }
    public static String getCatalogue(){
        return catalogue;
    }

    public static String successPoem(){
        String str = "";
        int a = (int) (Math.random() * 5);
        switch (a){
            case 1:
                str="白衣走马执霜雪,不枉人间少年郎.";break;
            case 2:
                str="明年此日青云去,却笑人间举子忙";break;
            case 3:
                str="夫何瑰逸之令姿,独旷世以秀群";break;
            case 4:
                str="绿蚁新醅酒,红泥小火炉。晚来天欲雪,能饮一杯无?";break;
            default:
                //若教眼底无离恨,不信人间有白头
                str="直道相思了无益,未妨惆怅是清狂";break;
        }
       return str;
    }
    public static String failurePoem(){
        String str = "";
        int a = (int) (Math.random() * 5);
        switch (a){
            case 1:
                str="人生若只如初见,何事秋风悲画扇";break;
            case 2:
                str="欲买桂花同载酒,终不似,少年游。";break;
            case 3:
                str="惆怅东栏一株雪,人生看得几清明。";break;
            case 4:
                str="休言万事转头空,未转头时皆梦。";break;
            default:
                str="试问岭南应不好,却道:此心安处是吾乡。";break;
        }
        return str;
    }

    //后续增加泛型?
    public <T> T fun(T t){
        return t ;
    }
}


config文件下的PlayerEnums类

package day411.project.config;

import day411.project.Player;

import static day411.project.config.Setting.getCreditLimit;

/**
 * @Author Cien
 * @Date 2022/4/11 16:09
 * @Version 1.0
 * @Note 枚举类
 */
public enum PlayerEnums {


    Rookie(0,"菜鸟"),
    Introduction(1,"入门"),
    Primary(2,"初"),
    Intermediate(3,"中"),
    Advanced(4,"高"),
    GodLike(5,"接近神明"),
    Legendary(6,"超神");

    private final int value ;
    private final String description;
    private PlayerEnums(int value, String description) {
        this.value = value;
        this.description = description;
    }
    public int getValue() {
        return value;
    }
    public String getDescription() {
        return description;
    }


    public static PlayerEnums getUserEnums(Integer value){
        PlayerEnums[] values = PlayerEnums.values();
        PlayerEnums p=Legendary;
        for (PlayerEnums pe:values) {
            if(value==pe.value){
                 p=pe;
            }
        }
        return p;
    }

}

utils文件夹下的FileUtils类

package day411.project.utils;

import day411.project.Player;
import day411.project.config.PlayerEnums;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;

/**
 * @Author Cien
 * @Date 2022/4/11 22:24
 * @Version 1.0
 * @Note 文件工具类
 */
public class FileUtils {

    //实体类转map
    public static Map<String, Object> entityToMap(Object object) {
        Map<String, Object> map = new HashMap<>();
        //获取声明字段并遍历放入map中
        for (Field field : object.getClass().getDeclaredFields()) {
            try {
                //field.isAccessible()在jdk1.9后废弃,教室环境使用field.canAccess
                //boolean flag = field.isAccessible();
                //boolean flag = field.canAccess(o);
                //设置访问权限
                field.setAccessible(true);
                Object o = field.get(object);
                map.put(field.getName(), o);
                field.setAccessible(true);
            } catch (Exception e) {
                System.err.println("反射获取值出现问题");
            }
        }
        return map;
    }

    //String转map
    public static Map<String, Object> stringToMap(String str){
        Map<String, Object> map = new HashMap<>();
        StringBuffer sbf = new StringBuffer();
        char[] chars = str.toCharArray();
        for (char c: chars) {
            if(c!='{' && c!='}' && c!=','){
                sbf.append(c);
            }
        }
        String[] strings = sbf.toString().split("\\ ");
        for (String s: strings) {
            map.put(s.substring(0, s.indexOf("=")), s.substring(s.indexOf("=")+1, s.length()) );
        }
        return map;
    }

    //map转实体类
    public static Player mapToEntry(Map<String,Object> map){
        Player p = new Player();
        try {
            p.setNo(Integer.valueOf(map.get("no").toString()));
            p.setCredit(Integer.valueOf(map.get("credit").toString()));
            p.setQueSum(Integer.valueOf(map.get("queSum").toString()));
            p.setRightQueSum(Integer.valueOf(map.get("rightQueSum").toString()));
            p.setRole(PlayerEnums.valueOf(map.get("role").toString()));
            System.out.println("读取数据成功,已为你继承上次数据");
        } catch (NumberFormatException e) {
            Scanner in= new Scanner(System.in);
            System.err.println("存档数据存在问题,是否初始化数据(y/n):");
            String i = in.nextLine();
            if("y".equals(i)){
                p.init();
                System.out.println("初始化成功");
            }else {
                stop();
            }
        }
        return p;
    }

    //中断
    public static void stop(){
            System.out.println("请更换存档或检查数据,see you again!");
            System.exit(0);
    }

}

utils文件夹下的StrUtuils类

package day411.project.utils;

import java.io.UnsupportedEncodingException;
import java.util.Random;

/**
 * @Author Cien
 * @Date 2022/4/12 17:54
 * @Version 1.0
 * @Note 字符工具类
 */
public class StrUtuils {

    //生成单个小写字母
    public static char getLowercaseChar(){

        Random random = new Random();
        int num = random.nextInt(26)+97;
        char a = (char)num;
        //System.out.println(a);
        return a;
    }
    //生成单个大写字母
    public static char getUppercaseChar(){
        Random random = new Random();
        int num = random.nextInt(26)+65;
        char a = (char)num;
        //System.out.println(a);
        return a;
    }
    //生成数字字符
    public static char getFiguresChar(){
        Random random = new Random();
        int num = random.nextInt(32)+33;
        char a = (char)num;
        //System.out.println(a);
        return a;
    }

    //生成汉字
    public static String getchineseStr() {
            String str = null;
            int hightPos, lowPos; // 定义高低位
            Random random = new Random();
            //这里采用GBK格式生成汉字,而gbk中汉字是双字节
            //获取高位值
            hightPos = (176 + Math.abs(random.nextInt(39)));
            //获取低位值
            lowPos = (161 + Math.abs(random.nextInt(93)));
            byte[] b = new byte[2];
            b[0] = (new Integer(hightPos).byteValue());
            b[1] = (new Integer(lowPos).byteValue());
            try {
                // 转成中文
                str = new String(b, "GBK");
            } catch (UnsupportedEncodingException ex) {
                ex.printStackTrace();
            }
            return str;
    }
}

FileWR类

package day411.project;

import java.io.*;
import static day411.project.config.Setting.getCatalogue;
import static day411.project.utils.FileUtils.*;

/**
 * @Author Cien
 * @Date 2022/4/11 17:48
 * @Version 1.0
 * @Note 存档读取类
 */
public class FileWR {


    private final String catalogue = getCatalogue();

    //判断存档是否存在
    public boolean fileExist() {
        File file = new File(catalogue);
        boolean flag;
        if(!file.exists()){
            flag = false;
        }else{
            flag = true;
        }
        return flag;
    }
    //存档
    public void fileWirte(Player p) {
        try {
            Writer fw = new FileWriter(catalogue);
            String str = entityToMap(p).toString().trim();
            fw.write(str);
            System.out.println("存档成功");
            fw.flush();
            fw.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    //读取存档
    public Player fileRead() {
        StringBuffer sbf=new StringBuffer();
        try {
            File file = new File(catalogue);
            Reader fr = new FileReader(file);
            char[] ch = new char[(int)file.length()];
            int length=fr.read(ch);

            while ((length!= -1)) {
                sbf.append(ch);
                length=fr.read();
            }
            fr.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Player p1 = mapToEntry(stringToMap(sbf.toString()));
        System.out.println("当前用户等级为:"+p1.getNo()+",积分为:"+p1.getCredit());
        return p1;
    }

}

Play类

package day411.project;

import java.util.Scanner;
import static day411.project.config.Setting.getTime;

/**
 * @Author Cien
 * @Date 2022/4/11 17:12
 * @Version 1.0
 * @Note 游戏主类
 */
public class Play {

    public void gameMain(Player p){
        TimeClock tc = new TimeClock();
        Scanner in = new Scanner(System.in);
        RandomString randomString = new RandomString();
        String str = randomString.getStr(p.getRole().getValue());

        tc.startTime();
        System.out.println("计时开始,你有"+getTime(p.getRole().getValue())+"秒时间进行填写");
        System.out.println(str);
        String userStr = in.nextLine();
        Long time = tc.endTime();

        System.out.println("用时"+time+"秒");
        p.isSuccess(str,userStr,time);
        p.rank();
    }
    public Player getPlayer(Player p){
        FileWR fwr = new FileWR();

        //读取数据
        if(!fwr.fileExist()){
            System.out.println("指定位置没有存档文件,或者无存档数据,已为你初始化数据");
            p.init();
        }else {
            System.out.println("读取数据中...");
            p = fwr.fileRead();
        }
        return p;
    }
    public static void main(String[] args) {
        Play play = new Play();
        Player p = new Player();
        FileWR fwr = new FileWR();
        Scanner in = new Scanner(System.in);
        p = play.getPlayer(p);
        p.rank();
        while (true){
            System.out.println("输入1开始游戏,2查看当前数据,3保存数据,4退出游戏");
            String flag = in.next();
            switch (flag){
                case "1":play.gameMain(p);;break;
                case "2":p.print();break;
                case "3":fwr.fileWirte(p);break;
            }
            if("4".equals(flag)) {
                System.out.println("see you again");
                break;
            }
        }
    }

}

Player类

package day411.project;


import day411.project.config.PlayerEnums;

import java.util.Scanner;

import static day411.project.config.PlayerEnums.*;
import static day411.project.config.Setting.*;
import static day411.project.utils.FileUtils.stop;

/**
 * @Author Cien
 * @Date 2022/4/11 15:26
 * @Version 2.0
 * @Note 玩家类
 */
public class Player {

    /**
     * 玩家等级
     */
    private Integer no;

    /**
     * 玩家段位,且与游戏难度挂钩
     */
    private PlayerEnums role;

    /**
     * 积分
     */
    private Integer credit;

    /**
     * 已做题数
     */
    private Integer queSum;

    /**
     * 正确题数
     */
    private Integer rightQueSum;


    /**
     * 正确率
     */
    //private Long accuracy;



    public Player() {
    }

    public void init(){
        this.no= 0 ;
        this.credit = 0;
        this.queSum = 0;
        this.rightQueSum = 0;
        this.role = PlayerEnums.Rookie;
    }

    public Integer getNo() {
        return no;
    }

    public void setNo(Integer no) {
        this.no = no;
    }

    public Integer getCredit() {
        return credit;
    }

    public void setCredit(Integer credit) {
        this.credit = credit;
    }

    public Integer getQueSum() {
        return queSum;
    }

    public void setQueSum(Integer queSum) {
        this.queSum = queSum;
    }

    public Integer getRightQueSum() {
        return rightQueSum;
    }

    public void setRightQueSum(Integer rightQueSum) {
        this.rightQueSum = rightQueSum;
    }

    public PlayerEnums getRole() {
        return role;
    }

    public void setRole(PlayerEnums role) {
        this.role = role;
    }

    private void addCredit(){
        Integer increase= getInCredit(this.role.getValue());
        this.credit+=increase;
        System.out.println("输入正确,积分增加"+increase+"分,当前正确率为"+getAccuracy()+"%");
    }


    //玩家等级和段位提升
    public void rank(){

        if(this.queSum>=getQueLimit(this.role.getValue()) && this.no!=6){
            this.no+=1;
            System.out.println("题数满足要求,等级+1,当前等级为:"+this.no);
        }

        if(this.role!=Legendary&&this.credit>getCreditLimit(this.role.getValue()) && this.no>getNoLimit(this.role.getValue())){
            this.role = getUserEnums(this.role.getValue()+1);
            System.out.println("积分和等级满足晋级条件,你已是"+this.role.getDescription()+"级强者");

        }



    }

    private boolean isQuick(Long ltime){
        boolean flag=false;
        if(ltime<=getTime(this.no)){
            flag=true;
        }
        return flag;
    }

    private String getAccuracy(){
        String accuracy = null;
        try {
            if(this.queSum==0){
                accuracy="0";
            }else {
                accuracy=String.format("%.2f", (rightQueSum*1.0/queSum)*100);
            }
        } catch (Exception e) {
            System.err.println("读取到的题数存在空指针异常,请检查数据和代码");
            Scanner in= new Scanner(System.in);
            System.err.println("题数存在问题,是否初始化题数数据(y/n):");
            String i = in.nextLine();
            if("y".equals(i)){
                this.queSum=0;
                this.rightQueSum=0;
                System.out.println("初始化成功");
            }else {
                stop();
            }
        }
        return accuracy;
    }

    private void success(){
        if(getComment()){
            System.out.println(successPoem());
        }
        setQueSum(getQueSum()+1);
        setRightQueSum(getRightQueSum()+1);
        addCredit();
    }

    private void fail(){
        if(getComment()){
            System.out.println(failurePoem());
        }
        setQueSum(getQueSum()+1);
        System.out.println("输入错误,当前正确率为"+getAccuracy()+"%");

    }

    public void isSuccess(String str, String userStr, Long time){
        if(str.equals(userStr)||str.trim().equals(userStr.trim())){
            if(!isQuick(time)){
                System.out.println("超过规定时间,不予加分");
            }else {
                success();
            }
        }else{
            fail();
        }
    }

    public void print(){
        System.out.println("玩家等级为:"+this.no+",游戏难度为:"+this.role.getDescription()+"级,积分为:"+this.credit+"分,已尝试:"+this.getQueSum()+"关,通过:"+this.getRightQueSum()+"关");
    }

}

RandomString类

package day411.project;

import static day411.project.config.Setting.getStrLength;
import static day411.project.config.Setting.gethavachinese;
import static day411.project.utils.StrUtuils.*;

/**
 * @Author Cien
 * @Date 2022/4/11 11:34
 * @Version 1.0
 * @Note 字符生成类
 */
public class RandomString {

    /*
     * 纯恶搞
     */
    private static String Legendary(){
        StringBuffer sbf  = new StringBuffer();
        for (int i = 0; i < 30; i++) {
            if(gethavachinese()){
                sbf.append(getchineseStr());
            }else {
                sbf.append(getLowercaseChar());
                sbf.append(getUppercaseChar());
                sbf.append(getFiguresChar());
            }
        }
        return sbf.toString();
    }

    private static StringBuffer insertSpace(StringBuffer sbf, Integer roleNo){
        if(gethavachinese() &&  ((int) (Math.random() * 2)) == 1){
            int len = sbf.toString().replaceAll(" ", "").length();
            if (len%5==0 && roleNo != 6) {
                sbf.append((char)32);
            }
            sbf.append(getchineseStr());
        }
        return sbf;
    }

    /*
     * 获取对应难度的字符串
     */
    public String getStr(Integer roleNo){
        StringBuffer sbf  = new StringBuffer();
        int len = 0;
        for (int i = 0; i < getStrLength(roleNo); i++) {
            switch (roleNo){
                case 0:
                case 1:
                case 2:
                    sbf.append(getLowercaseChar());
                    sbf=insertSpace(sbf,roleNo);
                    break;
                case 3:
                case 4:
                    if ((int) (Math.random() * 2) == 1) {
                        sbf.append(getLowercaseChar());
                    } else {
                        sbf.append(getUppercaseChar());
                    }
                    sbf=insertSpace(sbf,roleNo);
                    break;
                case 5:
                case 6:
                    if ((int) (Math.random() * 3) == 1) {
                        sbf.append(getLowercaseChar());
                    } else if((int) (Math.random() * 3) == 2){
                        sbf.append(getUppercaseChar());
                    }else {
                        sbf.append(getFiguresChar());
                    }
                    sbf=insertSpace(sbf,roleNo);
                    break;
                default:
                    sbf.append(Legendary());break;
            }
            len = sbf.toString().replaceAll(" ", "").length();
            if (len%5==0 && roleNo != 6) {
                sbf.append((char)32);
            }
        }
        return sbf.toString();
    }


}

TimeClock类

package day411.project;


/**
 * @Author Cien
 * @Date 2022/4/11 11:58
 * @Version 1.0
 * @Note 计时类
 */
public class TimeClock {
    private long startTime = 0;
    private long endTime = 0;

    //开始计时
    public void startTime(){
        //获取当前系统时间
        startTime = System.currentTimeMillis();
    }
    //结束计时并返回耗时
    public Long endTime(){
        //获取当前的系统时间,与初始时间相减就是程序运行的毫秒数,除以1000就是秒数
        endTime = System.currentTimeMillis();
        long usedTime = (endTime-startTime)/1000;
        return usedTime;
    }

}

posted @ 2022-04-13 14:39  goEver  阅读(214)  评论(0)    收藏  举报