def test_window_init_screen(self): root = tk.Tk() b = ['Easy1', 'Normal1', 'Hard1'] w = ['Easy2', 'Normal2', 'Hard2'] window = Window(root=root, black_players=b, white_players=w) window.init_screen() # board self.assertEqual(window.board.size, reversi.window.DEFAULT_BOARD_SIZE) self.assertEqual(window.board.cputime, reversi.window.CPU_TIME) self.assertEqual(window.board.assist, reversi.window.ASSIST_MENU[1]) self.assertEqual(window.board._squares, [[None for _ in range(window.board.size)] for _ in range(window.board.size)]) self.assertEqual(window.board._xlines, [6, 10, 14, 18, 22, 26, 30, 38, 40]) self.assertEqual(window.board._ylines, [4, 8, 12, 16, 20, 24, 28, 36, 39]) self.assertEqual(window.board.move, None) self.assertEqual(window.board.event.is_set(), False) # info self.assertEqual(window.info.player, {'black': b[0], 'white': w[0]}) self.assertEqual(window.info.language, reversi.window.LANGUAGE_MENU[0]) # start self.assertEqual(window.start.language, reversi.window.LANGUAGE_MENU[0]) self.assertEqual(window.start.event.is_set(), False)
def test_window_set_state(self): window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) window.init_screen() class TestState: def __init__(self): self.state = None def set_state(self, state): self.state = state window.start = TestState() window.menu = TestState() window.set_state('Normal') self.assertEqual(window.start.state, 'Normal') self.assertEqual(window.menu.state, 'Normal') window.set_state('Disable') self.assertEqual(window.start.state, 'Disable') self.assertEqual(window.menu.state, 'Disable')
class Reversi: """ リバーシゲーム """ INIT, DEMO, PLAY, END, REINIT = 'INIT', 'DEMO', 'PLAY', 'END', 'REINIT' def __init__(self, players_info={}, turn_disc_wait=0.1, sleep_time_play=1.5, sleep_time_end=0.01, sleep_time_turn=0.3, sleep_time_move=0.3): root = tk.Tk() root.withdraw() # 表示が整うまで隠す self.state = Reversi.INIT b = ['User1'] + list(players_info.keys()) w = ['User2'] + list(players_info.keys()) self.window = Window(root=root, black_players=b, white_players=w) players_info['User1'] = strategies.WindowUserInput(self.window) players_info['User2'] = strategies.WindowUserInput(self.window) self.players_info = players_info self.err_msg = ErrorMessage() # wait or sleep time (sec) self.turn_disc_wait = turn_disc_wait self.sleep_time_play = sleep_time_play self.sleep_time_end = sleep_time_end self.sleep_time_turn = sleep_time_turn self.sleep_time_move = sleep_time_move @property def state(self): return self._state @state.setter def state(self, state): self._state = state if state == Reversi.INIT: self.game = self.__init elif state == Reversi.DEMO: self.game = self.__demo elif state == Reversi.PLAY: self.game = self.__play elif state == Reversi.END: self.game = self.__end else: self.game = self.__reinit def gameloop(self): """ ゲーム処理 """ while True: if self.game(): break def start(self): """ アプリ開始 """ self.game_start() # ゲーム開始 self.window_start() # ウィンドウ開始 def game_start(self): """ ゲーム開始 """ game_thread = threading.Thread(target=self.gameloop) game_thread.daemon = True self._thread_start(game_thread) def _thread_start(self, thread): """ スレッド開始 """ thread.start() def window_start(self): """ ウィンドウ開始 """ self.window.root.deiconify() # 表示する self.window.root.mainloop() def __init(self): """ 画面初期化(初回、設定変更時) """ self.window.init_screen() self.window.set_state('normal') # メニューで登録ファイルが読み込まれた場合 if self.window.extra_file: extra_file = self.window.extra_file self.window.extra_file = "" self._load_extra_file(extra_file) self.state = Reversi.DEMO def _load_extra_file(self, extra_file): """ 登録ファイルを読み込む """ if os.path.isfile(extra_file): with open(extra_file, 'r') as f: name, cmd, timeouttime = None, None, None try: # 設定の読み出し json_dict = json.load(f) name = json_dict['name'] cmd = json_dict['cmd'] timeouttime = json_dict['timeouttime'] except Exception: self.err_msg.show('フォーマットエラーのため登録ファイルが読み込めませんでした') else: # メニューにAIの名前を追加 for color in ('black', 'white'): if name not in self.window.menu.menu_items[color]: self.window.menu.menu_items[color].append(name) self.window.menu.menus[color].add_command(label=str(name), command=self.window.menu._command(color, name)) # 戦略を追加 self.players_info[name] = strategies.External(cmd, timeouttime) else: self.err_msg.show('指定された登録ファイルが見つかりませんでした') def __demo(self): """ デモ画面 """ while True: if self.window.start.event.is_set(): self.window.start.event.clear() self.state = Reversi.PLAY break if not self._demo_animation(): self.state = Reversi.INIT break def _demo_animation(self): """ デモアニメーション継続中 """ center = self.window.board.size // 2 target = [ ('black', center, center-1), ('black', center-1, center), ('white', center-1, center-1), ('white', center, center), ] ptn = { 'black': [ ('black', 'turnblack'), ('turnblack', 'white'), ('white', 'turnwhite'), ('turnwhite', 'black'), ], 'white': [ ('white', 'turnwhite'), ('turnwhite', 'black'), ('black', 'turnblack'), ('turnblack', 'white'), ], } for color, x, y in target: for remove_color, put_color in ptn[color]: # メニュー設定変更時 if self._setting_changed(): return False # アニメーション処理 time.sleep(self.turn_disc_wait) self.window.board.remove_disc(remove_color, x, y) self.window.board.put_disc(put_color, x, y) return True def __play(self): """ ゲーム画面 """ self.window.set_state('disable') board = BitBoard(self.window.board.size) players = {} for color in ('black', 'white'): name = self.window.player[color] players[color] = Player(color, name, self.players_info[name]) # ウィンドウの設定をゲームに反映 strategies.common.Timer.time_limit = self.window.cputime Game( players['black'], players['white'], board, WindowDisplay(self.window, sleep_time_turn=self.sleep_time_turn, sleep_time_move=self.sleep_time_move), cancel=self.window.menu, ).play() time.sleep(self.sleep_time_play) # 少し待って終了状態へ self.state = Reversi.END def __end(self): """ 終了画面 """ self.window.set_state('normal') while True: time.sleep(self.sleep_time_end) if self.window.start.event.is_set(): self.window.start.event.clear() self.state = Reversi.REINIT break if self._setting_changed(): self.state = Reversi.INIT break def __reinit(self): """ 再初期化(ゲーム終了後再スタート時) """ self.window.init_screen() self.state = Reversi.PLAY def _setting_changed(self): """ ウィンドウの設定が変更されたとき """ if self.window.menu.event.is_set(): self.window.size = self.window.menu.size self.window.player['black'] = self.window.menu.black_player self.window.player['white'] = self.window.menu.white_player self.window.assist = self.window.menu.assist self.window.language = self.window.menu.language self.window.menu.event.clear() return True return False