大数据——项目实战之QuickHit游戏

项目需求

QuickHit游戏考验学员键盘输入内容的速度和正确率。
根据输入速率和正确率将玩家分为不同级别,级别越高,一次显示的字符数越多,玩家正确输入一次的得分也越高。如果玩家在规定时间内完成规定次数的输入,正确率达到规定要求,则玩家升级(为了简单起见,规定用户只要输入错误一次,则游戏结束)。玩家最高级别为6级,初始级别一律为一级。

项目环境准备

完成QuickHit,对于开发环境要求如下:
开发工具:MyEclipse 10或IntelliJ IDEA(这里我用的就是idea)
JDK 1.8

项目覆盖的技能点

面向对象程序设计的思想。
使用类图理解了的关系。
类的封装。
构造方法的使用。
this和static关键字的使用。

难点分析

需要用到的类

本项目功能简单,代码量较少,采用面向过程的思想可能更容易实现,此处关键是锻炼面向对象的设计能力,分析各段功能代码放到什么位置更合理一些,为大型项目的设计打好基础。
面向对象设计的过程就是抽象的讨程。通过在需求中找出名词的方式确定类和属性,通过找出动词的方式确定方法:然后对找到的词语进行筛选,剔除无关、不重要的词语;
最后对词语之间的关系进行梳理,从而确定类、属性、属性值和方法。
需求中和业务相关的名词主要是游戏、输入速率、玩家、级别、一次显示的字符数、正确输入一次的得分、规定时间、规定次数、超时、玩家的积分和玩家用时等。动词主要是输出、输入、确认和显示。
第一步:发现类
玩游戏肯定离不开玩家和游戏,可以首选抽象出玩家、游戏两个类。一次显示的字符数、正确输入一次的得分、规定时间和规定次数都与玩家的当前级别有关,可以再抽象出一个级别类。而积分和用时可以考虑设置为玩家属性。
经过分析,我们暂时从需求中抽象出如下类:游戏(Game)、玩家(Player)和级别(Level)。类图如下所示:
在这里插入图片描述
第二步:发现类的属性。
经过分析可知,玩家的属性有当前级别、玩家的积分和玩家用时等,而玩家用时其实是当前时间与开始时间的差;级别的属性有级别号、一次显示的字符数、正确输入一次的得分、规定时间和规定次数。
进行整理并合并:
玩家(Player)类的属性:玩家当前级别号(levelNo)、玩家当前级别积分(currScore)、当前级别开始时间(startTime)和当前级别已用时间(elapsedTime)。
级别(Level)类的属性:各级别编号(levelNo)、各级别一次输入字符串的长度(strLength)、各级别输出字符串的次数(strTime)、各级别闯关的时间限制(timeLimit)和各级别正确输入一次的得分(perScore)。
类图如下所示:
在这里插入图片描述
第三步:发现类的方法
经过分析,游戏类的主要方法有三个:输出字符串、确认玩家输入是否正确和输出相应结果信息。其中,第二个方法很简单,可以和第三个方法合并。而玩家类的方法只有一个,即玩游戏(根据游戏的输出来输入相同的字符串)。级别类主要是存放信息,没有具体操作。
进行整理并命名,得到如下结果:
玩家类的方法:玩游戏play()
游戏类的方法有两个:String printStr(),输出字符串,返回字符串用于和玩家的输入进行比较;void printResult(String out,String in),比较游戏输出out和玩家输入in,根据比较结果输出相应信息。
相应类图如下所示:
在这里插入图片描述
第四步:优化设计
在游戏类的printResult(String out,String in)方法中,输出相应结果时肯定会涉及玩家类的信息,如当前级别编号、当前级别积分、当前级别已用时间等,可以通过把Player对象作为游戏类的属性,轻松解决该问题。
级别类不包含各个级别的具体参数信息,可以增加LevelParam类,在该类中创建一个长度为6的Level数组,存放各个级别的具体参数信息,并使用public final static修饰该数组,可以直接通过类名来访问,却无法修改其值。
优化后的类图如下所示:
在这里插入图片描述

主要功能分析

(1)游戏输入字符串,主要步骤是生成固定但内容随机的字符串,同时向控制台输出生成的字符串并返回此字符串(必须返回,用于和玩家输入比较)。
(2)确认输入并输出结果:根据玩家输入是否如正确输出不同结果。当输入正确并且未超时,要输出玩家的当前级别、当前积分和已用时间。如何计算玩家的当前级别、当前积分和已用时间是关键。
(3)玩家玩游戏:游戏的6个级别可以通过循环实现,而每个级别中的多次字符串输出通过内部子循环实现,该控制功能放在Player类的play()方法中,每次玩家晋级后积分清零、计时清零。

界面分析

如果玩家输入正确且未超时,则输出玩家输入的正确信息(包括级别、积分和用时),并输出玩家当前积分、当前级别和已用时间。如果玩家输入正确但超时,则输出玩家超时信息,并退出系统。参考如下所示:
在这里插入图片描述

如果玩家输入错误,,则输出“输入错误,退出!”的提示信息,并退出系统。参考如下所示:
在这里插入图片描述

项目实现

QuickHit项目的执行步骤描述如下:
(1)游戏根据玩家的级别在控制台输出指定数量的字符。
(2)玩家根据控制台的输出来输入相同字符,按Enter键确认。
(3)游戏确认玩家输入是否正确。
(4)如果输入错误,则输出玩家输入错误提示信息,游戏非正常结束,
(5)如果输入正确但超时,则输出玩家速度太慢提示信息,游戏非正常结束。
(6)如果输入正确且没有超时,则输出玩家的积分、级别和用时时间。然后重复以上步骤,继续输出、输入和确认。
(7)玩家在规定时间内连续正确输入规定次数后,将显示玩家升级提示,游戏将重新计时记分,将一次输出更多的字符。6级玩家闯关成功,输出恭喜信息,游戏正常结束。

