JAVA 石头剪刀布简单实现

题目:

任务描述
“剪刀石头布”的游戏相信大家都不陌生,本案例要求编写一个剪刀石头布游戏的程序。程序启动后会随机生成1~3的随机数,分别代表剪刀、石头和布,玩家通过键盘输入剪刀、石头和布与电脑进行5轮的游戏,赢的次数多的一方为赢家。若五局皆为平局,则最终结果判为平局。

V1.0要求:

1.本题目为人机对战,项目里至少有两类,人和机器;
2.利用单例模式,创建用来存储“石头剪刀布”游戏结果的对象;
3.可以将“石头剪刀布”游戏结果输出成 JSON格式 的文件保存,并且还能将结果导入显示上一次游戏结果;
4.Maven项目;
5.git版本管理,至少很有master、develop分支,本地开发时创建以自己名字命名的分支,并在此分支上开发。

V1.1要求:

1.项目中引入logback日志框架;
2.将结果的导入和导出功能,归纳成接口(泛型接口、泛型方法);
3.编写接口实现类的单元测试类(需要引入Junit单元测试框架)。

V1.2要求:

1.将游戏运行独立成一个子线程运行;
2.优化“石头剪刀布”算法(解析算法就是用解析的方法找出表示问题的前提条件与结果之间关系的数学表达式,并通过表达式的计算来实现问题求解的方法。);
3.将“石头剪刀布”游戏规则,归纳为游戏规则接口中的一员。

算法参考:
从石头剪刀布浅谈算法的作用
算法进化历程-剪刀石头布

V1.3要求:

1.利用线程池模拟多组“石头剪刀布”比赛(每组参赛的参赛对象都不一样);
2.将每组的比赛成绩保存起来,并且可以将每组的成绩以列表的形式输出(最好有专门的线程输出结果列表);
3.列表中可以输出,成绩最佳的成员。(可以利用Stream)

V1.4要求:

1.让一个参赛对象参加不同的比赛(大于5场),参赛对象游戏生命有3个点;
2.游戏参赛对象获胜,生命点加1;游戏参赛对象失败,平局,生命点减1;当生命点数为0时,终止参赛对象的任何比赛;
3.将程序中的逻辑上的异常,创建自己的异常类,统一管理。

V1.0要求及其实现:

题目要求
1.本题目为人机对战,项目里至少有两类,人和机器;
2.利用单例模式,创建用来存储“石头剪刀布”游戏结果的对象;
3.可以将“石头剪刀布”游戏结果输出成JSON格式的文件保存,并且还能将结果导入显示上一次游戏结果;
4.Maven项目;
5.git版本管理,至少很有master、develop分支,本地开发时创建以自己名字命名的分支,并在此分支上开发。

在开始写之前,我们先了解一些需要知识:

单例模式:

定义:

保证一个类仅有一个实例,并提供一个访问它的全局访问点。

单例模式好处:
可以实现在需要的时候才创建对象,避免了不必要的资源浪费,
减少了 new 的使用对系统内存的使用频率降低,
减少 GC 压力 , 缩短 GC 停顿时间
但如果一直没有使用就会造成了资源的浪费。
提高性能

(GC 就是垃圾回收,是 Java 中的一种垃圾回收机制,指的是在 JVM 中用于释放那些不再使用的对象所占用的内存。而使用 static 在程序一开始执行就创建好了,不需要后面不断的 new ,而且 static 也保证了该类只有一个。)

参考:
GC是什么,为什么要有GC?
Java的GC机制

实现:

构建方式有两种:
· 饿汉方式: 指全局的单例实例在类装载时创建
· 懒汉方式: 指全局的单例实例在第一次被使用时构建

两种模式相似点:
· 单例类必须要有一个 private 访问级别的构造函数,只有这样,才能确保单例不会在系统被其他代码实例化

· instance 成员变量 和 unqueInstance 方法必须是 static 的。
(static 保证该类的实例只存在一个)

在例子中我参考使用的是: 饿汉式

