最近遇到一个保龄球记分的Game题目,回来查找了一下资料,现将代码拿出来共享。(代码的一切版权归原作者所有)
    
        题目:
 
 保龄球规则阐述:
 保龄球是一种比赛,比赛者把一个哈密瓜大小的球顺着一条窄窄的球道朝10个木瓶投掷。
 目标是要在每次投掷中击倒尽可能多的木瓶。
 
  一局比赛由10论组成。在每轮的开始,10个木瓶都是竖立摆放的。比赛者可以投掷两次
来尝试击倒所有的木瓶。
 
如果比赛者在第一次投掷中就击倒了所有的木瓶,则称之为“全中”,并且本轮结束。

如果比赛者在第一次投掷中没有击倒所有的木瓶,但在第二次投掷中成功的击倒了所有剩
余的木瓶,则称之为“补中”。
一轮中第二次投掷后,即使还有没有被击倒的木瓶,本轮也宣告结束。

全中轮的记分规则为:10,加上接下来的两次投掷击倒的木瓶数,再加上前一轮的得分。
补中轮的记分规则为:10,加上接下来的一次投掷击倒的木瓶数,再加上前一轮得分。
其他论的记分规则为:本轮中两次投掷所击倒的木瓶数,加上前一轮的得分。
 
如果第10轮为全中,那么比赛者可以再多投掷两次,以完成对全中的记分。
 同样,如果第10轮为补中,那么比赛者可以再多投掷一次,已完成对补中的记分。
因此,第10轮可以包含3次掷球而不是2次。

实现:
Game.java
----------------------------------------------------
package com.test.demo;  
/**  
* 保龄球游戏记分Game  
*  
* @author xudayu  
* 2008年6月27日  
*/
  
public class Game {  
  
public static void main(String[] args) {  
    
  Game g = new Game();  
    
  g.add(1);  
  g.add(4); //第一次结束  
  g.add(4);  
  g.add(5); //第二次结束  
  g.add(6);  
  g.add(4); //第三次结束  
  g.add(5);  
  g.add(5); //第四次结束  
  g.add(10); //第五次结束  
  g.add(0);  
  g.add(1); //第六次结束  
  g.add(7);  
  g.add(3); //第七次结束  
  g.add(6);  
  g.add(4); //第八次结束  
  g.add(10); //第九次结束  
  g.add(2);  
  g.add(8);  
  g.add(6); //第十次结束  
    
   for ( int j = 1; j < 11; j++) {  
      System.out.println( "第"+j+ "轮的得分是:"+g.scoreForFrame(j));  
  }  
    
}  
  
     /**  
  * 返回此轮得分  
  * @return  
  */
  
     public int score(){  
   return scoreForFrame(itsCurrentFrame);  
    }  
  
     /**  
  * 添加本轮没次投掷的得分,存入记分类  
  * 并且调整轮数  
  * @param pins int 分数  
  */
  
     public void add( int pins){  
  itsScorer.addThrow(pins);  
  adjustCurrentFrame(pins);  
    }  
  
     /**  
  * 最后一次投掷后,调整轮数,否则将本轮第一次投掷(firstThrowInFrame)设为false  
  * @param pins  
  */
  
     private void adjustCurrentFrame( int pins){  
   if (lastBallInFrame(pins)) //本轮最后一次投掷,调整轮数  
      advanceFrame();  
   else  
      firstThrowInFrame = false;  
    }  
  
     /**  
  * 判断本轮最后一次投掷,false不是最后一次,true是最后一次  
  * @param pins 得分  
  * @return boolean  
  */
  
     private boolean lastBallInFrame( int pins){  
   return stricke(pins)||!firstThrowInFrame;  
    }  
  
     /**  
  * 本轮第一次是否全中  
  * @param pins 得分  
  * @return boolean  
  */
  
     private boolean stricke( int pins){  
   return (firstThrowInFrame && pins == 10);  
    }  
  
     /**  
  * 改变轮数  
  * (第一轮itsCurrentFrame==1,  
  * 完成第一轮后,itsCurrentFrame==2  
  * ,一次类推,直到第10轮)  
  */
  
     private void advanceFrame(){  
   //Math.min(int,int)返回两个×××中最小的一个int  
  itsCurrentFrame = Math.min(10, itsCurrentFrame + 1);  
    }  
  
     /**  
  * 计算本轮投掷得分  
  * @param theFrame 轮数  
  * @return int 本轮得分  
  */
  
     public int scoreForFrame( int theFrame){  
   return itsScorer.scoreForFrame(theFrame);  
    }  
  
     private int itsCurrentFrame = 0; //当前轮数  
     private boolean firstThrowInFrame = true; //本轮第一次投掷  
     private Scorer itsScorer = new Scorer(); //计算得分类  
}
 
Scorer.java类
-----------------------------------------------------
package com.test.demo;
/**
* 计算保龄球每轮得分
* @author xudayu
* 2008年6月27日
*/

public class Scorer {
  
     /**
  * 投掷次数与投掷分数赋值
  * @param pins 投掷分数
  */

     public void addThrow( int pins){
  itsThrows[itsCurrentThrow++]=pins;
    }
  
     /**
  * 计算本轮得分
  * @param theFrame
  * @return
  */

     public int scoreForFrame( int theFrame){
  ball = 0;
   int score = 0;
   for ( int currentFrame = 0; currentFrame < theFrame; currentFrame++) {
       if (strike()) { //第一次投掷全中,加上后两次投掷的得分
    score += 10 + nextTwoBallsForStrike();
    ball++;
      } else if(spare()){ //第二次投掷补中,加上后一次投掷的得分
    score += 10 + nextBallForSpare();
    ball+=2;
      } else { //普通情况,2次投掷相加
    score += twoBallsInFrame();
    ball+=2;
      }
  }
  
   return score;
    }
  
     //第一次全中,本轮第一次全中
     private boolean strike(){
   return itsThrows[ball] == 10;
    }
  
     //第二次投掷,补中情况
     private boolean spare(){
   return (itsThrows[ball] + itsThrows[ball + 1]) == 10;
    }
  
     //返回本轮后两次的得分
     private int nextTwoBallsForStrike(){
   return itsThrows[ball +1]+itsThrows[ball+2];
    }
  
     //返回本轮后一次的得分
     private int nextBallForSpare(){
   return itsThrows[ball +2];
    }
  
     //返回不同的本轮2次投掷得分
     private int twoBallsInFrame(){
   return itsThrows[ball]+itsThrows[ball+1];
    }
  
     private int ball; //投掷次数
     private int[] itsThrows = new int[21]; //10轮所投掷的次数数组
     private int itsCurrentThrow =  0;
}
 
完毕!