微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

TDD练习:保龄球计分

前言


培训遗留作业,计划放在国庆空闲时间做,所以这算是走计划节奏。另外,真的是不喜欢做这些题,虽然实现以后发现很简单。但是没实现之前,多少还是觉得有些困难,可能是自己做题太少(不知道别人做题时候啥感觉)。。另外,做这些题我是感觉完全搭不上算法的边,可能是我自己没专门学过的原因吧,基本上纯粹是按照题的说明需求,然后自己思考,整理思路,然后实现...过程就是这样。


保龄球计分

(题目摘自网络,反正都一个规则)

打保龄球是用一个滚球去撞击10个站立的瓶,将瓶击倒。一局分10轮,每轮可滚球1 次或多次,以击到的瓶数为依据计分,一局得分为10轮得分之和,而每轮的得分不仅与本轮的滚球情况有关,还可能与后一轮或两轮的滚球情况有关,即:某轮某次滚球击倒的瓶数不仅要计入本轮得分,还可能会计入前一轮或两轮得分。
计分规则具体如下:
① 若某一轮的第一次滚球就击倒全部10个瓶,则本轮不再滚球(若是第10轮还需加2次滚球),该轮得分为本次击倒瓶数10与以后2次滚球所击倒瓶数之和。
② 若某一轮的第一次滚球未击倒全部10个球,则对剩下未击倒的瓶再滚球一次,如果这2次滚球击倒全部10个瓶,则本轮不再滚球(若是第10轮还需加1次滚球),该轮得分为这2次击倒瓶数10与以后1次滚球所击倒瓶数之和。
③ 若某一轮2次滚球未击倒全部10个瓶,则本轮不在滚球,该轮得分为这2次滚球所击倒瓶数之和。

编写一个程序,统计各轮得分和累积总分。
Input:
输入数据是文本格式,共1行(字符串),有最多22个[0,10]之间的整数,表示每轮滚球第一次或第二次记到的秋熟,输入数据保证合法,两个整数间仅有一个空格。

Output:
自定义。对外接口为 Calcscore(const char *s);


实现思路


计算每轮单独得分,十轮累加得总分。每轮单独得分,按规则可以大致总结出,如果议论中首次全中或者两次补中,则相当于第一次滚球后连续加后面两次;否则,只加后面一次。直接看代码吧,按照TDD方式,先写测例,再快速实现,最后的抽象实在不知道怎么抽象,估计是仅仅实现了功能代码质量还相当欠缺,后续看下别人实现,再来做修改

<span style="font-size:18px;">/* test.cpp */
#include <assert.h>

extern int Calcscore(const char *s);

void main()
{
	assert(Calcscore("10 10 10 10 10 10 10 10 10 10 10 10") == 300);
	assert(Calcscore("10 10 10 7 2 9 1 8 1 8 2 10 9 1 10 8 2") == 192);
	assert(Calcscore("1 4 4 5 6 4 5 5 10 0 1 7 3 6 4 10 2 8 6") == 133);
}</span>
<span style="font-size:18px;">/* bowling.cpp */
#include <stdio.h>
#include <stdlib.h>

typedef struct _context
{
	const char *s;
	int pos;
}Context;

int Record[10];

bool Is_STRIKE(int score)
{
	return score == 10;
}

int Parsescore(Context &ctx,int offset)
{
	int temp_score = 0;

	if (ctx.s[ctx.pos] == ' ')
	{
		ctx.pos++;
	}

	return atoi(ctx.s + ctx.pos + offset);
}

int CalcscorePerRound(Context &ctx)
{
	int offset = 0;
	int curr_score = 0;
	int next_score = 0;
	int round_score = 0;

	curr_score = Parsescore(ctx,0);       // 0表示解析分数的起始偏移
	if (Is_STRIKE(curr_score))
	{
		offset = 2;
		next_score = Parsescore(ctx,offset);
		ctx.pos += 2;         // 本轮STRIKE,下一轮击球开始解析的位置
	}
	else
	{
		offset = 0;
		ctx.pos++;
		next_score = Parsescore(ctx,offset);
		ctx.pos++;             // 本轮SPARE,下一轮击球开始解析的位置
	}

	// 本轮计分
	if (10 > (curr_score + next_score))          // 本轮两次击球未全中
	{	
		round_score = curr_score + next_score;
	}
	else                                       // 本轮STRIKE或两次补中
	{
		int third_score = Parsescore(ctx,offset);
		round_score = curr_score + next_score + third_score;
	}

	return round_score;
}

int Calcscore(const char *s)
{
	Context ctx = {s,0};
	int total_score = 0;

	printf("每轮得分:\n");
	for (int i = 0; i < 10; i++)
	{
		Record[i] = CalcscorePerRound(ctx);
		printf("%-2d ",Record[i]);
		total_score += Record[i];
	}
	printf("\n累计总分:%d",total_score);
	printf("\n+++++++++++++++++++++++++++++++++\n");

	return total_score;
}</span>

总结


领域规则抽象,思考了N久,真心就是(臣妾做不到啊...)。如果仅仅就为实现功能而写的代码,再进行重构抽象,现在感觉好难。只能是多看高质量代码,多积累,多练习了!

原文地址:https://www.jb51.cc/javaschema/285295.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