// 定义为常量保证一个类只有一个实例
private static final ResultOfGame RESULT_OF_GAME = new ResultOfGame();
 /*
 提供一个访问它的全局访问点
 将初始化的对象返回回去 ,在使用这个类的之前就创建好了这个对象
 */
public static ResultOfGame getInstance(){
        return RESULT_OF_GAME;
}

这种方法,不管你用不用都先创建,一直没有使用则浪费了空间,是典型的空间换时间,在每次调用时候不需要判断(因为只存在一个实例)。

参考链接:
深入理解单例模式——只有一个实例

JSON 格式文件保存:

JSON (JavaScript Object Notation)是一种轻量级的数据交换格式。
(轻量级,是指种格式不需要特定的容器,运行时占用内存资源很少。相对的,重量级,则是指不能随意创建和销毁它的实例,占用很多资源。)

参考:什么是重量级?什么是轻量级?
JSON 文件 参考: 常用文件类型 – JSON文件介绍
对JSON文件操作: java简单工具(一):JSON文件读取和写入

而我在这里使用的是 .txt 的文本文件

先创建一个 static 文件路径 Filepath 这样后面就不用频繁创建了
public static String Filepath = "C:\\Users\\彬彬\\IdeaProjects\\test\\test_file\\result.txt";

在gameV10 中使用 saveJsonData() 先初始化文件 为 null
防止上一次的游戏结果影响本局的游戏数据记录和读取。
在游戏进行中 每一局都存取本局结果,在下一局可以显示上一局的结果以及本局的结果

public static void gameV10(){
        scan.nextLine();
        // 初始化文件
        ResultOfGame.saveJsonData("null",Filepath);
        int n = 5;
        for(int i=0;i<n;i++){
            System.out.println("=====石头剪刀布 V1.0 =>");
            System.out.println("你出:(请输入 剪刀 石头 或 布):");
            Person person = new Person(scan.nextLine());
            String robotPunch = robot.robotPunch();
            System.out.println("机器出:"+robotPunch);
            // 这一局的游戏结果
            String result1 = gameOfRockPaperScissors(person.getPunch(),robotPunch);
            // 上一局结果
            System.out.println("上一局游戏结果:"+ ResultOfGame.readJsonData(Filepath));
            // 保存结果
            System.out.println("保存结果:" + ResultOfGame.saveJsonData(result1, Filepath));
        }
    }

/**
* 向文件中写入数据
*/
public static boolean saveJsonData(String jsonString,String jsonFilePath){
        boolean result = false; 
        BufferedWriter bw = null;
        //  使用 try {} catch(){} 环绕 
        // 捕捉可能产生的 IOException 异常
        try{
            File file = new File(jsonFilePath);
            if(!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
                file.createNewFile();
            }
            bw = new BufferedWriter(new OutputStreamWriter((new FileOutputStream(file)), StandardCharsets.UTF_8));
            bw.write(jsonString);
        // 保存成功 ture
            result = true;
        }catch(IOException e){
            System.out.println("保存数据到json文件异常!" + e);
        }finally{
            if(null != bw){
                try{
                    bw.close();
                }catch(IOException exception){
                    System.out.println("保存数据到json文件后,关闭流异常" + exception);
                }
            }
        }
        return result;
    }

