`

善用表驱动法

阅读更多

    最近碰到个需求,计算游戏得分的规则,类似这样:

游戏人数

第一名获得赌注

第二名获得赌注

第三名获得赌注

第四名获得赌注

二人

100%

0%

二人 (出现 2 个第 1 名时)

50%

50%

 

 

三人

70%

30%

0%

三人 出现 3 个第 1 名时

33.3333%

33.3333%

33.3333%

 

三人 ( 出现 2 个第 1 名时 )

50% × 2

0%

 

 

......
......
    这些奖励规则没有什么规律,随着人数增多,就越发复杂了,并且业务人员可能随时改变这些规则。
    显然,奖励规则可以采用策略模式,定义策略接口,根据游戏人数定义不同的规则,本质上就是利用动态的多态调用。可以想见,还是少不了复杂的case... when语句,以及繁多的代码。恰好最近读《unix编程艺术》和《代码大全2》,两者都提到一个结论:人类阅读复杂数据结构远比复杂的控制流程容易,或 者说数据驱动开发是非常有价值的。《代码大全2》声称这个是表驱动法。因此,这个奖励系数的计算,能否转化成一个查表过程呢?注意到,在游戏中,名次是根 据个人的积分在所有玩家中的排位来决定,大概会有这么个排序的玩家积分数组[100,50,3],这个数组表示3个玩家,第一名100分,第二名50分, 第三名才3分。依据规则,第一名的奖励系数就是0.7,第二名就是0.3。我想到类似这样的数组其实都有个形式表示它们的内置结构,比如 [100,50,3]数组的“结构”是"111",代表3个位置都有一个人。将"111"作为关键码去查表不就OK了?
    将每个排好序的积分数组解码为这样的关键码,然后去查预先写好的奖励系数表,这个奖励系数表大概类似:

  @@award_rate_hash={
    :"2"=>{
      :"11"=>{:"1"=>1,:"2"=>0},
      :"20"=>{:"1"=>0.5,:"2"=>0.5}
    },
    :"3"=>{
      :"111"=>{:"1"=>0.7,:"2"=>0.3,:"3"=>0},
      :"300"=>{:"1"=>0.33},
      :"201"=>{:"1"=>0.5,:"3"=>0},
      :"120"=>{:"1"=>1,:"2"=>0}
    },
    :"4"=>{
      :"1111"=>{:"1"=>0.65,:"2"=>0.30,:"3"=>0.05,:"4"=>0},
      :"4000"=>{:"1"=>0.25},
      :"3001"=>{:"1"=>0.33,:"4"=>0},
      :"1300"=>{:"1"=>1,:"2"=>0},
      :"2020"=>{:"1"=>0.5,:"3"=>0},
      :"1201"=>{:"1"=>0.7,:"2"=>0.15,:"4"=>0},
      :"1120"=>{:"1"=>0.7,:"2"=>0.3,:"3"=>0},
      :"2011"=>{:"1"=>0.35,:"3"=>0.3,:"4"=>0}
    }      
  }
 

    一个三级hash表,首先根据玩家人数查到特定的系数表,比如要查3个玩家、积分数组是[100,50,3]的奖励系数表就是  @@award_rate_hash [:"3"],然后积分数组 [100,50,3]解码为:"111",继续查,如此规则的奖励系数表就是 @@award_rate_hash [:"3"][ :"111"]——也就是 {: " 1 " => 0.7 ,: " 2 " => 0.3 ,: " 3 " => 0},那么查积分是100的玩家系数就是 @@award_rate_hash [:"3"][ :"111"][ ([100,50,3].index(100)+1).to_s.to_sym],也就是 : " 1 " => 0.7 [100,50,3].index(100)+1就是积分100的玩家在数组中的名次(即1),也就是:"1"指向的结果0.7 。其他玩家的查表过程与此类似,不细说了。
    这样,我们所有的奖励规则就是维护这么一张hash表,这个表看起来复杂,其实完全可以自动生成,让业务人员来提供样例数据,解码样例数据并生成这个表是很简单的事情。积分数组的“解码”,我给一个Ruby版本:

 

  #解码数组为字符串关键码
  def decode_array(array)
    len=array.size
    trace_list=[]
    result=[]
    len.times do |time|
      result[time]=0   
      trace_list[time]=false
    end
    array.each_with_index do |item,index|
      result[index]=count_times(array,trace_list,index,len)
    end
    return result.join('').to_sym
  end
  def count_times(array,trace_list,index,len)
    item=array[index]
    result=0
     (index..len).each do |i|
      if array[i]==item and !trace_list[i]
        result+=1
        trace_list[i]=true
      end
    end
    return result
  end
 
5
2
分享到:
评论
3 楼 fhqllt 2012-09-29  
代码大全 把表驱动做为 重要的一块讲解,但是楼主这个 应用场合很符合。
2 楼 yuanman2002 2008-04-18  
很受启发。
1 楼 yuanman2002 2008-04-18  

相关推荐

    善用教法,打造Auto CAD实效课堂.pdf

    针对这一问题,有经验的教师提出了一系列教学方法,其中“任务驱动教学法”和“项目教学法”是两种以学生为主体的学习教学方法。 任务驱动教学法的核心在于提出具有实际意义的教学任务,这些任务要符合学生的认知...

    教学体会-善用时序图编制PLC程序.pptx

    "教学体会-善用时序图编制PLC程序" 本资源是关于使用时序图编制PLC程序的教学体会,共二十二页。主要讲解了如何使用时序图设计PLC程序,包括风机顺序控制、机床动力头运行控制等实例。 首先,课程简介中提到,时序...

    生物法壳聚糖行业(2021-2026)企业市场突围战略分析与建议.docx

    企业应充分利用新闻、事件营销等低成本传播工具,借助优秀的品牌视觉设计吸引消费者眼球,同时善用网络营销手段,如社交媒体和搜索引擎优化,扩大品牌知名度。 面对竞争对手,企业应密切关注其动态,及时调整策略以...

    人力资源管理(劳动关系管理).zip

    在这个以互联网为驱动的时代,劳动关系的管理方式正经历着前所未有的变革。本资料《人力资源管理(劳动关系管理).pptx》将深入探讨这一主题,帮助我们理解如何在数字化背景下有效处理劳动关系。 一、劳动关系概述 ...

    STM32-Keil-pack.zip

    STM32是意法半导体(STMicroelectronics)推出的一系列基于ARM Cortex-M内核的微控制器,广泛应用于嵌入式系统、物联网设备、消费电子产品等领域。 Keil是著名的嵌入式系统开发工具,提供了MDK(Microcontroller ...

    创新思维训练课件(PPT 50页).pptx

    因此,课程提供了一些策略,如磁盘驱动器的案例分析,来引导学员反思和改变自己的思维模式。 此外,奖惩分析法作为一种实用工具,可以帮助识别阻碍创新的因素,即惩罚因子,以及推动创新的动力,即奖励因子。通过对...

    数据十诫(车品觉)

    这一点在当今数据驱动的时代尤为重要,因为人们很容易被大量的数据和复杂的技术手段所迷惑,而忽略了数据的核心价值。车品觉提倡用“对比/细分/溯源”这六个字作为数据处理的真言,指引我们在数据处理过程中应该遵循...

    电商时代背景下新疆干果营销的机遇与营销对策分析.zip

    9. 法规遵循:电商经营涉及诸多法规,如食品安全法、电子商务法等,企业需合规经营,确保产品安全,维护消费者权益。 10. 持续创新:电商市场变化快速,新疆干果企业需持续创新,适应消费者需求变化,开发新产品,...

    微博电商营销行业报告-卓尔数科-202011精品报告2020.pdf

    通过研究其他品牌的成功营销案例,品牌主可以学习和借鉴其策略玩法、创意内容和互动方式,以便更好地制定自己的微博电商营销策略。 综上所述,电商营销正在经历着由移动端增长、品牌营销预算转移、社交电商的兴起...

    信息化教学大赛培训班心得体会.docx

    引入视频情境,生动讲解新知识,再结合任务驱动或项目法解决实际问题,以及运用拓展和深化的方法来巩固知识,这种教学模式使得教学过程既有趣又富有成效。这种方法适用于各种课程,因为它能引导学生主动参与,提高...

    创新思维 超越自我 追求卓越 开创会计行业大发展的灿烂前程.doc

    【创新思维】在会计行业...综上所述,会计行业的发展需要创新思维的驱动,要求从业者超越自我,追求卓越,并善用现代信息技术来提升管理效能。只有这样,才能在激烈的竞争中立于不败之地,开创会计行业更加灿烂的未来。

    《大学生创业基础》期末考试100分全对文档.docx

    7. **创业行为驱动力**:创业行为主要由创业者的动机驱动,如对市场机会的识别、个人愿景和目标追求。 8. **未来生活趋势**:社会老龄化、宅男宅女增多、移动互联网的普及是未来的趋势,而强调群众化并不一定是错误...

    高职生英语自学能力培养研究.doc

    1. 学生自主学习意识不强:学生在英语学习中缺乏自我驱动,往往依赖教师的引导,未能意识到自己是学习的主导者。这需要教师引导学生认识到自我学习的重要性,培养他们的学习自觉性。 2. 学习计划性差:有效的学习...

    新时代数字传播内容营销方案.ppt

    总结来说,这份营销策划方案强调了在新时代背景下,品牌必须深入理解消费者,善用新媒体平台,运用数据和技术进行创新营销,以建立强大的品牌内核,实现与消费者的深度连接。同时,品牌应积极探索品效合一的营销策略...

    中考政治总复习.docx

    - **考点四:自强对人生的作用**:分析自强精神如何驱动个人进步,克服困难。 - **考点五:培养自强精神**:提供培养自强精神的具体策略和方法。 3. **学法用法 自我保护** - **考点一:正确认识身边的诱惑**:...

    3分钟看懂Python后端必须知道的Django的信号机制

    这种机制类似于事件驱动编程,使得开发者能够响应模型、请求/响应周期以及数据库操作等关键点上的事件。 首先,理解Django信号机制的三个基本元素: 1. 发送者(Senders):触发信号的实体,通常是Django的某些内...

    如何利用Oracle命令解决函数运行错误

    总之,解决Oracle函数运行错误需要深入理解异常处理机制,善用`DBMS_OUTPUT`进行调试,并检查函数的逻辑、输入参数、数据库配置以及可能的环境差异。通过逐步排除法,我们通常能找到问题所在并修复它。在实际操作中...

    Java心得 学JAVA必看

    可以使用番茄工作法等时间管理技巧来提高工作效率;同时,也要学会放松自己,保持良好的身心状态,这样才能更好地面对挑战。 #### 10. 养成写博客的习惯 将学习过程中的心得体验、遇到的问题及解决方法记录下来,并...

Global site tag (gtag.js) - Google Analytics