文章目录
前言
这一章节,我们主要解决面对用户输入数据不符合预期时,不让虚拟机直接结束程序,保证我们的程序的稳定性,这里引入异常处理机制。还要完成我们游戏结果的可视化表达,并且可以让我们对数据结果的查询,这里会引入File类的使用还有ArrayList类的使用。
一、异常类的使用
1、为什么需要使用异常类?
其实在理想状态下,我们输入数据都合法合规的,那么程序的就不需要异常类的使用。但是很多情况下,我们输入的数据会存在概率性出错的概率,比如没用仔细读程序输入的要求,手滑直接将数据输入到我们的程序…反正异常类的使用可以有效的挺高我们的程序的健壮性。不至于因为一些人为因素而造成虚拟机将我们的程序直接干掉。
1,表现形式
1.try-catch
try {
statement;
} catch (Exception e) {
e.printStackTrace();
}
这句话执行方式是这样的,try语句包裹的我们的可能会出错的语句,如果捕获到错误的时候我们的虚拟机会将出错信息的地方将其在控制台中抛出。我们try语句中表达式不进行表示,程序进行向下执行。
2.try-finally
try {
statement;
} finally {
statement;
}
这句话的执行路径也是先继续捕获操作,不管捕获操作是否成功,程序会进行对下面finally包裹语句。
但值得注意的一点就是return表达式的在这里的使用,假设我们在这里将try中放入一个return表达式的话,我们的执行步骤是怎么样的呢?很多人会认为我们在try语句中使用return语句,就不会进行下面语句了,其实不是它会先进行完我们的try语句再进行return语句!!!!
3.try-catch-finally
执行路径就是当我们捕获错误到的时候,我们就会多一个将栈顶错误打印出来!其他执行路径于如上相似。
4.try-resource-with
这个是jdk1.7出现的语法糖,这个捕获异常的机制可以使用在我们需要创建资源性文件的时候使用,这个捕获机制是如何使用的呢?
try (createStatement){
statement;
} catch (IOException e) {
statement;
}
这个可以首先判断我们的资源型文件是否已经存在,如果存在的话直接捕获异常!那么为什么会说这个语法是一个语法糖呢?
我们知道我们将文件进行操作时首先需要打开,然后进行将再进行我们接下来的操作,进行完操作之后我们接下来一步是什么呢?那就是将我们的文件关闭,将文件内容写入硬盘进行永久保存,但是不管是创建,修改还是关闭我们的编译器都会报出一个warming级别的错误。这种错误我们需要解决才能通过我们编译器的编译,所有我们需要如果用try-catch去捕获错误,我们需要至少需要三个try-catch语句,但是如果我们使用try-resource-with进行我们异常操作的话,我们仅需要一个去包裹。
那为什么try-resource-with可以少这么多的try-catch语句的包裹呢?因为它能自动检查文件是否已经被创建,读写操作是否已经可以找到我们指定的文件,还能在语句结束时,自动关闭我们文件。这就是我们try-resource-with捕获机制的优势所在!
2.程序改进空间
前面我们侃侃而谈这么多对捕获机制的一个描述,那么在我们石头剪刀布中我们应该如何进行一个改进呢?
首先我们需要确定我的石头剪刀布的改进空间在哪?因为我们石头剪刀布存在人对象的原因,可能会造成我i们数据输入的错误,所以我们要对我们这个存在问题进行我们的程序的改进,那么我们输入只有可能输入三个数字我们的判断机制才能读懂。所以我们可以做一个机制进行我们数据控制,就是我们实现整一个输入,我们只能接入0,1,2三个数字,读入不合法数值时候我们就可以让用户再一次输入。那么具体应该怎么做呢?来看看我实现的代码!
int input = -1;
//使用person1.guesture接人输入
while(true) {
try {
log.info("请输入你要选择的手势(0,石头,1,剪刀,2布):");
input = in.nextInt();
person.guesture = person.getGuesture(input);
if (person.guesture <= 2 && person.guesture >= 0) {
break;
}
} catch (Exception e){
log.info("请检查你的输入,请再次输入!!!");
}
我们对于下一个输入0~2以外的数据的时候,我们的就不能跳出这个无线循环,但是在编写过程中我发现了一个奇怪的问题:我们程序在我们输入数据不合法的时候就会无限重复下面的输出语句,这个问题这么解决呢?我首先想到的问题时我们输入缓冲区还未清空,我们整个程序就会按照我们第一次输入的数据进行一个执行。那么我们需要重新让我们键盘缓冲区置空,等待用户的输入,再进行下次输入。所以我们改进的代码应该加入一个重新读入键盘数据的操作的操作。下面是改进的代码!
int input = -1;
//使用person1.guesture接人输入
while(true) {
try {
log.info("请输入你要选择的手势(0,石头,1,剪刀,2布):");
input = in.nextInt();
person.guesture = person.getGuesture(input);
if (person.guesture <= 2 && person.guesture >= 0) {
break;
}
} catch (Exception e){
log.info("请检查你的输入,请再次输入!!!");
in.next();
}
二、游戏数据的可视化表达
1.可视化表达是什么?
就是我们用笔在纸上进行记录,然后我们可以看我们纸上的记录的结果仅此而已!
2.如何进行操作我们可视化操作呢?
就让我们先想想我们需要的工具
- 一支笔
- 一张纸
- 一些数据
那么这些在我们程序是怎么表示的呢?我们首先是需要一张纸,那么我们的纸是什么呢?就是file,一个文件,那么一些数据从那里来呢?数据就是从我们进行我们游戏的时候判断语句产生的游戏结果,那么我们还需要一只笔,众所周知我们计算机数据以字节进行数据存储的,所以我们写入操作最基本是一个字节进行写入,但是一个字节是不能完成我们汉字的写入操作的,那么我们就需要使用字节流进行我们数据写入。
下面推荐大家读这一篇文章,进行我们文件操作学习的深入Java IO流(超详细!)
1、数据存储
因为我们需要实现数据的查找的功能,因此我们需要进行一个有着存储先后顺序的集合,不仅方便我们进行写入操作,既能实现我们查找操作。这里我会使用ArrayList集合进行数据的存储。
2、如何使用集合实现数据存储呢?
首先我们一定需要创建ArrayList对象,然后将我们的游戏结果加入到ArrayList类创建对象之中。
所以我们加入这些代码到我们的项目之中。
ArrayList<String> gameResult = new ArrayList<>();
gameResult.add("第"+count+"局的结果"+result);
利用这两行代码就能完成我们的数据存储了!
3、全部代码编写
1.人,电脑,判断机制
与上一章节无疑,可以看看第二章节具体代码编写
2.读入操作和写入操作
这里利用了try-resource-catch进行一个捕获操作
写入数据:
/**
*@Description: 输入数据
*@Param: [result]
*@return:[ArrayList<String>]
*@Author: Mr.Lin
*@Date: 2022/5/27 19:31
*/
public void addDate(ArrayList<String> result){
try(BufferedWriter bufferedWriter =
new BufferedWriter(new OutputStreamWriter(new FileOutputStream("src/test/resources/result.txt",true)))){
bufferedWriter.write(String.valueOf(result));
bufferedWriter.newLine();
} catch (IOException e) {
e.printStackTrace();
}
}
读文件数据:
/**
*@Description: 读文件内内容
*@Param: []
*@return:[]
*@Author: Mr.Lin
*@Date: 2022/5/27 19:31
*/
public String readDate(){
String s = null;
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(new FileInputStream("src/test/resources/result.txt")))){
s = bufferedReader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return s;
}
3、main函数编写
@Slf4j
public class GameMain {
public static void main(String[] args) {
String result = null;
Judge judge = new JudgeIMPH();
Scanner in = new Scanner(System.in);
//创建人对象,然后得到手势
Person person = new Person("","");
//创建电脑对象,然后得到手势
Computer computer = new Computer("","");
Random random = new Random();
//创建file来存储数据
ResultFile resultFile = new ResultFile();
ArrayList<String> gameResult = new ArrayList<>();
//进行判断语句
int count = 1,win = 0,debeat = 0;
while(count <= 5 && win <=3 && debeat <= 3){
int input = -1;
//使用person1.guesture接人输入
while(true) {
try {
log.info("请输入你要选择的手势(0,石头,1,剪刀,2布):");
input = in.nextInt();
person.guesture = person.getGuesture(input);
if (person.guesture <= 2 && person.guesture >= 0) {
break;
}
} catch (Exception e){
log.info("请检查你的输入,请再次输入!!!");
in.next();
}
}
//使用end来接judge方法的返回值
int computerGuesture = random.nextInt(3);
result = judge.judge(computerGuesture , person.guesture);
if (result.equals("胜利"))win++;
else if (result.equals("失败"))debeat++;
log.info("这局游戏的结果是"+ result);
log.info("现在游戏已经进行"+count+",其中胜利了"+win+",失败了"+debeat);
gameResult.add("第"+count+"局的结果"+result);
resultFile.addDate(gameResult);
count++;
}
}
}
总结
这一次编写改进的地方是使用文件操作,将我们结果进行一个可以有记录的保存,利用异常类让我的程序更为之健壮。但是不足地方在我们写入操作中没能将我们数据进行一个对于阶段性的输入,而是将我们全部数据加入我们文件中,而且没能发挥出我们ArrayList集合存储数据的优势,查找需要进行一个时间复杂度为O(n)的操作,而ArrayList的查找效率是O(1)。程序是一次性的不能多次使用,因为我们的文件创建仅仅只有能有一次…这些都是我在检查程序发现的缺点,如果大家发现其他错误,希望大家能指正我的错误,让我继续完善我的程序!谢谢大家!