以面向对象的思维和软件架构完成一道编程题目(Java)

我是小康小白,一个平平无奇的Java小白。热爱有趣的文字,生活和远方。
个人博客:https://blog.csdn.net/weixin_45791445
有问题欢迎QQ联系:1059320343 (记得备注CSDN)

在这里插入图片描述
大家好呀,我康小白又来了。
在这里插入图片描述

闲话不多说,让我们开始正题。

一,题目:

1.1【问题描述】
编写一个帮助小学生练习数学的程序,帮助小学生练习100以内的四种数学运算:加、减、乘、除。
1.2【基本要求】
a) 程序应先询问用户的ID号(ID号包括两个大写字母和4位数字),例如:
请输入用户ID号:AB1234 程序应对输入的ID号验证,符合ID号要求的格式,然后程序提示三种选择: (1)开始测试 (2)检查分数 (3)退出

b) 测试:该程序将给出10道数学题,例如:
12 * 3 =36
48 + 32 =80

56 / 28 =2
注意:
i)学生将依次回答每一个问题(在等于号后面给出答案),然后给出下一道题。

ii)试题应包含四种数学运算:加、减、乘、除,它们是随机产生的。相邻的问题应该是不同的操作,每个操作必须至少出现一次。

iii)为每道题随机生成数字,但必须确保参与运算的数字和结果都小于100且大于零的整数。 iv)十道题做完后,记录学生完成这十道题所用的时间。

v)给每个学生一个分数。将该学生的ID、成绩和使用时间保存到一个名为record.txt的文件中。

vi)在屏幕上输出以下信息:

问题 | 正确答案 | 你的答案

c) 成绩检查:从文件“record.txt”中列出该学生的所有历史成绩。例如:
你以前的记录是:
AB1234 80 150秒
AB1234 50 182秒
AB1234 90 98秒

二,注意点

这道题目不难,但如何在题目中体现我们Java的面向对象那?
君且听我慢慢道来:

  1. 分析对象:
    首先题目的主体是什么:计算题,玩家
    那么就是两对象;

  2. 分析对象属性:

    1. 计算题(Operation):
      计算题有什么属性呀?
      两个参数,一个结果,一个运算符号;
      这是最基础的属性,可是这是就有个问题了,两个运算的参数尚可以随机生成,那运算的符号如何随机生成呀?
      小白的想法是使用数字来代替符号,在对象类中添加相应的方法进行转换。
      可这时小白又遇到了一个问题,小白原本的转换是这样写的:
      在这里插入图片描述
      设置一个String类型的属性expression,通过方法转化成对应的符号。
      可是在运算的时候小白发现了问题,我的这种方法可以进行输出但不能进行运算。()
      于是小白想了一种解决方法:
      在这里插入图片描述
      设置了String类型的expression变量用来输出表达式。
      设置了float类型的result来记录正确结果。

      这里使用的是switch case语句,在这种判断中会比多重if循环快

      后面为了进行对比,小白还设置了一个float类型的playerResult来存储每道题玩家的运算结果。
      所以运算式(Operation)的所有属性有:
      在这里插入图片描述
      为了讲存储式转换为String形式,还需要重写对象的toString()方法
      在这里插入图片描述

      1. 玩家(Player)
        基础属性:玩家ID,玩家的总成绩,玩家的所用时间,玩家最后的表达式以及自己的答案和正确答案
        在这里插入图片描述
        为了计算玩家得分,还需要写一个方法
        在这里插入图片描述
        为了实现对玩家成绩的输入,需要重写对象的toStirng()方法
        在这里插入图片描述
        为了输出用户所有的题目信息,还需要写一个方法
        在这里插入图片描述
        由于operationsToString是一个ArrayList集合,所以使用for循环输出比迭代器要快,迭代器更适合类似于LinkList的输出。
  3. 上面就是Java面向对象思想的集中体现:
    遇到项目(上面的这道题目就可以简单理解为一个简单的小项目)时,思考其中一共有多少对象,且首先分析这些对象基础的属性有什么,(就像上文的玩家对象基础属性只有玩家ID,玩家总成绩,玩家所用时间)。然后在做项目的过程中分析为了完成项目还需要多少属性(就像上文的玩家对象中有个ArrayList类型的属性operationsToString----指的是玩家最后的表达式以及自己的答案和正确答案,为什么要将玩家最后的表达式以及自己的答案和正确答案作为一个单独的属性添加到玩家对象中?)。
    当然还有很重要的一点是所有的属性都应当是私有(private)的,只能通过get和set方法实现对属性的访问。这也就是Java三大特性中的封装。封装提高了代码的安全性降低了代码的耦合度,方便了模块的多次调用。

