最近遇到一个保龄球记分的Game题目,回来查找了一下资料,现将代码拿出来共享。(代码的一切版权归原作者所有)
保龄球规则阐述:
保龄球是一种比赛,比赛者把一个哈密瓜大小的球顺着一条窄窄的球道朝10个木瓶投掷。
目标是要在每次投掷中击倒尽可能多的木瓶。
一局比赛由10论组成。在每轮的开始,10个木瓶都是竖立摆放的。比赛者可以投掷两次
来尝试击倒所有的木瓶。
如果比赛者在第一次投掷中就击倒了所有的木瓶,则称之为“全中”,并且本轮结束。
如果比赛者在第一次投掷中没有击倒所有的木瓶,但在第二次投掷中成功的击倒了所有剩
余的木瓶,则称之为“补中”。
一轮中第二次投掷后,即使还有没有被击倒的木瓶,本轮也宣告结束。
全中轮的记分规则为:10,加上接下来的两次投掷击倒的木瓶数,再加上前一轮的得分。
补中轮的记分规则为:10,加上接下来的一次投掷击倒的木瓶数,再加上前一轮得分。
其他论的记分规则为:本轮中两次投掷所击倒的木瓶数,加上前一轮的得分。
如果第10轮为全中,那么比赛者可以再多投掷两次,以完成对全中的记分。
同样,如果第10轮为补中,那么比赛者可以再多投掷一次,已完成对补中的记分。
因此,第10轮可以包含3次掷球而不是2次。
----------------------------------------------------
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();
//计算得分类 }
-----------------------------------------------------
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;
}
本文转自xudayu 51CTO博客,原文链接:http://blog.51cto.com/xudayu/84365,如需转载请自行联系原作者