着手できる場所のチェックと石を取る処理を追加
ちゃんとテストしていない。
# -*- coding: utf-8 -*- import sys import codecs sys.stdout = codecs.getwriter('utf-8')(sys.stdout) class Untouchable(Exception): pass class Goban(object): invalid = 99 empty = 0 black = 1 white = -1 around_moves = ((1, 0), (-1, 0), (0, 1), (0, -1)) def __init__(self, size): self.size = size self.data = [ [ 0 for i in range(size) ] for j in range(size) ] def render(self, output=sys.stdout): for i, line in enumerate(self.data): for j, point in enumerate(line): if point == self.empty: output.write(self._empty_str(i, j)) elif point == self.black: output.write(u'●') else: output.write(u'○') output.write('\n') def get_opponent_color(self, color): return color * -1 def touch(self, x, y, color): if not self.touchable(x, y, color): raise Untouchable() self.data[y][x] = color gottens = set() opponent = self.get_opponent_color(color) for move_x, move_y in self.around_moves: next_x = x + move_x next_y = y + move_y if self.get_state(next_x, next_y) is not opponent: continue if not self.check_alive(next_x, next_y, opponent): self._get_stones(next_x, next_y, gottens) for gotten_x, gotten_y in gottens: self.data[gotten_y][gotten_x] = self.empty return len(gottens) def _get_stones(self, x, y, gottens): color = self.get_state(x, y) targets = [(x, y)] gottens.add((x, y)) target = targets.pop() while target is not None: x, y = target for move_x, move_y in self.around_moves: next_x = x + move_x next_y = y + move_y if self.get_state(next_x, next_y) is not color: continue if (next_x, next_y) not in gottens: targets.append((next_x, next_y)) gottens.add((next_x, next_y)) target = targets.pop() if targets else None def touchable(self, x, y, color): if self.get_state(x, y) is not self.empty: return False else: if not self.check_alive(x, y, color): return False return True def get_state(self, x, y): if x < 0 or self.size <= x or y < 0 or self.size <= y: return self.invalid return self.data[y][x] def check_alive(self, x, y, color): targets = [(x, y)] target = targets.pop() while target is not None: for move_x, move_y in self.around_moves: next_x = x + move_x next_y = y + move_y state = self.get_state(next_x, next_y) if state is self.empty: return True elif state is color: targets.append((next_y, next_y)) target = targets.pop() if targets else None return False def _empty_str(self, x, y): if x == 0: if y == 0: return u'┏' elif y == self.size - 1: return u'┓' else: return u'┯' elif x == self.size - 1: if y == 0: return u'┗' elif y == self.size - 1: return u'┛' else: return u'┷' else: if y == 0: return u'┠' elif y == self.size - 1: return u'┨' else: return u'┼' def test(): goban_size = 19 goban = Goban(goban_size) goban.touch(3, 3, Goban.black) goban.touch(15, 15, Goban.white) goban.touch(0, 1, Goban.black) goban.render() goban.touch(0, 0, Goban.white) goban.render() gotten = goban.touch(1, 0, Goban.black) goban.render() print gotten, 'got.' if __name__ == '__main__': test()
実行。
┏┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┓ ●┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼●┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼○┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┗┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┛ ○┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┓ ●┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼●┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼○┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┗┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┛ ┏●┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┯┓ ●┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼●┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼○┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┠┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┼┨ ┗┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┷┛ 1 got.