那么如何在题目中体现基础的软件架构

我下面使用的就是一种软件架构—三层架构

  1. 三层架构
    这是百度的结果 在这里插入图片描述

    表现层(UI)(web层)
    业务逻辑层(BLL)(service层)
    数据访问层(DAL)(dao层)
    再加上实体类库(Model)
    在这里插入图片描述
    src目录下有三个包,dao , model , service , web
    dao 包中原本应当是存放对数据库的访问,即对数据库的增删改查。这里由于题目中要求使用的是创建txt文件来存储信息。所以里面类的方法实现了对txt的存储和存出。还有一些是项目中需要使l用的基础方法。(具体代码请查看文章末尾的所有代码)
    model中存放的是实体类,一般是与数据库中的数据表相对应。
    service包中的类起连接作用,将UI表示层与DAL数据访问层之间联系起来。他们就是处理涉及业务逻辑相关的问题,比如在调用访问数据库之前,先处理数据、判断数据。
    web层存放的是用户看到的主界面。由于本题目没有对界面的要求,所以这里小白没有写内容。

  2. 在完成一个项目时要完善对各种情况的思考,以及处理。
    例如题目要求中要求只读出该学生的历史成绩那么就应当考虑到文件中可能会存在其它学生的历史成绩。
    那么就需要在读取成绩时添加一个判断
    我的代码实现是这样的
    在这里插入图片描述

3. 实现了上面文章中的两点便实现了面向对象思维和软件架构的小实践。

三,补充

为什么要将玩家最后的表达式以及自己的答案和正确答案作为一个单独的属性添加到玩家对象中?

因为为了实现一个玩家对应所有他在这次测试中完成的题目的自己的答案和正确答案。之前

软件架构和设计思维有什么区别?
设计是架构的实现之一。

四,代码

dao包中
—WorkDomeDao类

package dao;

import model.Operation;
import model.Player;

import java.io.*;
import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

/**
 * @author kangzhijie
 * @date 2020/10/10 10:56
 */
public class WorkDemoDao {
    
    



    //随机生成数字去进行运算,但运算的类型由输入的symbol确定
    public Operation randomGenerate(int symbol, Player player) {
    
    
        Random random = new Random();
        int x = random.nextInt(100);
        int y = random.nextInt(100);
        while (x == 0) {
    
    
            x = random.nextInt(100);
        }
        while (y == 0) {
    
    
            y = random.nextInt(100);
        }

        Operation operation = new Operation(x, y, symbol);
        //调用方法来创建运算式
        operation.matchingSymbol();

        //获得表达式
        System.out.print(operation.getExpression() + "=");

        //要求用户去输入自己的答案
        try {
    
    
            Scanner scanner = new Scanner(System.in);
            operation.setPlayerResult(scanner.nextFloat());
        } catch (Exception e){
    
    
            System.out.println("提示:每次运算的结果只需要精确到小数点后一位即可,且无需四舍五入");
            System.out.println("请再次输入你的答案");
            Scanner scanner1 = new Scanner(System.in);
            operation.setPlayerResult(scanner1.nextFloat());
        }

        //计算总分
        player.countScore(operation);

        //将这次的运算添加到List集合中
        player.getOperationsToString().add(operation.toString());

        return operation;
    }

    //游戏的主体,player是玩家对象
    public void mainBody(Player player) {
    
    

        System.out.println("提示:每次运算的结果只需要精确到小数点后一位即可,且无需四舍五入");

        //在每次开始游戏之前重置当前用户对象的成绩和使用时间
        player.setScore(0);
        player.setTime(0);
        ArrayList<String> arrayList = new ArrayList<>();
        player.setOperationsToString(arrayList);


        Random random = new Random();
        WorkDemoDao workDemo = new WorkDemoDao();
        long startTime = System.currentTimeMillis();
        for (int i = 0; i <= 3; i++) {
    
    
            workDemo.randomGenerate(i, player);
        }

        //设置个节点保证每一次的新操作与上次不同
        int symbolLast = 3;


        for (int j = 0; j < 7; j++) {
    
    
            int symbol = random.nextInt(3);
            while (symbol == symbolLast) {
    
    
                symbol = random.nextInt(3);
            }
            symbolLast = symbol;
            workDemo.randomGenerate(symbol, player);
        }
        long endTime = System.currentTimeMillis();
        long time = (endTime - startTime) / 1000;
        player.setTime(time);

        workDemo.inputSource(player);
    }

