要求
做一个人机交互的打字游戏。
提取类:
Game类
genStr:可以随机输出字符串。
printResult: Player类
levelNo:玩家的级别号
currentScore:得分
startTime:开始时间
elapedTime:已用时间。
使用知识点
1.面向对象编程(OOP)基本原则
封装:所有的数据(如玩家得分、字符串长度、关卡参数等)和行为(如生成字符串、计算得分等)都被封装在相应的类中。
继承:使用了类的继承机制。例如,NumGenImpl, AbcGenImpl, MixGenImpl 这几个类都继承了 IGenStrategy 接口,重写了 genString 方法,展现了多态的特性。
多态:通过接口 IGenStrategy 和其具体实现类(如 NumGenImpl),Game 类可以通过传入不同的策略类(如数字生成、字母生成或混合生成)来改变字符串生成的方式,展示了多态。
抽象:通过接口 IGenStrategy,在 Game 类中我们不关心具体的字符串生成逻辑,只需要知道有一个 genString 方法,这就隐藏了具体实现的细节。
2. 接口和实现
接口(Interface):IGenStrategy 是一个接口,定义了生成字符串的方法 genString,而具体的生成逻辑由 NumGenImpl, AbcGenImpl, MixGenImpl 等类来实现。接口是实现多态的基础。
实现类:NumGenImpl, AbcGenImpl, MixGenImpl 是具体的实现类,它们实现了 IGenStrategy 接口,并根据不同的逻辑生成字符串。
3. 构造函数(Constructor)
每个类(如 Player, Level, Game)都通过构造函数初始化实例变量(如玩家等级、字符串生成策略等)。构造函数用于初始化对象时为对象分配初始值。
4. 随机数生成(Random)
使用 Random 类来生成随机数字或字符,这为字符串生成策略提供了基础。Random.nextInt() 方法被用来生成随机的数字和字符。
5. 字符串处理
StringBuilder:在 NumGenImpl, AbcGenImpl, MixGenImpl 类中,使用了 StringBuilder 来动态生成字符串,这是因为 StringBuilder 更适合处理字符串的拼接操作,相比于 String 类,它效率更高。
charAt():charAt() 方法用于获取字符串中指定位置的字符,这在字母生成策略中用于从字母表中随机挑选字符。
6. 控制台输入输出
使用 Scanner 类从控制台获取用户输入(例如,玩家输入的字符串),并通过 System.out.println() 向玩家显示提示信息或结果。
输出格式:通过 System.out.printf() 输出用时,使用了 %.2f 格式化输出时间,确保精确到小数点后两位。
7. 时间处理
使用 System.currentTimeMillis() 获取当前时间的毫秒数,来计算游戏的开始时间和已用时间。
8. 数组和集合
数组:在 LevelParams 类中,使用了一个数组 levels[] 来存储多个关卡的设置。这样可以方便地扩展和管理多个关卡。
增强的 for 循环:在 Game 类中的 start() 方法中,使用了增强的 for 循环遍历所有关卡,并为每个关卡生成相应的字符串。
9. 条件判断与循环
使用 if 条件语句判断玩家输入的字符串是否正确,若正确则增加分数。
for 循环:用 for 循环遍历多个关卡,或者在每个关卡内遍历字符串的生成次数。
10. 方法参数和返回值
方法参数:方法如 genString(int length) 采用了方法参数来动态传入生成字符串所需的长度,显示了方法如何接受输入并根据不同的输入生成不同的输出。
方法返回值:方法如 genString() 返回了一个生成的字符串,用于游戏逻辑中的比较和计分。
实际代码
import java.util.Random;
import java.util.Scanner;
// 1. IGenStrategy接口
interface IGenStrategy {
String genString(int length);
}
// 2. 数字字符串生成策略
class NumGenImpl implements IGenStrategy {
@Override
public String genString(int length) {
StringBuilder sb = new StringBuilder();
Random rand = new Random();
for (int i = 0; i < length; i++) {
sb.append(rand.nextInt(10)); // 生成数字 0-9
}
return sb.toString();
}
}
// 3. 字母字符串生成策略
class AbcGenImpl implements IGenStrategy {
@Override
public String genString(int length) {
StringBuilder sb = new StringBuilder();
Random rand = new Random();
String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
for (int i = 0; i < length; i++) {
sb.append(characters.charAt(rand.nextInt(characters.length())));
}
return sb.toString();
}
}
// 4. 混合字符串生成策略(字母+数字)
class MixGenImpl implements IGenStrategy {
@Override
public String genString(int length) {
StringBuilder sb = new StringBuilder();
Random rand = new Random();
String characters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
for (int i = 0; i < length; i++) {
sb.append(characters.charAt(rand.nextInt(characters.length())));
}
return sb.toString();
}
}
// 5. Player类
class Player {
int levelNo; // 玩家等级
int score; // 当前得分
long startTime; // 游戏开始时间
long elapsedTime; // 游戏已用时间
public Player(int levelNo) {
this.levelNo = levelNo;
this.score = 0;
}
public void startGame() {
startTime = System.currentTimeMillis();
}
public void endGame() {
elapsedTime = System.currentTimeMillis() - startTime;
}
public void addScore(int score) {
this.score += score;
}
}
// 6. Level类(关卡类)
class Level {
int levelNo; // 关卡编号
int strLength; // 字符串长度
int strTimes; // 每关字符串出现次数
long limitedTime; // 限时
int perScore; // 每个正确的得分
public Level(int levelNo, int strLength, int strTimes, long limitedTime, int perScore) {
this.levelNo = levelNo;
this.strLength = strLength;
this.strTimes = strTimes;
this.limitedTime = limitedTime;
this.perScore = perScore;
}
}
// 7. LevelParams类(关卡参数类)
class LevelParams {
Level[] levels; // 关卡集合
public LevelParams(Level[] levels) {
this.levels = levels;
}
}
// 8. Game类(游戏类)
class Game {
private Player player; // 玩家
private IGenStrategy iGenStrategy; // 字符串生成策略
private LevelParams levelParams; // 关卡参数
public Game(Player player, IGenStrategy iGenStrategy, LevelParams levelParams) {
this.player = player;
this.iGenStrategy = iGenStrategy;
this.levelParams = levelParams;
}
public String genStr(int levelNo) {
Level level = levelParams.levels[levelNo - 1];
return iGenStrategy.genString(level.strLength); // 根据当前策略生成字符串
}
public void printResult() {
System.out.println("游戏结束!");
System.out.println("得分: " + player.score);
System.out.printf("用时: %.2f 秒\n", player.elapsedTime / 1000.0);
}
public void start() {
Scanner scanner = new Scanner(System.in);
player.startGame();
// 遍历每一个关卡
for (Level level : levelParams.levels) {
String target = genStr(level.levelNo); // 生成当前关卡的字符串
System.out.println("Level " + level.levelNo + " - 请输如下字符串(长度: " + level.strLength + "):");
System.out.println(target);
// 按关卡要求进行字符串输入与检查
for (int i = 0; i < level.strTimes; i++) {
String input = scanner.nextLine();
if (input.equals(target)) {
System.out.println("正确!");
player.addScore(level.perScore); // 得分
} else {
System.out.println("错误!应为:" + target);
}
}
}
player.endGame();
printResult(); // 打印最终成绩和用时
}
public static void main(String[] args) {
// 创建不同的关卡
Level level1 = new Level(1, 10, 3, 60000, 10); // Level 1
Level level2 = new Level(2, 15, 3, 60000, 20); // Level 2
LevelParams levelParams = new LevelParams(new Level[]{level1, level2});
// 创建玩家和游戏策略(可以更改为其他策略)
Player player = new Player(1);
IGenStrategy strategy = new NumGenImpl(); // 可以切换为 AbcGenImpl 或 MixGenImpl
// 创建游戏对象并开始游戏
Game game = new Game(player, strategy, levelParams);
game.start();
}
}