JavaEE漫漫学习路之任务篇之面向对象高级

这篇博客详细介绍了作者在学习JavaEE过程中,通过三个实际任务深入理解面向对象编程:用户登录案例、自定义MyList类实现动态扩容以及人机猜拳游戏。通过这些实践,作者探讨了接口定义、动态扩容机制、垃圾回收原理以及控制台游戏的实现策略。
摘要由CSDN通过智能技术生成


前言

这次是真正意义的发布第一次博客,也是由于老师有要求,我又很纠结到底要不要去写博客,因为对于我而言,这条路在我毕业后不一定走,但是我现在又是学这个的,想要学好,那些博客,记录自己的学习情况又是必要的一个步骤(要不你去写笔记,用笔写)。俗话说:好记性不如烂笔头,你学习后不久的知识也许很快就会忘,所以这也是写博客的一个原因。即记录了自己的学习进度,又可以在之后的学习中回过头来复习,当然也是为了更好的理解学习的内容,毕竟都是要脸的,你发个博客,要是烂的不行,也觉得丢脸。好了,心路历程,感受先告一段落。接下来看正文。


题目一:用户登录案例

任务概述:假设用户账号为:admin,密码为 123,编写用户登陆案例。 要求:请将登陆定义为 login 方法, 并加粗样式将 login 方法写在 UserService 类中。

解题思路: 我们一看到题目,上面开头就说假设用户账户,还有密码。那我们其实就可以定义两个属性

     private String name;//用户名
     private String password;//用户密码

