JAVA面向对象设计实例之一发牌比较大小

程序功能阐述如下:

由电脑随机从扑克牌堆中抽取前两张牌,一张属于用户,一张属于电脑,比较其大小:

      大小规则:数字规则:

                           2<3<4<5<6<7<8<9<10

                            花色规则:

                            方块<梅花<红桃<黑桃

      比较规则:数字优先,同数字,花色优先。

项目截图:

JAVA面向对象设计实例之一发牌比较大小_第1张图片

针对这个项目,我们先把思路做一下整理:

在这个项目中用到了数据,我们先从数据入手,进行数据的分析:

对于发牌比大小,数据就是牌。

单纯说牌,还有一个前提是比较大小.那么在数据进行设计的时候,比较简单和直接的设计就是:

按照牌大小顺序排好。

我们先看我们定的规则:

1、黑桃>红桃>梅花>方块

                 2、无论任何花色2<3<4<5<6<7<8<9<10

                 3、大王最大,其次是小王

           我们在排这个列表的时候可以根据方块2、梅花2、红桃2、黑桃2、方块3、….黑桃A 、小王、大王这个顺序来组织和排序数据。

           排完以后,诸如:方块2、梅花2、红桃2 、黑桃2等内容都可以是一个String类型,根据String类型的特点:一个String就是一个char数组,在堆内存里有一定的空间存储。54张牌就要有54个堆内存空间来存储。在对这个堆内存空间操作的过程中,也对字符串进行处理,而String的处理其实就是在String会进行数组复制,进而浪费内存。

           针对这一问题,我们可以采用技术:读写分离。

           把字符串做为一个变量也好,静态也罢,只是储存着牌的信息,也不能比较大小,真正比较大小还需要我们的整型数据,我们能不能把牌的信息和整型数据结合起来,一一对应,一个整型数据对应一个牌的信息,当我们使用这个牌的时候,再进行对应关系的映射,我们的操作只针对这个整型的一个集合。这就构成了我们的读写分离,读的是牌的信息和整型数的对应关系,写或者说操作的都是整型的列表或集合。

                那么整型库的类型可以定义成ArrayList

                 整型库与牌信息的对应关系我们应用Map集合:

Map

                 一副牌理好以后,我们需要洗牌,也就是打乱牌。

             打乱牌始终对ArrayList中的Integer操作,取得这张牌也可以对ArrayList的Integer操作,比较也是对ArrayList的Integer操作。这一期间都是对Integer操作,直到需要对应关系的时候我们直接找那个key对应的String映射。

           这样数据的思路出来了:

           也就是我们可以定义一个数据类,比如这个类叫PuKe。这里至少先有两个成员变量:

一个list列表,里面存0-----53的整数。

           一个Map 集合里面存0—53和方块2----大王的对应关系

           初始化的时候可以对这两个成员变量进行赋值:

           就是把花色牌和比较的数字一一对应。

           这样我们得到的代码可以是:

           先定义两个成员变量:

            

        

      再进行初始化:

            

        

        初始化以后进行赋值:

                 思路:我们可以把花色和点数进行循环匹配出牌面来,用一个标志整数位的值来进行累加计算整型值。

                 这样把数据放在列表中就变成以下形式:

        

JAVA面向对象设计实例之一发牌比较大小_第2张图片

        

        这个数据里缺少大王和小王,我们再把大王和小王对应的数值也放进去。

        JAVA面向对象设计实例之一发牌比较大小_第3张图片

        

        在数据PuKe类的构造函数里有了以下代码以后,我们可以用map的keySet遍历方法:

        JAVA面向对象设计实例之一发牌比较大小_第4张图片

        

        可以在主类中调用一下,看一下结果是不是我们想象中的样子:

            JAVA面向对象设计实例之一发牌比较大小_第5张图片            

            JAVA面向对象设计实例之一发牌比较大小_第6张图片

            

            JAVA面向对象设计实例之一发牌比较大小_第7张图片

            JAVA面向对象设计实例之一发牌比较大小_第8张图片

            

        放在Map集合中的结果已经完成,也是我们期望的顺序。下面我们要进行的就是集合中的数据打散,进行洗牌的操作。

洗牌实际上就是把纸牌集合随机进行两两交换,进行若干次,就可以把集合中的元素顺序弄乱。由于我们采用读写分离,实际上我们打乱的是Integer整型数据的集合。

实际的代码实现如下:

            JAVA面向对象设计实例之一发牌比较大小_第9张图片

        

    当然,由于collections工具类的引用,这段程序也可以用工具类实现:

            

        

        把集合打散后,相当于我们已经完成了扑克牌集合的准备。下一步我们要做的事就是能够从牌顶拿出一张牌给玩家,再拿出一张牌给电脑,然后比较大小。

        从牌库顶拿一张牌我们需要写方法get

        

        

        但要注意的是,我们每次拿的牌是不一样的,才能保证电脑和玩家的牌不同,我们就得需要定义一个index变量,这个变量存放的就是牌库的索引值,每次拿牌索引值增加,就可以保证每次拿到不同的牌,不过前提是这个值不会因为程序的初始化而变化,所以用静态变量来定义这个index值。

