pythonic python中的保龄球游戏kata

时间:2015-10-09 21:59:49

标签: python

我试图解决Uncle Bobs保龄球游戏kata(http://www.butunclebob.com/ArticleS.UncleBob.TheBowlingGameKata),但没有找到足够感觉pythonic的解决方案。

此解决方案或多或少是对Martins C ++解决方案的改编,并使用数组索引来计算罢工和备件的分数。它有效,但感觉不像我希望的那样pythonic。

class Game():

    def __init__(self):
        self.rolls = []

    def roll(self, pins):
        self.rolls.append(pins)

    def score_c(self):
        total_score = 0
        frame_index = 0
        for frame in range(10):
            if self.rolls[frame_index] == 10:
                 total_score += 10 + self.rolls[frame_index + 1] + self.rolls[frame_index + 2]
                frame_index +=1
            elif self.rolls[frame_index] + self.rolls[frame_index + 1] == 10:
                total_score += 10 + self.rolls[frame_index + 1]
                frame_index += 2
            else:
                total_score += self.rolls[frame_index] + self.rolls[frame_index + 1]
                frame_index += 2
        return total_score

我可以使用便利功能来实现打击和备用条件,但是你可以得到图片。

但是我认为必须有一种方法可以直接通过索引访问roll数组。这感觉就像一个非常类似于c的方式,直接增加frame_index肯定在python中感觉不对。所以我认为必须有一个更简洁的方法来做到这一点。我在下面做了一个尝试,并没有真正适用于完美游戏。

这个使用发电机来提供感觉非常整洁的框架,但这也意味着必须添加0来进行打击才能制作完整的2个滚动框架。

class Game():

    def __init__(self):
        self.rolls = []

    def _frame_iterator(self):
        for i in range(0, 20, 2):
            yield (self.rolls[i], self.rolls[i+1])

    def roll(self, pins):
        self.rolls.append(pins)
        if pins == 10:
            self.rolls.append(0)

    def score(self):
        total_score = 0
        spare = False
        strike = False
        for frame in self._frame_iterator():
            if spare:
                total_score += frame[0]
                spare = False
            if strike:
                total_score += frame[1]
                strike = False
            if frame[0] + frame[1] == 10:
                spare = True
            if frame[0] == 10:
                strike = True
            total_score += frame[0] + frame[1]
        return total_score

我的问题基本上是,有没有人用不同于更多的pythonic方式解决Python中的保龄球kata而不是叔叔bobs C ++解决方案?并建议如何改进我的尝试?

1 个答案:

答案 0 :(得分:0)

这绝对是一种不同的方法(实现roll()中的大多数规则,而不是score()),我认为它也是非常pythonic。

class Game(object):
    def __init__(self):
        self._score = [[]]

    def roll(self, pins):
        # start new frame if needed
        if len(self._score[-1]) > 1 or 10 in self._score[-1]:
            self._score.append([])

        # add bonus points to the previous frames
        for frame in self._score[-3:-1]:
            if sum(frame[:2]) >= 10 and len(frame) < 3:
                frame.append(pins)

        # add normal points to current frame
        for frame in self._score[-1:10]:
            frame.append(pins)

    def score(self):
        return sum(sum(x) for x in self._score)

这里的主要思想是将所有卷存储在一个列表中,以制作包含每个帧的卷(和奖励点)列表的帧列表。

使它成为pythonic的原因是例如得分方法中的生成器表达式。

另一个pythonic示例是使用列表切片。我roll()的中间部分的早期版本看起来像:

for i in [2, 3]:
    if len(self._score) >= i:
        sum(self._score[-i][:2]) >= 10 and len(self._score[-i]) < 3:
            self._score[-i].append(pins)

使用列表切片的当前版本的优雅之处在于,您不必检查列表是否足够长以回显1或2帧。而且,你可以免费得到一个很好的局部变量(frame = self._score[-i]),而不必为它专门设置一条线。