当然建议在定义属性的同时,加上无参和全参的构造方法,要不要的先不说,起码要求有,用到了直接调用就是。

 		public UserService(){}//无参构造方法

        public UserService(String name, String password) {//全参构造方法
            this.name = name;
            this.password = password;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getPassword() {
            return password;
        }

        public void setPassword(String password) {
            this.password = password;
        }

之后的要求是:定义为 login 方法, 并将 login 方法写在 UserService 类中。那我的解决方法是,创建了一个接口User,写了个login方法,之后再UserService类中去重写了一下,直接参考老师代码

User接口

public interface User {
    //接口方法
    boolean login(String name,String password);
}

这是重写的login方法

 @Override//重写接口的方法
    public boolean login(String name,String password)  {
        //字符串比较相等的时候将后输入的放前面,防止空指针异常
        if(name.equals(this.name)) {
            if(password.equals(this.password)) {
                System.out.println("登录成功!");
                return true;
            }else {
                System.out.println("密码错误!");
            }
        }else {
            System.out.println("账号输入有误!");
        }
        return false;
    }

搞到这里,代码要求基本完成,然后就可以测试了

public class UserServiceTest {//测试类

    public static void main(String[] args) {
        UserService u = new UserService();//创建对象
        Scanner input = new Scanner (System.in);//控制台输入
        //存放用户登录得账号及密码
        String name ;
        String password;
        //设置账号及密码
        u.setName("admin");
        u.setPassword("123");
        //判断用户登录情况
        for (int  i = 0;i<3;i++){
            System.out.println("你还有" + (3-i) + "次机会");
            System.out.println("请输入账户名称:");
            name = input.next();
            System.out.println("请输入密码:");
            password = input.next();
            if(u.login(name,password)) {
                break;
            }
        }
    }
}

这里参考了这位兄弟的代码:链接:https://blog.csdn.net/weixin_46312449/article/details/112733549

题目二:MyList类

2、试题:自定义一个类, 命名为 MyList,类中包含属性:Object[] element;定义如下几个方法:

  1. 增加方法 add : 可以向数组属性中依次存储 Object,数
    组内容存满时,需实现动态扩容(详解在下面)。 参考: Boolean add(Object
    obj)
  2. 删除方法 remove : 可以根据数据或下标,从数组属性
    中删除 Object 数据,删除后,数组后续 元素需前移。 参考:void remove(Object
    obj) 或 void remove(Integer index)
  3. 查询方法 get : 方法传入下标,返回数组中指定下标的
    数据。
    参考:Object get(Integer index)
  4. 当前存储数据量 size : 获取当前存储的有效数据长度
    参考:size=数组.length

动态扩容详解: 无需真正增加原数组的容量,只用将原内容复
制到新的大数组,然后让原数组名称重新等于大数组即 可。由于原数组数据
在堆中, 失去引用会被 GC 自动回收。(考点:如何实现数组的动态长度)>

说到了垃圾回收,那我们也可以填补一下这个知识的空缺:

  • 垃圾回收器(GC),在C/C++等语言中,由程序员负责回收无用内存。
  • 而Java语言消除了程序员回收无用内存空间的责任;
  • JVM提供了一个系统线程(GC),用于跟踪存储空间的分配情况,检查并释放那些可以被释放的存储空间。垃圾回收器在Java程序运行过程中自动启用,程序员无法精确控制和干预。

言归正传,解题思路:首先定义一个类叫MyList,然后又说要包含一个属性Object[] element;这里就可以看出,是关于数组的,然后在往下看到它的几个方法中要求实现动态扩容,动态扩容很明显,他说要将原有的数组直接复制到新的大数组中,然后重新让原有的数组=新数组

贴图如下:
在这里插入图片描述那其中的int capacity; 其实就是我们每次都要添加的最大容量,而int size;就是最终的大小了

所以我们的属性最后有:

    //属性
    private Object[] element;//盛放元素的数组
    private int capacity;//最大容量
    private int size;//实际大小

    //构造方法
    public MyList2() {
        size=0;//实际大小默认就是0
        capacity=4;//默认容量--可以自己定义
        element=new Object[capacity];//分配数组的空间--数组的空间一定开辟就不能改变大小
    }

接着分析说增加方法 add中可以向数组属性中依次存储 Object,数组内容存满时,动态扩容。那我们就需要思考怎么存储,怎么扩容,什么时候进行扩容。于是有了接下来的add方法

代码如下(示例):

   //方法
    /**
     * 添加元素
     * @param obj
     */
    public void add(Object obj) {
        if(size>=capacity){//数组内容是否存满,满了之后需要扩容
            //动态扩容
            Object[] newArr=new Object[capacity*2];//新数组的大小可以自己决定,比原来大就可以
            //将原有数组的元素复制到新的数组中
            for (int i = 0; i < element.length; i++) {
                newArr[i] = element[i];
            }
            //让原数组名称重新等于新数组即可
            element = newArr;
        }
        element[size]=obj;//存放元素
        size++;//实际大小+1
    }

同样的在往下看到了删除方法时,要求可以根据数据或下标两个方面,从数组属性中删除 Object 数据。它说删除后,数组后续元素需前移。
我们先说根据数据删除,我们在删除数据的时候第一判断就是其是否存在,判定存在则直接删除对应的对象,并返回

 /**
     * 根据指定的对象删除
     * @param obj
     * @return
     */
    public Object remove(Object obj) {
        //先判断该对象是否存在
        for (int i = 0; i < element.length; i++) {
            if(element[i]!=null && obj==element[i]) {
                return remove(i);//找到对象的对应下标,remove
            }
        }
     	//如果没有
        return null;//该数组中没有要删除的对象
    }

然后再来说根据下标删除,这个就要求我们去明白是通过什么行为操作去通过下标来删除的,其实与其说是删除不如说是覆盖,因为本来的对象其实也没有丢失,只是被后面的对象给掩盖了。打个比方:说我和你打架,我180,160斤,你160,120斤,我上去就把你给压在了身下,旁边的人还以为我自己趴地上搞行为艺术。那别人没有看见你,但你是不存在了吗,当然不是,你只是在我下面而已,对吧。用一张图表示:

贴图如下:
在这里插入图片描述那通过这个图我们应该就可以理解是怎样通过下标覆盖删除的了,代码如下

 /**
     * 根据下标删除
     * @param index
     * @return
     */
    public Object remove(int index) {
        //如果是最后一个元素
        if(index==size-1) {
            size--;
            return element[index];//返回被删除的数值
        }
        //数组后续元素需前移
        Object obj=element[index];
        for(int i=index;i<size;i++) {
            element[i] = element[i+1];
        }
        size--;//删除成功之后实际大小要-1
        return obj;//返回被删除的数值
    }

最后是查询的方法:比较简单,直接通过get(int index)传入下标,return一下还有getSize获取大小,打印出来就好了

  /**
     * 查询方法
     * @param index
     * @return
     */
    public Object get(int index) {
        return element[index];
    }

    public int getSize() {
        return size;
    }

最后是Test类

public class MyListTest2 {
    public static void main(String[] args) {
        MyList2 list = new MyList2();
        //添加元素
        for (int i = 0; i < 5; i++) {
            list.add("一模一样"+i);
        }
        String s1="一模一样";//根据下标删除

        list.add(s1);
        //String s2="一模一样2";//根据指定的对象删除
        //删除元素
        //Object obj=list.remove(s2);
        Object obj=list.remove(3);
        System.out.println("删除的元素:"+obj);//根据下标删除
        //获取元素
        for (int i = 0; i < list.getSize(); i++) {
            System.out.println(list.get(i));
        }
    }
}

题目三:人机猜拳游戏

任务概述: 今天的任务是通过控制台方式实现一个人机对战的猜拳游戏,用户通过输入(1.剪刀 2.石头 3.布),机器随机生成(1.剪刀 2.石头 3.布),胜者积分,n 局以后通过积分的多少判定胜负。

  1. 定义机器类,以及拳头属性(此属性只有三个值:剪刀,石头,布。这里的值可以使用数值代替)
  2. 定义生成随机数的方法(让机器生成剪刀,石头,布的值),赋值给第一步的拳头属性
  3. 定义测试类,获取用户输入的剪头石头布的值,和随机生成的值比较
  4. 测试中,定义变量保存胜者积分

重点来了各位,人机之争,万万不可不可疏忽。

解题思路:我们看任务概述说,这是一个人类和机器通过控制台猜拳,积分比赛,最终根据比分输赢的游戏。

首先第一个要求说是定义一个机器类,有3个属性,通过数值代替,那我们去想一些,我们是否需要去创建3个属性,分别是石头剪刀,布,然后set方法赋值,还是说我们直接去通过给3个值定义这3个属性呢?都可以兄弟们,但是我的能力有限,我是看到这个题目的时候就想到了之前老师的那个快递E栈(现在没开始去写那个博客,等以后吧)的方法,毕竟都是通过控制台输出的。然后我就首先想到了这个

public static void menu(){
        while(true) {
            int id = starMenu();
            if(id==0) {
                return;
            }
        }
    }

然后我就按照这相同的思路一步一步实现到最后

 //判断赢家方法
    public static String ScoreMenu() {
        Scanner input = new Scanner(System.in);
        System.out.println("用户的积分:" + p.getScore());
        System.out.println("机器的积分:" + m.getScore());
        if (p.getScore() > m.getScore()) {
            return "人类领先";
        } else if (p.getScore() == m.getScore()) {
            return "人类和机器打平";
        } else {
            return "机器赢";
        }

    }

最后的时候发现p对象为空,出现了一个空指针异常,因为我是按照原本的快递E栈的实现方法写的(那个是数组),然后我很苦恼,去网上找了好久,也没有解决,最后是去出现写个类,不用static静态去创建方法之后,去调用原本的Game才算是完整

注意:以上都是发牢骚,接下来才是真正的解题

思路不变,首先创建三个类,一个人类,一个不是人类(机器),一个是游戏类,分别在人类类与机器类中构造无参和全参方法,当然也创建他们共有的一个属性,都有积分,在人类类中通过创建said方法,写个循环,由于不知道到底进行多少次,所以用while循环,然后嵌套一个switch(这个网上都要,直接参考),选择情况1,2,3,,分别表示剪刀,石头,布

public class People {
    private int score;

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }
    public People(){}//无参构造方法

    public People(int score) {//全参构造方法
        this.score = score;
    }

    public int said(){
        Scanner input = new Scanner(System.in);
        System.out.println("游戏开始:");
        while (true){
            System.out.println("人出拳的方式:1、剪刀,2、石头,3、步");
            int num = input.nextInt();
            switch (num){
                case 1:
                    System.out.println("人出剪刀");
                    break;
                case 2:
                    System.out.println("人出石头");
                    break;
                case 3:
                    System.out.println("人出布");
                    break;
                default:
                    System.out.println("你是不会玩吗?");
                    break;
            }
            return num;
        }
    }
}