游戏输出字符

实现步骤可以设计为以下几步:
(1)生成字符串。
(2)输出字符串。
(3)返回字符串(必须返回,用于和玩家的输入进行比较)。

确认输入的字符并输出结果

实现步骤可以设计为以下几步:
(1)确认玩家的输入是否正确。
(2)如果输入不正确,则直接输出错误信息并退出程序。
(3)如果输入正确,则会有以下两种情况。
a:如果超时,则直接输出玩家超时信息并退出程序。
b:如果没有超时,则执行以下操作:
计算玩家当前积分。
计算玩家已用时间。
输出玩家当前级别、当前积分和已用时间。
判断用户是否已经闯过最后一关并处理。

玩家玩游戏

实现步骤可以设计为以下几步:
(1)创建Game对象并传入player属性。
(2)外层循环(循环次数是6,每循环一次,玩家提升一级)。
a:晋级。
b:积分清零,计时清零。
c:内层循环(循环次数是该级别的strTime,每循环一次完成一次人机交互)。
游戏输出字符串。
玩家输入字符串。
判断玩家输入的字符串并输出相应结果。

初始化各个级别的具体参数

各个级别的具体参数信息,如各级别编号,各级别一次输出字符串的长度、各级别输出字符串的次数、各级别闯关的时间限制和各级别正确输入一次的得分,应该在游戏开始前进行初始化。

代码展示

public class Player {
    private String name;
    private int curLevel=1;//当前级别编号
    private int curScore;
    private long startTime=System.currentTimeMillis();
    private int usedTime;
    public Player(String name) {
        this.name = name;
    }
    public void play(){
        Game g=new Game();
        g.player=this;
        g.run();
        System.out.println("恭喜"+name+",您已通关!");
}
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getCurLevel() {
        return curLevel;
    }
    public void setCurLevel(int curLevel) {
        this.curLevel = curLevel;
    }
    public int getCurScore() {
        return curScore;
    }
    public void setCurScore(int curScore) {
        this.curScore = curScore;
    }
    public long getStartTime() {
        return startTime;
    }
    public void setStartTime(long startTime) {
        this.startTime = startTime;
    }
    public int getUsedTime() {
        return usedTime;
    }
    public void setUsedTime(int usedTime) {
        this.usedTime = usedTime;
    }
}
public class Level {
    private int lvlNum;//级别号
    private int charCnt;//当前级别每次输出的字符数
    private int perScore;//每次输入后的正确得分
    private long limitTime;//当前级别规定时间
    private int inputNum;//输入次数
    public Level(int lvlNum, int charCnt, int perScore, long limitTime, int inputNum) {
        this.lvlNum = lvlNum;
        this.charCnt = charCnt;
        this.perScore = perScore;
        this.limitTime = limitTime;
        this.inputNum = inputNum;
    }
    public int getCharCnt() {
        return charCnt;
    }
    public int getPerScore() {
        return perScore;
    }
    public long getLimitTime() {
        return limitTime;
    }
    public int getInputNum() {
        return inputNum;
    }
}
public interface LevelParams {
    Level[] LEVELS={
            new Level(1,2,3,20,5),
            new Level(2,3,5,40,8),
            new Level(3,4,7,60,10),
            new Level(4,5,8,55,8),
            new Level(5,6,9,50,6),
            new Level(6,7,10,40,4)
    };
}
import java.util.Scanner;
public class Game implements LevelParams {
    Player player = new Player("sam");
    //生成一串字符
    public String getString() {
        int curLvl = player.getCurLevel();
        Level lvl = LEVELS[curLvl - 1];
        String str = "";
        for (int i = 0; i < lvl.getCharCnt(); i++) {
            int ranNum = (int) (Math.random() * 10);
            str += ranNum;
        }
        return str;
    }
    //流程控制
    public void run() {
        Scanner sc = new Scanner(System.in);
        System.out.println("欢迎" + player.getName() + "来到QuickHit峡谷");
        while (player.getCurLevel()<=6){
            int lvlNum = player.getCurLevel();
        Level lvl = LEVELS[lvlNum - 1];
        for (int i = 0; i <= lvl.getInputNum(); i++) {
            System.out.println("当前级别为:" + player.getCurLevel() + "积分为:" +
                    player.getCurScore() + ",已用时间:" + player.getUsedTime()/1000+"秒");
            String out = getString();
            System.out.println(out);
            System.out.println("请输入对应的字符串:");
            String input = sc.next();
            long now = System.currentTimeMillis();
            player.setUsedTime((int) (now - player.getStartTime()));
            if (!input.equals(out)) {//输入与输出不一致,则错误,退出程序
                System.out.println("输入错误");
                System.exit(1);
            } else if (player.getUsedTime() / 1000 > lvl.getLimitTime()) {
                System.out.println("输入超时,游戏结束");
                System.exit(1);
            }
            //输入正确且未超时
            player.setCurScore(player.getCurScore() + lvl.getPerScore());//加分
        }
        player.setCurLevel(player.getCurLevel() + 1);
        player.setUsedTime(0);
      player.setStartTime(System.currentTimeMillis());
    }
}}
public class Test {
    public static void main(String[] args) {
        Player p=new Player("sam");
        p.play();
    }
}

输出结果:
在这里插入图片描述

  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值