这样代码变成:

            

                JAVA面向对象设计实例之一发牌比较大小_第10张图片

        

            这样我们就实现了一个拿牌的过程。

            不过我们拿到的是数字,在外面调用后,一定会进行数字对应的牌面的转换,我们就需要把map这个存放牌值的集合进行封装后的getter,setter方法,供外面调用后把数字转成相对应的牌面。

            

                JAVA面向对象设计实例之一发牌比较大小_第11张图片

            

        整个数据类我们已经完成了,下面我们就要进行游戏角色类的设置了。

        对于游戏角色类,我们不难分析,由电脑和用户端同时拿一张牌,然后比较大小,从这个要求中,就会明白,我们需要电脑类、用户类,由于这两个类都需要从数据牌库类中取牌,方法也是一样的,所以我们可以找到他们的共同父类,我们暂且叫选手类。

        在选手类中我们不难分析,他们应该有成员变量就是他们各自的名字,我们可以简单处理,初始化的时候就把名字进行赋值,然后有一个方法从数据牌库中拿牌,拿到牌后转化成我们需要的牌面信息。

        JAVA面向对象设计实例之一发牌比较大小_第12张图片

        JAVA面向对象设计实例之一发牌比较大小_第13张图片

        

        以上是选手类的相关代码:

        电脑类和用户类直接继承于选手类即可,不用做方法的重写,但从继承的相关理论中我们知道,构造器不能继承过来,我们在子类继承中把构造器用super关键字来继承过来,这样子类就有自己的名字了,再进行比较牌面。

        于是电脑类Computer就为:

        JAVA面向对象设计实例之一发牌比较大小_第14张图片

        

        用户类就成为了:

            JAVA面向对象设计实例之一发牌比较大小_第15张图片

            

        参与的角度类建立成功后,我们创建操作类,就是游戏的整个运行过程类:

        一般的游戏过程类都包括:游戏初始化方法,游戏运行方法,游戏判断方法和游戏结束方法,

         于是这个运行过程类就包括:

             Init() 方法 game()方法  judge()方法  gameover()方法

        而对于这个游戏,init()可以实现发牌,发完牌直接比较,judge()方法,最后再gameover方法,不需要game()方法

我们可以写一个运行过程类的接口,让开发者都遵循我们统一的命名标准和规范。

        JAVA面向对象设计实例之一发牌比较大小_第16张图片

            

    接下来我们定义一个操作类实现这个接口

        JAVA面向对象设计实例之一发牌比较大小_第17张图片

                JAVA面向对象设计实例之一发牌比较大小_第18张图片

                

            在这个操作类中,我们只需要实现init()、judge()和gameover方法即可。

            Init()方法中实例牌库、电脑、用户,然后电脑和用户从牌库中取牌。

                JAVA面向对象设计实例之一发牌比较大小_第19张图片

            

       这里定义成员变量的Computer、Player、Puke 三个变量的原因是由于这三个成员变量在init()方法、judge()方法和gameover方法中都要调用,所以定义一个全局的成员变量。

        new Computer和new Player的过程中直接给这三个成员变量的name赋值,即参与游戏的两个角色,然后new PuKe()是把扑克牌产生,并调用PuKe中的shuffle方法打乱。再由Computer成员变量comp调用其父类的方法fetch一张牌,再由Player成员变量player调用其父类的方法fetch一张牌,然后执行judge();

          这是上面代码的相关逻辑。

          然后我们看judge()的完成。

        在judge方法中,我们明显需要得到一个量,这个量就是扑克牌对应的整型值,而这个值我们也放在了扑克牌类中的ArrayList列表中,我们即然要取这个值,就需要知道电脑类、玩家类中fetch方法中获取的牌对应的整型值是多少,我们没有定义这个获取方法,因此需要把电脑类和玩家类的父类再增加一个成员变量,这个变量就是key,我们通过fetch()方法获取了牌之后,还要把key值存储一下,然后定义getter方法让外界可以调用,这样judge就可以进行key值的比较了,继而来决定牌的大小。

        先看改写的选手类:

        增加key值:

                

        

        定义getter方法,外界不需要对其设置,所以不用设置setter。

                JAVA面向对象设计实例之一发牌比较大小_第20张图片

          

            在fetch的时候我们把key 值也保存下来。

                    JAVA面向对象设计实例之一发牌比较大小_第21张图片

            

        这样选手类的key值设置完成后,电脑类和用户类的key值也设置了。

        下面我们完成操作类的judge()方法,代码如下:

                JAVA面向对象设计实例之一发牌比较大小_第22张图片

            

        看逻辑也非常简单。

        对比电脑的key值与玩家的key 值,大了话“玩家输了”,小的话“玩家赢了”。

        最后调用gameover()方法.

                

        

         gameover()方法也非常简单,就是输出一句“游戏结束,欢迎使用“。

        这个游戏程序的最后,我们需要定义主类来调用,我们叫MainLei,这个名称可以自己定义。在其中只要初始化一下游戏操作类,即CaoZuo类实例化和调用其init方法即可:

          JAVA面向对象设计实例之一发牌比较大小_第23张图片

        

    至此,整个程序完成。我们可以看一下整体的程序目录结构,养成良好的结构习惯。

                 JAVA面向对象设计实例之一发牌比较大小_第24张图片

















        

你可能感兴趣的:(JAVA基础)