问题描述
写一个十瓶保龄球游戏计分程序
输入:字符串(下面描述)表示的一局保龄球游戏
输出:整数的分数
评分规则:
每场比赛,投球手有十个回合。
在每一回合中,投球手有两次机会击倒所有的十个瓶子。
如果一回合中的第一个球击倒了所有的十个瓶子,这被称为“strike”。回合结束。该回合的得分是10加上在接下来的两个球中击倒的瓶的总数。
如果一回合中的第二个球击倒了所有的十个瓶子,这被称为“spare”。回合结束。该回合的得分是10加上在下一个球中击倒的瓶数。
如果在两个球之后,10个瓶中至少还有一个(没有全部被击倒),那么这一回合的分数就是这两个球击倒的瓶的总数。
如果你在最终回合(第十回合)中得到"spare",你将得到额外一球。
如果你在最终回合(第十回合)中得到"strike",你将得到额外两球。
每一个额外球都将被视为一个独立回合(比如,在最终回合得到"strike",你将获得额外两球,在第一个额外球中,你击倒所有的瓶(获得"strike")。那么在第二个额外球中,你仍有机会去击倒所有瓶(十个瓶))。如果是在额外球中击倒所有瓶子,你不会再获得额外球。额外球中的得分仅用于计算最终回合(第十回合)的得分。
比赛得分是所有回合得分的总和。
例子:
‘X’ 表示strike
‘/’ 表示spare
‘-’ 表示未击倒一球
‘|’ 表示回合边界
“||” 后表示的是额外球
X|X|X|X|X|X|X|X|X|X||XX
十回合中每回合均是第一球击倒所有瓶(strike)。
两个额外的球,每球也都是击倒所有瓶(strike)。
每一回合的得分 == 10 +下两球的击倒瓶数
每回合得分 == 10 + 10 + 10 == 30
总得分 == 10 x 30 == 300
9-|9-|9-|9-|9-|9-|9-|9-|9-|9-||
十回合中每回合均是第一球击倒9个瓶。
十回合中每回合的第二球均没有击倒剩下的1个瓶。
没有得到额外球。
每一回合的得分 == 第一球击倒瓶数 + 第二球击倒瓶数
每回合得分 == 9 + 0 == 9
总得分 == 10 x 9 == 90
5/|5/|5/|5/|5/|5/|5/|5/|5/|5/||5
十回合中每回合均是第一球击倒5个瓶。
十回合中每回合的第二球均击倒剩下的5个瓶(spare)。
一个额外的球,击倒5个瓶子。
每一回合的得分 == 10 + 下一球的击倒瓶数
每回合得分 == 10 + 5 == 15
总得分 == 10 x 15 == 150
X|7/|9-|X|-8|8/|-6|X|X|X||81
总得分 == 167
算法实现
algorithm.h
#ifndef ALGORITHM_INCLUDED
#define ALGORITHM_INCLUDED
#include <stdio.h>
enum type
{
STRIKE = 1,
SPARE,
OTHER,
};
int answer(char *pc);
#endif
algorithm.c
#include "algorithm.h"
#if 0
X indicates a strike
/ indicates a spare
- indicates a miss
| indicates a frame boundary
The characters after the || indicate bonus balls
#endif
int answer(char *pc)
{
char *p_current;
char aframe[12][2]; //无需使用这样一个数组,调试可方便打印解析字符结果
int each_frame[12][2];
char type[12];
//输入合法性检查?
int i;
p_current = pc;
for (i = 0; i < 10; i++)
{
aframe[i][0] = *p_current; //current frame first element
p_current++;
if ('|' == *p_current) //strike
{
//只有strike一回合只扔一球,虚拟第二球得分为0
aframe[i][1] = '\0';
type[i] = STRIKE; //strike
each_frame[i][0] = 10;
each_frame[i][1] = 0;
//当前指向的是'|',指向下一个frame第一个元素需将偏移加1
//第10个球后指向的是"||"中的第二个'|'
p_current += 1;
}
else //other
{
//非strike,获取第二球的结果
aframe[i][1] = *p_current;
if (aframe[i][1] == '/')
{
type[i] = SPARE; //spare
if (aframe[i][0] == '-')
{
each_frame[i][0] = 0;
}
else
{
each_frame[i][0] = aframe[i][0] - '0';
}
each_frame[i][1] = 10 - each_frame[i][0];
}
else
{
type[i] = OTHER; //other
if (aframe[i][0] == '-')
{
each_frame[i][0] = 0;
}
else
{
each_frame[i][0] = aframe[i][0] - '0';
}
if (aframe[i][1] == '-')
{
each_frame[i][1] = 0;
}
else
{
each_frame[i][1] = aframe[i][1] - '0';
}
}
//当前指向的是第二球,指向下一个frame第一个元素需将偏移加2
//第10个球后指向的是"||"中的第二个'|'
p_current += 2;
}
}
p_current += 1; //for循环结束后指向"||"中第二个'|',指向额外球需加在此加1
//不管是否有额外两球,都虚拟出额外的两轮投球
type[10] = STRIKE;
type[11] = STRIKE;
if (STRIKE == type[9]) //第10球为strike有额外两轮投球
{
//额外第一轮投球
aframe[10][0] = *p_current;
each_frame[10][1] = 0;//第二次投球为虚拟出的投球,固定为0
//解析第一次投球
if (aframe[10][0] == '-')
{
each_frame[10][0] = 0;
}
else if (aframe[10][0] == 'X')
{
each_frame[10][0] = 10;
}
else
{
each_frame[10][0] = aframe[10][0] - '0';
}
//额外第二轮投球
p_current++;
aframe[11][0] = *p_current;
each_frame[11][1] = 0;//第二次投球为虚拟出的投球,固定为0
//解析第一次投球
if (aframe[11][0] == '-')
{
each_frame[11][0] = 0;
}
else if (aframe[11][0] == 'X')
{
each_frame[11][0] = 10;
}
else
{
each_frame[11][0] = aframe[11][0] - '0';
}
}
else if (SPARE == type[9])//第10球为spare有额外一轮投球
{
aframe[10][0] = *p_current;
each_frame[10][1] = 0;//第二次投球为虚拟出的投球,固定为0
//解析第一次投球
if (aframe[10][0] == '-')
{
each_frame[10][0] = 0;
}
else if (aframe[10][0] == 'X')
{
each_frame[10][0] = 10;
}
else
{
each_frame[10][0] = aframe[10][0] - '0';
}
//第二轮投球为虚拟的,固定为0
each_frame[11][0] = 0;
each_frame[11][1] = 0;
}
else
{
//两轮投球均为虚拟出来的,固定为0
each_frame[10][0] = 0;
each_frame[10][1] = 0;
each_frame[11][0] = 0;
each_frame[11][1] = 0;
}
for (i = 0; i < 12; i++)
{
printf("\r\neach_frame[%d][0] = %d",i,each_frame[i][0]);
printf("\r\neach_frame[%d][1] = %d",i,each_frame[i][1]);
printf("\r\ntype[%d] = %d",i,type[i]);
}
//以上解析出12轮投球,每轮两球,每球得分均已算出
int sum = 0;
//通过前10轮击球情况计算得分
for (i = 0; i < 10; i++)
{
if (STRIKE == type[i]) //current strike
{
sum += 10;
//本轮strike至少加下轮两球得分
sum += each_frame[i+1][0];
sum += each_frame[i+1][1];
if (STRIKE == type[i+1]) // next strike
{
//下轮仍为strike,则加下下轮第一球
sum += each_frame[i+2][0];
}
}
else if (SPARE == type[i]) //current spare
{
sum += 10;
//本轮spare需加下轮第一球
sum += each_frame[i+1][0];
}
else
{
//仅计算本轮得分
sum += each_frame[i][0];
sum += each_frame[i][1];
}
}
return sum;
}