Bootstrap

JAVA面向对象设计实例二剪刀石头布

案例题目:

           用面向对象的思想完成

 

 

根据给定的题目进行分析:

1、       首先我们考虑需要几个类来实现,

2、       在这几个设定的类中有没有可能出现抽象类

3、       有没有出现接口来实现内容

我们可以初步判断三个类和一个主程序是显示易见的。

A、玩家类 :与电脑比拼的人 

B、电脑类 :参与游戏的智能机器人

C、游戏类:电脑和玩家工作的平台

D、主程序调用

接着再分析这几个类有哪些方法和属性

玩家类哪些行为、属性:

           根据给定的题目,很显然可以获得name和score属性。

                  name:玩家的名字

                  score:玩家的总分

方法:

             出拳:给出猜拳的数字

电脑类也很显示会出现同样的属性和方法:

属性。

                  name:玩家的名字

                  score:玩家的总分

方法:

             出拳:给出猜拳的数字

这样电脑类和玩家类都有同样的属性和方法,我们可以做出以下考虑:

1、       可不可以有一个共同的父类为他们服务

2、       父类可不可以出现共同的方法和属性

3、       父类的方法中有没有子类可能重用的代码

这样可以决定父类需不需要做成抽象类,不允许去new ,只能子类继承再去使用。

 我们可以暂时考虑一下电脑和玩害对猜拳代码的写法:

           电脑类:

ch=随机数产生1,2,3

                      Switch(ch)

case 1:

                                  println(name+“出拳:剪刀”);break;

case 2:

                                  println(name+“出拳:石头”);break;

case 3:

                                  println(name+“出拳:布”);break;

                      玩家类:

ch=用户输入的数值

                      Switch(ch)

case 1:

                                  println(name+“出拳:剪刀”);break;

case 2:

                                  println(name+“出拳:石头”);break;

case 3:

                                  println(name+“出拳:布”);break;

由上面两个类代码的大概样子,就可以得出他们是有重复代码的,完全可以通过父类完成重复代码的编写,再通过子类继承过来实现重写来完成子类需要的功能。

当父类的方法在子类中被重写时,很有可能在以后的编程过程中会同现多态的情况。这样也有利于代码的扩展。引用父类或者引用子类。既然有多态的多现,就使得父类不能成为抽象类,需要可以new来实现的。

      这样设计中就出现了多态的情况。

 

电脑类、玩家类

多态技术引入会给我们带来扩展的方便。

再加入玩家没有问题。

选手类可以new

比如cuquan(XuanShou xs);就可以实现

cuquan(new 电脑类());

cuquan(new 玩家类());

在程序体中就可以

xs.出拳

           一个函数就完成了电脑的出拳和玩家的出拳。

           再则,游戏类的考虑:

           只要我们想做游戏类,必然包含对游戏的初始化,开始游戏,判断游戏,结束游戏。这些过程是必不可少的。为了更好的规划方法,把游戏类做成接口,限定开发者的方法名称,有利于更合理地去进行代码管理。

           因此游戏类可以做成接口.

           通过以上的分析

基本结论:

1、       三个类:选手类、玩家类、电脑类

都可以new,有多态的发生

2、       游戏类:扩大化,统一规范变成接口Game

初始化init()实现的功能。New类player compute;

开始游戏:start();

游戏判定:judge();

游戏结束:  end();

      三个类一个接口

     三个类:Athlete Computer Player

一个接口:Game

分析结束后,现在我们实现代码:

      选手类:Athlete类

           先做两个私有成员变量

                

        

对这两个成员变量做getter setter方法:

点击菜单:Source--àGenerater Getters and Setters

 

就会出现对变量的选择,在两个变量上打勾:

 

 

OK后,就可以实现私有变量的getter和setter方法

 

再对Athlete做构造方法,有参与无参:

先做有参:点击ecllipse--àGenerater Constructor using Fields

 

 

出现选择的成员变量名,选择后,OK

 

 

 

有参构造函数成功。

 