同理:机器类

public class Machine {
    private int score;

    public int getScore() {
        return score;
    }

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

    public Machine(int score){
        this.score = score;
    }
    public int say(){
        Scanner input = new Scanner(System.in);//获取控制台输入
        while (true){
            System.out.println("机器出拳:1、剪刀,2、石头,3、布");
            Random r = new Random();
            int num = r.nextInt(3);
            switch (num){
                case 1:
                    System.out.println("机器出剪刀");
                    break;
                case 2:
                    System.out.println("机器出石头");
                    break;
                case 3:
                    System.out.println("机器出布");
                default:
                    System.out.println("机器出故障了,请重新输入");
                    break;
            }
            return num;
        }
    }
}

这里要讲一下,随机数问题,我们可以通过
Random r = new Random();
int num = r.nextInt(3);
这两步来产生随机数,并使num接收

参考链接:https://www.cnblogs.com/phpyangbo/p/java-suijishu.html
这位哥哥正好也是有讲猜拳游戏的,大家也可以参考,学习嘛,就是到处看,到处找过来敲

OK,往下看,接下来通过创建startMenu方法首先实现起始界面。

public int starMenu() {//起始界面
        System.out.println("=====欢迎参加人机对战猜拳游戏======");
        System.out.println("用户输入:");
        System.out.println("请输入您的操作:1-开始游戏,2-查看比分,0-退出");
        int id = 0;
        while (true){
            id = input.nextInt();//接收id
            if(id == 1) {
                GameMenu();
                break;
            }else if(id==2) {
                ScoreMenu();
                break;
            }else if(id==0){
                System.out.println("谢谢使用");
                return 0;
            }else {
                System.out.println("选择有误,请重新输入!");
            }
        }
        System.out.println("本次游戏已结束!");
        return id;
    }

