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