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

引言

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

初识面向对象

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

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

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

封装方法

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

  • 题目解析以及逻辑拆分
    我们现在将自己带入一张牌局,你和你的一个朋友在玩一个比较牌大小的游戏。这时一个美女荷官从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图,这一定会是你编程路上的一个十分实用的工具。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

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