这是最终实现的,起始在刚开始,我们肯定要去填充id==1的GameMenu,按照要求,人类先出手,然后我们直接通过number1与number2调用人类类的said方法和机器类中的say方法,通过if else if else 判断输赢情况

public void GameMenu() {//游戏界面
        System.out.println("人类优先出拳:");
        int number1 = p.said();
        int number2 = m.say();
        if ((number1 == 1 && number2 == 3) || (number1 == 2 && number2 == 1) || (number1 == 3 && number2 == 2)) {
            System.out.println("人类胜利");
            p.setScore(p.getScore() + 1);
        } else if (number1 == number2) {//平局
            System.out.println("二者平局!");
        } else {
            System.out.println("机器侥幸!");
            m.setScore(m.getScore() + 1);
        }
    }

之后是填充id==2的积分界面,在设计中我是首先将现在的积分情况打印出来,之后通过再一个if else if else 来比较最终结果,结束比赛。

 //积分排名
    public void ScoreMenu() {//积分界面
        Scanner input = new Scanner(System.in);
        System.out.println("用户的积分:" + p.getScore());
        System.out.println("机器的积分:" + m.getScore());
        System.out.println("最终对战结果如下:");
        System.out.println("人类 :\t机器");
        if (p.getScore() > m.getScore()) {
            System.out.println("人类领先");
        } else if (p.getScore() == m.getScore()) {
            System.out.println("人类和机器打平");
        } else {
            System.out.println("机器胜利");
        }
    }

Game类完整代码如下:

public class Game {
    public Scanner input = new Scanner(System.in);
    public Random random = new Random();
    private People p;
    private Machine m;

    public People getP() {
        return p;
    }

    public void setP(People p) {
        this.p = p;
    }

    public Machine getM() {
        return m;
    }

    public void setM(Machine m) {
        this.m = m;
    }
    public Game() {
        this.p= new People();
        this.m = new Machine();
    }
    public Game(People p,Machine m) {
        this.p= new People();
        this.m = new Machine();
    }

    public void menu(){
        while(true) {
            int id = starMenu();
            if(id==0) {
                return;
            }
        }
    }

    public int starMenu() {//起始界面
        System.out.println("=====欢迎参加人机对战猜拳游戏======");
        System.out.println("用户输入:");
        System.out.println("请输入您的操作:1-开始游戏,2-查看比分,0-退出");
        int id = 0;
        while (true){
            id = input.nextInt();//接收id
            if(id == 1) {
                GameMenu();
                break;
            }else if(id==2) {
                ScoreMenu();
                break;
            }else if(id==0){
                System.out.println("谢谢使用");
                return 0;
            }else {
                System.out.println("选择有误,请重新输入!");
            }
        }
        System.out.println("本次游戏已结束!");
        return id;
    }

    public void GameMenu() {//游戏界面
        System.out.println("人类优先出拳:");
        int number1 = p.said();
        int number2 = m.say();
        if ((number1 == 1 && number2 == 3) || (number1 == 2 && number2 == 1) || (number1 == 3 && number2 == 2)) {
            System.out.println("人类胜利");
            p.setScore(p.getScore() + 1);
        } else if (number1 == number2) {//平局
            System.out.println("二者平局!");
        } else {
            System.out.println("机器侥幸!");
            m.setScore(m.getScore() + 1);
        }
    }
    //积分排名
    public void ScoreMenu() {//积分界面
        Scanner input = new Scanner(System.in);
        System.out.println("用户的积分:" + p.getScore());
        System.out.println("机器的积分:" + m.getScore());
        System.out.println("最终对战结果如下:");
        System.out.println("人类 :\t机器");
        if (p.getScore() > m.getScore()) {
            System.out.println("人类领先");
        } else if (p.getScore() == m.getScore()) {
            System.out.println("人类和机器打平");
        } else {
            System.out.println("机器胜利");
        }
    }
}

之后通过Test类,调用menu,输出控制台进行比赛

public class Test {
    public static void main(String[] args) {
        Game game = new Game();
        game.menu();
    }
}

接下来是比赛结果:
在这里插入图片描述
经过漫长的比赛,最终人类赢得了胜利,让我们为人类的胜利欢呼吧


总结

到了这里,我们的任务也算是告一段落,其实通过这次任务也算是复习了一遍我们在这段时间进行的学习,当然很多的没有复习到,而且在完成任务也不是独立完成的,我承认我是菜鸟,好了,慢慢来吧,且学且看吧,指不定,嘿嘿,我不学了,我换行。啊!!!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少年,又是你

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值