Java实现Blackjack程序添加split分牌功能需重写代码问题咨询
现有代码的核心设计缺陷
- 完全依赖静态全局变量存储状态:所有游戏状态绑定在
BlackJack类的静态属性上,仅支持存储单副手牌的相关数据,你预先定义的playerCards2~6本质是硬编码补丁,无法动态适配分牌后可变的手牌数量,逻辑复用率为0。 - 操作方法和全局状态强耦合:
hit()、stand()、doubleDown()等操作方法都是直接修改全局的玩家手牌、分数变量,无法指定操作目标,分牌后生成的多副手牌完全无法调用现有逻辑。 - 状态碎片化:单副手牌的关联属性(牌组、分数、赌注、状态标记)散落在不同的全局变量中,没有统一封装,修改时很容易出现状态不一致的bug,比如你现在的
reScore()就是为了补救同步问题额外加的逻辑。 - 扩展性极差:除了分牌功能无法实现外,后续如果要加多玩家、规则自定义、多副牌靴等功能都需要全部推翻重写。
合理的21点程序结构设计
按面向对象的封装原则拆分职责,每个类只负责自己相关的逻辑和状态:
1. 手牌类(Hand)
封装单副手牌的所有属性和操作,是支持分牌的核心:
- 属性:
- 私有牌组列表
private List<Card> cards - 当前手牌的赌注
private int bet - 状态标记:是否停牌、是否投降、是否 blackjack
- 私有牌组列表
- 方法:
void addCard(Card card):给当前手牌加牌int getScore():把你现有计算分数的逻辑挪到这里,直接返回当前手牌的分数boolean isBust():判断当前手牌是否爆牌boolean canSplit():判断当前手牌是否满足分牌条件(只有两张牌且面值相同)
2. 玩家类(Player)
封装玩家的资产和所有手牌:
- 属性:
- 筹码余额
private int bankroll - 手牌列表
private List<Hand> hands,分牌时直接往这个列表里加新的Hand对象即可,支持任意数量的分牌
- 筹码余额
- 方法:筹码增减、添加/移除手牌等通用操作
3. 庄家类(Dealer)
封装庄家的逻辑:
- 属性:庄家只有一副手牌
private Hand hand - 方法:把你现有stand方法里的庄家自动摸牌逻辑(摸牌到不小于17点)挪到这里
4. 牌堆类(CardDeck)
你现有逻辑基本可用,只需要优化封装:
- 内部维护发牌指针,不用暴露给外部,新增
Card nextCard()方法,直接返回下一张要发的牌,不用外部维护全局index变量
5. 游戏主类(BlackJackGame)
调度整个游戏流程:
- 属性:持有牌堆、玩家、庄家、输入Scanner的实例
- 核心流程方法:
- 开局初始化:初始化玩家筹码、洗牌
- 回合开始:清空上回合手牌,给玩家和庄家各发两张牌
- 玩家操作处理:遍历玩家的每副手牌,依次询问操作:
- hit:调用当前手牌的
addCard()发一张牌 - stand:标记当前手牌停牌
- split:校验当前手牌
canSplit()为true、玩家余额够额外一份赌注,就把当前手牌拆成两个Hand对象,各押一份等额赌注,分别发一张新牌加入玩家的手牌列表 - doubleDown、surrender对应修改当前手牌的状态和赌注即可
- hit:调用当前手牌的
- 庄家回合:调用庄家的自动摸牌逻辑
- 结算:遍历玩家所有手牌,分别和庄家手牌比大小,计算输赢修改玩家筹码
按这个结构重构后,所有单副手牌的逻辑都可以复用,不需要反复重写,分牌功能只需要加个拆分手牌的逻辑即可实现。
内容的提问来源于stack exchange,提问作者zezpwn44
相关产品推荐
相关产品推荐