/**
 * 读取文件数据
 */
    public static String readJsonData(String jsonFilePath ){
        File file = new File(jsonFilePath);
        String result = null;
        FileReader fr = null;
        /*
           文件读取对象
         */
        BufferedReader br = null;
        /*
           字符流对象
         */
        try{
                fr = new FileReader(file);
                br = new BufferedReader(fr);
                String str;
                while((str = br.readLine()) != null){
                    result = str;
                }
            }catch(Exception e) {
            e.printStackTrace();
        } finally{
            try{
                fr.close();
                br.close();
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }

Maven 项目的创建(IDEA):

首先我们先了解下为什么要创建使用 Maven 项目
Maven 项目是一个项目管理 和 整合工具(简单来说就是将我们做项目的一些需要的 jar 包等 一些需要的东西帮我们封装好这样就不需要自己去下载和寻找了,就像现在的学习都有很多补习班,以前你还要考虑好自己的学习路线,而现在补习班都帮你规划好你的学习路线,你只需要选择自己适合的,就可以了)。

参考: maven是什么?有什么特点,及其 安装 使 用。
参考: IDEA配置Maven(详细版)

Git 的版本管理:

如果没有安装 git 的小伙伴可以参考 Git 详细安装教程(详解 Git 安装过程的每一个步骤
git 的基本操作:
· git init — 仓库初始化
在使用 Git 进行版本控制之前,必须要初始化仓库。在初始化前要先创建一个目录

$ mkdir git-tutorial
$ cd git-tutorial
$ git init

因为我这里是已经创建过仓库的,所以不太一样
在这里插入图片描述
结果初始化后的结果应该是这样的
git init
· git status —— 查看仓库状态
该命令用来查看 Git 仓库状态

$ git status

在这里插入图片描述
显示:我们在 master 分支下
commit (提交)指的是记录工作树下所有文件的当前状态
nothing to commit 说明我们当前仓库还没有记录任何状态。
这时我们需要建立一个 README.md 文件作为管理对象

$ touch README.md
$ git status

· git add —— 向暂存区添加文件
如果我们创建了文件且想添加到仓库中作为管理对象,我们通过git status 查看的时候发现它会显示在 Untracked files 里面,所以就需要通过 git add 将这个文件加入到暂存区(Stage 或者 Index),暂存区只是提交前的一个临时区域。

$ git add README.md
$ git status 

· git commit —— 保存仓库的历史记录
我们可以通过这些记录来查看当前暂存区实际保存到仓库的历史记录,甚至可以在工作树 恢复文件。

git commit -m "First commit" // 记述一行提交信息 

在这里插入图片描述

git commit // 记述详细的提交信息

在这里插入图片描述
建议使用 git 前,实操下每种命令的使用否则后面遇到问题就有可能会劝退哦,小编当时差点就被劝退了,由于急于上手直接写项目才拿项目来练手,结果吃了很多亏 。
推荐文章:Git命令大全
参考《GitHub 入门与实践》

V1.0 的最终代码实现
RockPaperScissorsOfV1:

package firstweekproject;

//V1.0要求:
//        1.本题目为人机对战,项目里至少有两类,人 和 机器;
//        2.利用单例模式,创建用来存储“石头剪刀布”游戏结果的对象;
//        3.可以将“石头剪刀布”游戏结果输出成JSON格式的文件保存,并且还能将结果导入显示上一次游戏结果;
//        4.Maven项目;                                                                        
//        5.git版本管理,至少很有master、develop分支,本地开发时创建以自己名字命名的分支,并在此分支上开发。   

import java.util.Scanner;
/**
 * @author 彬彬
 */
class RockPaperScissorsOfV1 {

    public static Robot robot = new Robot();
    public static Scanner scan = new Scanner(System.in);
    public static String Filepath = "C:\\Users\\彬彬\\IdeaProjects\\test\\test_file\\result.txt";
    // 项目要求 用JSON 格式保存 这里使用 .txt 文本保存
    public static void main(String[] args) {
            System.out.println("=====石头剪刀布=>");
                    gameV10();
            }

    public static void gameV10(){
        scan.nextLine();
        // 初始化文件
        ResultOfGame.saveJsonData("null",Filepath);
        int n = 5;
        for(int i=0;i<n;i++){
            System.out.println("=====石头剪刀布 V1.0 =>");
            System.out.println("你出:(请输入 剪刀 石头 或 布):");
            Person person = new Person(scan.nextLine());
            String robotPunch = robot.robotPunch();
            System.out.println("机器出:"+robotPunch);
            // 这一局的游戏结果
            String result1 = gameOfRockPaperScissors(person.getPunch(),robotPunch);
            // 上一局结果
            System.out.println("上一局游戏结果:"+ ResultOfGame.readJsonData(Filepath));
            // 保存结果
            System.out.println("保存结果:" + ResultOfGame.saveJsonData(result1, Filepath));
        }
    }


    public static String gameOfRockPaperScissors(String personPunch, String robotPunch){
        if(personPunch.equals(robotPunch)){
            System.out.println("当前局:平局");
            return "平局";
        }

        boolean personPunchRes =
                ("剪刀".equals(personPunch) && "布".equals(robotPunch)||
                        "石头".equals(personPunch) && "剪刀".equals(robotPunch)||
                        "布".equals(personPunch) && "石头".equals(robotPunch));
        boolean robotPunchRes =
                ("剪刀".equals(robotPunch) && "布".equals(personPunch)||
                        "石头".equals(robotPunch) && "剪刀".equals(personPunch)||
                        "布".equals(robotPunch) && "石头".equals(personPunch));

        if(personPunchRes){
            System.out.println("当前局:人类胜利");
            return "人类胜利";
        }
        if(robotPunchRes){
                    System.out.println("当前局:机器胜利");
                    return "机器胜利";
            }
        System.out.println("输入异常 ");
        return "输入异常";
    }
}

ResultOfGame:

package firstweekproject;

import java.io.*;
import java.nio.charset.StandardCharsets;

class ResultOfGame {
    private static final ResultOfGame RESULT_OF_GAME = new ResultOfGame();
    private ResultOfGame(){}

    /**
     * synchronized 用于加锁 保证 Result_of_game 只会被实例化一次
      */

    public static ResultOfGame getInstance(){
        return RESULT_OF_GAME;
        /*
          将初始化的对象返回回去 // 在使用这个类的时候就创建好了这个对象
          */
    }
    /**
     * 向文件中写入数据
      */
    public static boolean saveJsonData(String jsonString,String jsonFilePath){
        boolean result = false;
        BufferedWriter bw = null;
        try{
            File file = new File(jsonFilePath);
            if(!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
                file.createNewFile();
            }
            bw = new BufferedWriter(new OutputStreamWriter((new FileOutputStream(file)), StandardCharsets.UTF_8));
            bw.write(jsonString);
            result = true;
        }catch(IOException e){
            System.out.println("保存数据到json文件异常!" + e);
        }finally{
            if(null != bw){
                try{
                    bw.close();
                }catch(IOException exception){
                    System.out.println("保存数据到json文件后,关闭流异常" + exception);
                }
            }
        }
        return result;
    }
    /**
     * 读取文件数据
      */
    public static String readJsonData(String jsonFilePath ){
        File file = new File(jsonFilePath);
        String result = null;
        FileReader fr = null;
        /*
          // 文件读取对象
         */
        BufferedReader br = null;
        /*
          // 字符流对象
         */
        try{
                fr = new FileReader(file);
                br = new BufferedReader(fr);
                String str;
                while((str = br.readLine()) != null){
                    result = str;
                }
            }catch(Exception e) {
            e.printStackTrace();
        } finally{
            try{
                fr.close();
                br.close();
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
        return result;
    }


}

Person:

package firstweekproject;
/**
 * @author 彬彬
 */
public class Person {
    private String punch;
    public Person(){

    }

    public  Person (String punch){
        this.punch = punch;
    }

    public String getPunch() {
        return punch;
    }

    public void setPunch(String punch) {
        this.punch = punch;
    }
}

Robot:

package firstweekproject;
/**
 * @author 彬彬
 */
public class Robot {
    private String punch;
    /**
     * 定义 一个方法输出机器 出的 是什么
      */
    public Robot(){
    }

    public String robotPunch(){
        double flag;
        flag = (Math.random() * 3 );
        switch((int)flag){
            case 0:
                this.punch = "石头";
                return "石头";
            case 1:
                this.punch = "剪刀";
                return "剪刀";
            case 2:
                this.punch = "布";
                return "布";
            default: break;
        }
        return null;
    }

    public String getPunch() {
        return punch;
    }

    public void setPunch(String punch) {
        this.punch = punch;
    }
}

(本文都是根据自我对该项目和知识点的理解写的,如有不合理的欢迎指出,如有侵权及时删除。)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值