葡京抽卡系统升级版——面向对象思想

引言

对于我之前关于抽卡系统的描述,大家可能会感到疑惑,并且认为这样单线程一股脑解决方式思路过于呆板,接下来我们讲解一下如何用面向对象的方式对该题进行解答。(有不知道扑克牌比较方式的读者可以看一下之前的抽卡系统)
在写之前,我们要明白面向对象的特征是什么。

初识面向对象

面向对象设计最为典型的三个特征便是封装、继承、多态,

  • 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。
  • 继承,它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。
  • 多态,允许将子类类型的指针赋值给父类类型的指针。

今天我们所利用到的主要思想就是封装,那么如何进行封装呢?

封装方法

为了让大家更好的明白和理解封装方法,我从两种角度为大家展开

  • 题目解析以及逻辑拆分
    我们现在将自己带入一张牌局,你和你的一个朋友在玩一个比较牌大小的游戏。这时一个美女荷官从52张牌中随机发给你们两个人一张牌,这时你们看完自己发的牌后互相比较,最后结果要么是你比你朋友的大,你获得了牌局的胜利,要么是他比你大。

现在我们分析这个事件的主要“人物”——你、你的朋友、荷官、52张扑克牌。你和你的朋友是参与者player,而荷官则是管理和发牌的人PokerManager,然而我们为了让荷官获得每张牌的信息,所以我们需要为52张牌获得应有的属性——数字和花色,然后将这52张牌的属性统统交给荷官,然后由荷官随机抽取这52张牌的两张牌。
大概思路我们从通俗的方式进行了讲解,下面我们从UML图的方式进行讲解。

image.png

  • UML解释
    PokerNumber和PokerSuit则是Poker的两个必要属性,因为每一张牌的属性不同,所以我们必须单独对两个属性进行描述,而不是直接在Poker里面进行添加属性。然后我们在PokerManager里面创建一个专门储存在pokers这个数组里面。必要的Poker所包含的比较方法以及PokerManager中的抽牌方法我们在具体代码中进行描述。

代码分析

  • Poker组成属性
  1. PokerNumber
public class Pokernumber {
      public String number;
      public int tag;
      public Pokernumber(String number, int tag) {
            this.number = number;
            this.tag = tag;
      }
}

2,PokerSuit

public class Pokersuit {
    public String suit;
    public int tag;

    public Pokersuit(String suit, int tag) {
        this.suit = suit;
        this.tag = tag;
    }
}
  • Poker
public class Poker {
    Pokernumber numberObj;
    Pokersuit suitObj;
    public Poker(Pokernumber numberObj, Pokersuit suitObj) {
        this.numberObj = numberObj;
        this.suitObj = suitObj;
    }
    public Poker() {}
    public boolean compare(Poker other)
    {
        boolean result=true;
        if (this.numberObj.tag == other.numberObj.tag)//点数相同比较花色
        {
            result=this.suitObj.tag > other.suitObj.tag;//利用result返回条件判断结果
        } else {
           result= this.numberObj.tag > other.numberObj.tag;
        }
        return result;
    }
}
  • 荷官 PokerManager
import java.util.ArrayList;
import java.util.Random;
public class PokerManager {
    ArrayList<Poker>pokers=new ArrayList<>() ;  //为Arraylist开辟空间防止调用时出现无空间情况
    String []numbers= {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
    String []suits= {"♦","♣","❤","♠"};
    PokerManager(){
        for (int i = 0; i < numbers.length; i++) {
            for (int s = 0; s < suits.length; s++) {
                pokers.add(new Poker(new Pokernumber(numbers[i],i), new Pokersuit(suits[s],s)));
                //傻瓜做法
//                Poker p1 = new Poker();
//                p1.numberObj=new Pokernumber(numbers[i],i);
//                p1.suitObj=new Pokersuit(suits[s],s) ;
//                pokers.add(p1);
            }
        }
    }
    public Poker getPoker()
    {
      Random rd=new Random();
      int index=rd.nextInt(pokers.size());
      pokers.remove(index);
      return pokers.get(index);
    }
}
  • 抽牌测试
public class Test {
    public static void main(String[] args) {
        PokerManager Person1=new PokerManager();
        Poker p1=Person1.getPoker();
        Poker p2=Person1.getPoker();
        if(p1.compare(p2))
        {
            System.out.println(p1.numberObj.number+p1.suitObj.suit+">"+p2.numberObj.number+p2.suitObj.suit);
        }
        else {
            System.out.println(p1.numberObj.number+p1.suitObj.suit+"<"+p2.numberObj.number+p2.suitObj.suit);
        }
    }
}

对于我们使用的牌的比较方法可以参考我之前博客https://www.jianshu.com/p/6b70d5a3d0ac
这里我简单描述一下——就是通过自定义字符串集合来规定每一个数或者花色的大小顺序,比较则是比较每个字符串的下标大小。

为什么使用Arraylist

看过之前博客的同学可以看到我之前并没有使用Arraylist这种集合的方式来进行52张牌的存储,而是直接随机抽取,并判断,但是实际上这是并不高效的,并且每一次的条件判断会严重影响程序的真实性——因为我们的实际场景是从52张牌中获得两张牌,而之前的做法相当于从两副牌中抽取分别抽取两张牌,抽取后判断是否相等,这样显然是不符合题意的,因为我们是从一副牌中抽取两张牌的。所以我们用集合的方式储存52张Pokers,并且用remove的方式来解决出现同一张牌——其实跟现实生活中一样,抽取一张牌后,这张牌就会从荷官所管理的一副牌,取出所以我们调用pokers.remove()取出那张牌。

有兴趣的读者可以看一下这个程序的Kotlin版本