    //判断输入ID是否符合要求
    public Boolean judgeId(String id) {
    
    
        int judge1 = 1;
        int judge2 = 1;

        String strEnglish = id.substring(0, 2);
//        System.out.println(strEnglish);
        String strNumber = id.substring(2, 6);
//        System.out.println(strNumber);

        //判断字符串是否都为大写
        char data1[] = strEnglish.toCharArray();
        for (char value : data1) {
    
    
            if (value > '0' && value < '9') {
    
    
                judge1 = 0;
            }
            if (Character.isLowerCase(value)) {
    
    
                judge1 = 0;
            }
        }


        //判断字符串是否都为数字
        char data2[] = strNumber.toCharArray();
        for (char c : data2) {
    
    
            if (c < '0' || c > '9') {
    
    
                judge2 = 0;
            }
        }

        return judge1 != 1 || judge2 != 1;


    }

    //判断ID的格式
    public String inputID() {
    
    
        Boolean judge;
        Scanner scanner = new Scanner(System.in);
        WorkDemoDao workDemo = new WorkDemoDao();

        System.out.println("提示:玩家ID应该由两位大写英语字母加四位数字组成");
        System.out.print("请输入玩家的ID:");
        String id = scanner.next();
        if (id.length() == 6) {
    
    
            judge = workDemo.judgeId(id);
        } else {
    
    
            judge = true;
        }

        if (judge) {
    
    
            while (judge) {
    
    
                System.out.println("ID不符合格式");
                System.out.println("提示:玩家ID应该由两位大写英语字母加四位数字组成");
                System.out.print("请重新输入您的ID:");
                id = scanner.next();
                if (id.length() == 6) {
    
    
                    judge = workDemo.judgeId(id);
                } else {
    
    
                    judge = true;
                }
            }
        }
        return id;
    }

