再探设计模式之状态模式(纸牌游戏的开发)

状态模式主要用于检测和切换状态,其中细节对客户端是透明的,自动完成检测和状态的切换,常用的场景是公文的流转和游戏中角色的升级,在设计开始时role并没有play方法,只有check方法,check方法中需要将每一次的筹码写死在客户端,这显然不符合游戏的场景,所以在后面改造的过程中增加了一个play方法从控制台读入每次进行纸牌的筹码大小,整个设计还用到了模版方法模式,在设计等级的玩法时通过模版方法,具体角色重写抽象模版的值做到反向的控制


package com.linewell.modeldesign.state

import scala.util.Random

/**  * 某软件公司欲开发一款纸牌游戏软件,在该软件中用户角色具有入门级、熟练级、高手级和骨灰级  * 角色的等级和积分对应,游戏胜利增加积分,游戏失败扣除积分  * 入门级具有最基本的功能play() 0 - 20  * 熟练级在呢家了游戏胜利积分加倍功能doubleScore() 20 -40  * 高手级在熟练级的基础上增加了换牌的功能changeCards() 40 -80  * 骨灰级在高手级的基础上增加了偷看系统牌的机会peekCards() 80  *  * Created by ctao on 2015/9/3.  */  /**  * 环境类  * @param score 积分  * @param level 等级  */ case class Role(var score: Double = 1, var level: Level = null) {
    /**  * 自己可交换的牌  */  var visibleCard = 0
    /**  * 自己不可交换的牌  */  var invisibleCard = 0
    /**  * 系统可交换的牌  */  var systemVisibleCard = 0
    /**  * 系统不可交换的牌  */  var systemInvisibleCard = 0

    /**  * 设置初始等级  */  level = Primary(this)

    /**  * 进行赌博游戏,从控制台读入数据  */  private def check(point: Double): Unit = {

        /**  * 初始化牌组  */  initCard()

        /**  * 检测状态  */  checkState()


        println(s"自己的可交换牌${visibleCard}自己的不可交换牌${invisibleCard}系统的可交换牌${systemVisibleCard}系统不可交换牌$systemInvisibleCard")

        /**  * 选择等级对应的玩法  */  level.play(point)


    }

    /**  * 检测状态,如果积分在0-20则将level设置为入门级  * 如果积分在20-40则将level设置为熟练级  * 如果积分在40-80则将level设置为高手级  * 如果积分在80以上在将level设置为骨灰级  */  private def checkState(): Unit = score match {
        case s if s >= 0 && s < 20 => level = Primary(this)
        case s if s >= 20 && s < 40 => level = Secondary(this)
        case s if s >= 40 && s < 80 => level = Professional(this)
        case s if s >= 80 => level = Final(this)
    }

    /**  * 初始化牌,每一次play的时候洗牌  */  private def initCard(): Unit = {
        visibleCard = Random.nextInt(10)
        invisibleCard = Random.nextInt(10)
        systemVisibleCard = Random.nextInt(10)
        systemInvisibleCard = Random.nextInt(10)
    }

    /**  * 模版方法  * 玩游戏,从控制台读入  */  def play(): Unit = {
        println(s"当前积分为$score,请输入您本次游戏的筹码,0退出本游戏")
        var point = io.StdIn.readDouble()
        while (point != 0) {
            check(point)
            println(s"当前积分为$score,请输入您本次游戏的筹码,0退出本游戏")
            point = io.StdIn.readDouble()
        }
        println("感谢您的使用,下次再见")
    }
}




package com.linewell.modeldesign.state

import scala.util.Random

/**  * 等级,抽象状态  * Created by ctao on 2015/9/3.  */ sealed abstract class Level(role: Role) {
    /**  * 是否翻倍  */  var isDoubleScore = false   /**  * 是否偷看别人牌  */  var isPeekCard = false   /**  * 是否交换牌  */  var isChangeCard = false    /**  * 玩牌,模版方法  * @param point 押注大小  */  def play(point: Double) = {
        /**  * 先判断是否看对方牌  */  isPeekCard match {
            case true => peekCards()
            case false => isChangeCard match {
                /**  * 判断是否交换牌  */  case true => changeCards()
                case false =>
            }
        }

        /**  * 筹码如果大于积分,则积分不够,如果筹码小于0,则输出筹码不够  * 进入游戏  * 判断自己的可交换牌和自己不可交换牌之和与系统可交换牌与不可交换牌之和的大小  * 如果大则胜出,如果有翻倍卡,则筹码*2加到自己积分上  * 如果小则输掉,则积分减去本次筹码  */  point match {
            case p if p > role.score => println("积分不够")
            case p if p < 0 => println("请选择大于0的筹码")
            case _ => println("玩纸牌游戏")
                if ((role.systemInvisibleCard + role.systemVisibleCard) > (role.invisibleCard + role.visibleCard)) {
                    role.score -= point
                    println(s"你输了您现在还有${role.score}积分")

                } else {
                    print("你赢了")
                    if (isDoubleScore) {
                        doubleScore(point)
                    } else {
                        role.score += point
                    }
                    println(s"您现在还有${role.score}积分")
                }
        }

    }


    /**  * 筹码翻倍方法  * @param point 筹码  */  private def doubleScore(point: Double): Unit = {
        println("筹码翻倍")
        role.score += (point * 2)
    }

    /**  * 交换手牌  */  private def changeCards() = {
        role.visibleCard = role.systemVisibleCard + role.visibleCard  role.systemVisibleCard = role.visibleCard - role.systemVisibleCard  role.visibleCard = role.visibleCard - role.systemVisibleCard  println("换牌")
        println(s"交换后自己的可交换牌${role.visibleCard}自己的不可交换牌${role.invisibleCard}系统的可交换牌${role.systemVisibleCard}系统不可交换牌${role.systemInvisibleCard}")
    }

    /**  * 偷看系统可交换牌  * 如果自己可交换牌小于系统的,则交换  */  private def peekCards(): Unit = {
        println("偷看系统的牌")
        if (role.systemVisibleCard > role.visibleCard) {
            changeCards()
        }
    }

}


/**  * 入门级  * @param role 角色  */ case class Primary(role: Role) extends Level(role)

/**  * 熟练级  * @param role 角色  */ case class Secondary(role: Role) extends Level(role) {
    /**  * 积分翻倍  */  isDoubleScore = true }

/**  * 高手级  * @param role 角色  */ case class Professional(role: Role) extends Level(role) {
    /**  * 积分翻倍  */  isDoubleScore = true   /**  * 换牌  */  isChangeCard = Random.nextBoolean()
}

/**  * 骨灰级  * @param role 角色  */ case class Final(role: Role) extends Level(role) {
    /**  * 积分翻倍  */  isDoubleScore = true   /**  * 换牌  */  isChangeCard = true   /**  * 偷看系统牌  */  isPeekCard = true }


package com.linewell.modeldesign.state

/**  * 状态模式测试客户端  * Created by ctao on 2015/9/4.  */ object Client extends App {
    val role = Role(40)
    role play()



}

你可能感兴趣的:(再探设计模式之状态模式(纸牌游戏的开发))