  • Poker属性
  1. PokerNumber
- PokerNumber
package KotlinPoker
//点数
class PokerNumber constructor(val number:String,
                              val tag:Int){

}
  1. KotlinPoker
package KotlinPoker
//花色
class PokerSuit constructor(val suit:String,val tag:Int) {
}

3.Poker

class Poker (val numberObj: PokerNumber, val suiObj:PokerSuit) {
    fun compareTo(other: Poker)=
         if (this.numberObj.tag == other.numberObj.tag)//点数相同比较花色
        {
            this.suiObj.tag > other.suiObj.tag
        } else {
            this.numberObj.tag > other.numberObj.tag
        }
    }
  • PokerManager
import kotlin.random.Random

class PokerManager {
    val pokers:ArrayList<Poker> = arrayListOf();
    //点数数组
    val numbers= arrayOf("3","4","5","6","7","8","9","10","J","Q","K","A","2")
    val suis= arrayOf("♦","♣","❤","♠")
    init {
      for((i,number) in numbers.withIndex())
      {
          for((j,suit) in suis.withIndex())
          {
              pokers.add(Poker(PokerNumber(number,i), PokerSuit(suit,j)))
          }
      }
    }
    //获取一张扑克牌
    fun getPoker():Poker{
//        val index= Random.nextInt(pokers.size)
//        val poker=pokers[index]
//        pokers.removeAt(index)
//        return poker
        Random.nextInt(pokers.size).also {
            pokers[it].apply {
                pokers.remove(this)
                return this
            }
        }
    }
}
  • 测试抽牌
fun main() {
    PokerManager().apply {
        val poker1=getPoker()
        val poker2=getPoker()
        val result=poker1.compareTo(poker2)
        if(result)
        {
            println("${poker1.numberObj.number}${poker1.suiObj.suit}>"+"${poker2.numberObj.number}${poker2.suiObj.suit}")
        }
        else{
            println("${poker1.numberObj.number}${poker1.suiObj.suit}<"+"${poker2.numberObj.number}${poker2.suiObj.suit}")
        }
    }
}

总结

学习面向对象的方式,并且理解题目事件、“人物”,并理解其关联十分重要,面向对象的设计在某种程度上能够让整个程序的逻辑性更强、比面向过程的程序更加的模块化,为了更加理解每个类的关系,我强烈建议认真学习画UML图,这一定会是你编程路上的一个十分实用的工具。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,527评论 5 470
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,314评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,535评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,006评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,961评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,220评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,664评论 3 392
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,351评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,481评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,397评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,443评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,123评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,713评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,801评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,010评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,494评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,075评论 2 341

推荐阅读更多精彩内容

  • “上帝创造了人,并给了人思想,而思想是决定万物的根本尺度” ——引 面向对象的概念 面向对象指面向客观规律之间的...
    丶legend阅读 1,654评论 1 11
  • 第一部分 用特殊方法实现Python风格的类 为了实现更好的可扩展性,Python语言提供了大量的特殊方法,它们大...
    VictorChi阅读 438评论 0 0
  • java面向对象の初体验之扑克牌小Demo 在初学java之时听到最多的就是面向对象编程,什么是面向对象呢?和c语...
    Nicely阅读 521评论 0 1
  • 1.1.类和对象 1.1.1.万物皆对象 分类是人们认识世界的一个很自然的过程,在日常生活中会不自觉地将对象进行分...
    Rolle_Wang阅读 711评论 0 0
  • 类和对象 万物皆对象 分类是人们认识世界的一个很自然的过程,在日常生活中会不自觉地将对象进行进行分类 对象归类 类...
    __method__阅读 208评论 0 0