    //向文件中写入玩家的信息
    public void inputSource(Player player) {
    
    
        File file = new File("D:\\record.txt");
        if (!file.exists()) {
    
    
            try {
    
    
                file.createNewFile();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

        try {
    
    
            //FileWriter构造方法中添加的true确保了Java文件写入是向文件末尾添加而不是覆盖原文件
            FileWriter fileWriter = new FileWriter("D:\\record.txt", true);
            BufferedWriter bufferedWriter = new BufferedWriter(fileWriter);
            bufferedWriter.write(player.toString() + "\n");
            bufferedWriter.close();
        } catch (IOException e) {
    
    
            e.printStackTrace();
        }

    }

    //查询文件获取信息
    public void outputScoreLast(Player player) {
    
    
        File file = new File("D:\\record.txt");

        //使用ArrayList来存储每行读取到的字符串
        ArrayList<String> arrayList = new ArrayList<>();

        if (!file.exists() && !file.isDirectory()) {
    
    
            System.out.println("您尚未进行游戏,请先进行游戏后查询分数!");
        } else {
    
    
            System.out.println("您之前的记录是:");
            try {
    
    
                RandomAccessFile randomAccessFile = new RandomAccessFile(file, "r");
                //按行读取字符串
                String str = null;
                while ((str = randomAccessFile.readLine()) != null) {
    
    
                    //判断是否为当前用户ID
                    String[] middle = str.split("  ");
                    if (middle[0].equals(player.getId())) {
    
    
                        arrayList.add(str + "秒");
                    }
                }
                randomAccessFile.close();
            } catch (IOException e) {
    
    
                e.printStackTrace();
            }
        }

        if (arrayList.size() != 0) {
    
    
            for (String s : arrayList) {
    
    
                System.out.println(s);
            }
        } else {
    
    
            System.out.println("您还未进行测试,请至少测试一次后,查询成绩");
        }

    }


    //选择代码的主体
    public void switchCase(Player player) throws IOException {
    
    
        Scanner scanner = new Scanner(System.in);

        WorkDemoDao workDemo = new WorkDemoDao();
        System.out.println("欢迎玩家" + player.getId());
        boolean middle = true;
        while (middle) {
    
    
            System.out.println("请选择您要进行的操作:");
            System.out.println("-----(1)开始测试-----");
            System.out.println("-----(2)检查分数-----");
            System.out.println("-----(3)退出-----");
            int i = scanner.nextInt();
            switch (i) {
    
    
                case 1:
                    workDemo.mainBody(player);
                    player.inputExpression();
                    System.out.println(player.getId() + "的成绩是" + player.getScore());
                    break;
                case 2:
                    workDemo.outputScoreLast(player);
                    break;
                case 3:
                    middle = false;
                    break;
                default:
                    System.out.println("无效操作,请重新输入");
                    break;
            }
        }
        System.out.println("已成功退出");

    }
}

model包

—Operation类
—Player类

package model;

/**
 * @author kangzhijie
 * @date 2020/9/27 10:19
 */
public class Operation {
    
    

    //运算变量一
    private int x;

    //运算变量二
    private int y;

    //运算符号
    private int symbol;

    //正确结果
    private float result;

    //算式的表达式
    private String expression;

    //玩家输入的答案
    private float playerResult;

    public Operation() {
    
    

    }

    public Operation(int x, int y, int symbol) {
    
    
        this.x = x;
        this.y = y;
        this.symbol = symbol;
    }

    public int getX() {
    
    
        return x;
    }

    public void setX(int x) {
    
    
        this.x = x;
    }

    public int getY() {
    
    
        return y;
    }

    public void setY(int y) {
    
    
        this.y = y;
    }

    public int getSymbol() {
    
    
        return symbol;
    }

    public void setSymbol(int symbol) {
    
    
        this.symbol = symbol;
    }

    public float getResult() {
    
    
        return result;
    }

    public void setResult(float result) {
    
    
        this.result = result;
    }

    public String getExpression() {
    
    
        return expression;
    }

    public void setExpression(String expression) {
    
    
        this.expression = expression;
    }

    public float getPlayerResult() {
    
    
        return playerResult;
    }

    public void setPlayerResult(float playerResult) {
    
    
        this.playerResult = playerResult;
    }

    public void matchingSymbol() {
    
    
        switch (symbol) {
    
    
            case 0:
                result = x + y;
                expression = x + "+" + y;
                break;
            case 1:
                result = x - y;
                expression = x + "-" + y;
                break;
            case 2:
                result = x * y;
                expression = x + "*" + y;
                break;
            case 3:
                result = x / y;
                expression = x + "/" + y;
                break;
            default:
                System.out.println("无此类型");
                break;
        }
    }



    @Override
    public String toString() {
    
    
        return expression + " | " + result + " | " + playerResult;
    }
}

package model;

import java.util.ArrayList;
import java.util.List;

/**
 * @author kangzhijie
 * @date 2020/9/27 11:30
 */
public class Player {
    
    

    //玩家id
    private String id;

    //玩家总成绩
    private int score;

    //玩家所用时间
    private long time;

    //玩家最后的表达式以及自己的答案和正确答案
    private ArrayList<String> operationsToString = new ArrayList<>();


    public Player() {
    
    
    }

    public Player(String id) {
    
    
        this.id = id;
    }

    public Player(String id, int score, long time, ArrayList<String> operationsToString) {
    
    
        this.id = id;
        this.score = score;
        this.time = time;
        this.operationsToString = operationsToString;
    }

    public String getId() {
    
    
        return id;
    }

    public void setId(String id) {
    
    
        this.id = id;
    }

    public int getScore() {
    
    
        return score;
    }

    public void setScore(int score) {
    
    
        this.score = score;
    }

    public long getTime() {
    
    
        return time;
    }

    public void setTime(long time) {
    
    
        this.time = time;
    }

    public List<String> getOperationsToString() {
    
    
        return operationsToString;
    }

    public void setOperationsToString(ArrayList<String> operationsToString) {
    
    
        this.operationsToString = operationsToString;
    }

    //计算得分
    public void countScore(Operation operation) {
    
    
        if (operation.getPlayerResult() == operation.getResult()) {
    
    
            this.score += 10;
        }
    }

    //输出用户所有的题目信息
    public void inputExpression() {
    
    
        System.out.println("问题 | 正确答案 | 你的答案");
        for (int i = 0; i < operationsToString.size(); i++) {
    
    
            System.out.println(operationsToString.get(i));
        }
    }

    @Override
    public String toString() {
    
    
        return id + "  " + score + "  " + time;
    }


}

service包
—WorkDemo类

package service;

import dao.WorkDemoDao;
import model.Player;

import java.io.IOException;

/**
 * @author kangzhijie
 * @date 2020/9/27 8:21
 */
public class WorkDemo {
    
    



    public static void main(String[] args) throws IOException {
    
    

        WorkDemoDao workDemo = new WorkDemoDao();

        System.out.println("开始测试");
        //获取正确的id作为id
        String id = workDemo.inputID();
        //创建玩家对象
        Player player = new Player(id);
        //开始选择操作
        workDemo.switchCase(player);

    }


}

web包

以上就是代码源码,如有问题和疑惑,以及想要代码的包的欢迎联系小白。


小白写博客不容易,希望各位兄弟们,点赞评论收藏加关注。小白在此谢谢各位老爷们。
在这里插入图片描述
对于白嫖的兄弟们
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45791445/article/details/108890171
今日推荐