拷贝产生无参构造函数:

 

为了防止此类实例对象打印不是一个堆内存地址,重写toString方法.

点击Ecllipse--àGenerate toString()

 

 

就会产生toString方法的自动重写函数:

 

然后我们可以写父类的chuquan()函数.在写函数里出现了switch(ch) ,ch 做为变量,我们如何接收,如果传参,在参数中接收,游戏类在调用这个方法时就会传参。会出现了游戏类和电脑类、玩家类之间的一种耦合关系,这种耦合也不利于游戏玩家的扩展。再添加玩家又需要游戏类处理,这样很麻烦,失去了继承后代码重用的好处。不能做参数,在类中只能做成员变量,于是成员变量就多了一个ch.

 

做成员变量ch的setter和getter方法:

 

有了ch的成员变量,Athlete的chuquan方法就有了这样的代码体:

 

 

Computer Player继承Athlete,重写出拳方法chuqu()

Super.chuquan()放在重写代码的下面

于是Player类的重写方法为:

 

 

然后实现两个类初始化的名字输入,写入代码体:

 

电脑类:

 

玩家类:

 

玩家类和电脑类基本完成。

游戏接口类:直接定义接口,然后在其中限定抽象方法:

 

 

新建TestGame类,实现这个接口:

 

TestGame类报错,需要重写定义的抽象方法:

 

上图是重写展示的部分代码。

对这五个方法重写,需要游戏中的两个主角全程参与,player和computer就是这成为这个类的成员变量了解。

也就是说TestGame类,重写方法的时候增加两个成员变量

因为每个方法都用同一个对象

Player player=new Player()

Computer comp=new Computer()

 

在游戏类的构造函数中设置代码块,目的是对游戏进行说明性文档和用户的警示语。

 

接着实现游戏类的init方法:

将玩家进行new,将电脑进行new

根据游戏流程的提示:

这里的game_continue()方法是按照游戏流程,询问用户是否继续游戏:

 

 

从流程代码中看,当用户输入y即进入到start()方法,即游戏开始的方法:

 

从游戏流程上看,在玩家出拳和电脑出拳后进入到judge环节:即判断胜负

剪刀石头布判断胜负可从以下三种方法中实现。

(1)         穷举法:

我们假定1为赢,-1为输,0为平局

玩家   剪刀        石头        布

电脑   石头(1)    剪刀(-1)    剪刀(1)

               布(-1)      布(1)            石头(-1)

                   剪刀:(0)    石头(0)     布(0)

 

这样代码变成:

 

(2)         二维数组法:

把剪刀、石头、布三项看成行和列的三项,玩家为行,电脑为列,赢了为1,平局为0,输了为-1,构成的二维数组如下:

剪刀   石头    布

剪刀      0     -1      1

石头     1      0      -1

布       -1     1      0

行:玩家 列:电脑

Int[] arr={{0,-1,1},{1,0,-1},{-1,1,0}}

这样二维数组的代码为:

(3)减值规律法

 

    剪刀石头 布

    1     2   3

    Player  computer

赢的情况:Player-comuter==1||player-computer==-2

输的情况:player-computer=-1||player-computer==2

其它情况:平局

于是代码就变成了。

    

 

根据程序输出的具体流程,玩家赢了还需要对总分进行统计,电脑赢了也需要对总分进行统计。对总分进行统计的方法都是取出总分,然后进行加值操作,玩家和电脑都继承于选手类,所以可以使用多态的方法。

    

然后在judge里面调用此方法:

最后进行end()结束方法的调用,因为有比赛次数的统计,所以加入一个成员变量sum;

 

根据game_continue()里面对sum的判断决定是否运行到end()结束方法中:

 

 

最后在end()方法中输出sum的比赛次数和最终比较的结果:

 

最后建立主程序类MainGame,运行主程序

 

至此,剪刀石头布面向对象程序基本雏形制作完毕.

代码的github地址:https://github.com/wawacode/java_stone-scissors-cloth

;