保龄球计分算法(C语言实现)

保龄球计分算法(C语言实现)

问题描述

写一个十瓶保龄球游戏计分程序

输入:字符串(下面描述)表示的一局保龄球游戏
输出:整数的分数

评分规则:
每场比赛,投球手有十个回合。
在每一回合中,投球手有两次机会击倒所有的十个瓶子。
如果一回合中的第一个球击倒了所有的十个瓶子,这被称为“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;
}

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值