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_extradialog_select_extra_file(self): import os test_filetypes = None test_initialdir = None extra_file_ok = 'extra_file_ok' def test_askopenfilename_ok(filetypes, initialdir): nonlocal test_filetypes, test_initialdir, extra_file_ok test_filetypes = filetypes test_initialdir = initialdir return extra_file_ok def test_askopenfilename_ng(filetypes, initialdir): return False window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) extradialog = reversi.window.ExtraDialog(window, threading.Event(), 'Japanese') # OK extradialog.askopenfilename = test_askopenfilename_ok extradialog.button1.invoke() self.assertEqual(test_filetypes, [("", "*.json")]) self.assertEqual(test_initialdir, os.path.abspath(os.path.dirname('./extra/'))) self.assertEqual(extradialog.extra_file.get(), extra_file_ok) # NG extradialog.askopenfilename = test_askopenfilename_ng extradialog.button1.invoke() self.assertEqual(extradialog.extra_file.get(), extra_file_ok) extradialog.dialog.destroy()
def test_window_menu_set_state(self): window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) # initial expected = ['normal' for _ in window.menu.menu_items.keys()] result = [] for name in window.menu.menu_items.keys(): index = window.menu.index(name.title()) result.append(window.menu.entrycget(index, 'state')) self.assertEqual(result, expected) # disable window.menu.set_state('disable') expected = ['disabled' for _ in window.menu.menu_items.keys()] expected[-1] = 'normal' result = [] for name in window.menu.menu_items.keys(): index = window.menu.index(name.title()) result.append(window.menu.entrycget(index, 'state')) self.assertEqual(result, expected) # normal window.menu.set_state('normal') expected = ['normal' for _ in window.menu.menu_items.keys()] expected[-1] = 'disabled' result = [] for name in window.menu.menu_items.keys(): index = window.menu.index(name.title()) result.append(window.menu.entrycget(index, 'state')) self.assertEqual(result, expected)
def test_window_menu_create_menu_items(self): window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) for item in [ 'size', 'black', 'white', 'cputime', 'extra', 'assist', 'language', 'cancel' ]: self.assertIsInstance(window.menu.menus[item], tk.Menu)
def test_window_menu_init(self): root = tk.Tk() b = ['Easy1', 'Normal1', 'Hard1'] w = ['Easy2', 'Normal2', 'Hard2'] window = Window(root=root, black_players=b, white_players=w) self.assertIsInstance(window.menu.window, Window) self.assertEqual(window.menu.size, reversi.window.DEFAULT_BOARD_SIZE) self.assertEqual(window.menu.black_player, b[0]) self.assertEqual(window.menu.white_player, w[0]) self.assertEqual(window.menu.assist, reversi.window.ASSIST_MENU[1]) self.assertEqual(window.menu.language, reversi.window.LANGUAGE_MENU[0]) self.assertEqual(window.menu.cancel, reversi.window.CANCEL_MENU[0]) self.assertIsNone(window.menu.cputimedialog) self.assertIsNone(window.menu.extradialog) self.assertIsInstance(window.menu.event, threading.Event) self.assertEqual( window.menu.menu_items['size'], range(reversi.board.MIN_BOARD_SIZE, reversi.board.MAX_BOARD_SIZE + 1, 2)) self.assertEqual(window.menu.menu_items['black'], b) self.assertEqual(window.menu.menu_items['white'], w) self.assertEqual(window.menu.menu_items['cputime'], reversi.window.CPUTIME_MENU) self.assertEqual(window.menu.menu_items['extra'], reversi.window.EXTRA_MENU) self.assertEqual(window.menu.menu_items['assist'], reversi.window.ASSIST_MENU) self.assertEqual(window.menu.menu_items['language'], reversi.window.LANGUAGE_MENU) self.assertEqual(window.menu.menu_items['cancel'], reversi.window.CANCEL_MENU)
def test_window_extradialog_set_parameter(self): new_extra_file = 'new_extra_file' window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) extradialog = reversi.window.ExtraDialog(window, threading.Event(), 'Japanese') extradialog.extra_file.set(new_extra_file) extradialog.button2.invoke() self.assertEqual(window.extra_file, new_extra_file) self.assertTrue(extradialog.event.is_set())
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')
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
def test_window_cputimedialog_init(self): window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) event = 'event' language = 'Japanese' cputimedialog = reversi.window.CpuTimeDialog(window, event, language) self.assertEqual(cputimedialog.window, window) self.assertEqual(cputimedialog.event, event) self.assertEqual(cputimedialog.dialog.master, window.root) self.assertEqual(cputimedialog.parameter.get(), str(window.cputime)) self.assertEqual(cputimedialog.label1['text'], reversi.window.TEXTS[language]['CPU_WAIT_TEXT']) self.assertEqual(cputimedialog.entry['textvariable'], str(cputimedialog.parameter)) self.assertEqual(cputimedialog.label2['text'], reversi.window.TEXTS[language]['CPU_SECOND_TEXT']) self.assertEqual(cputimedialog.button['text'], reversi.window.TEXTS[language]['CPU_SETTING_TEXT']) cputimedialog.dialog.destroy()
def test_window_extradialog_init(self): window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) event = 'event' language = 'Japanese' extradialog = reversi.window.ExtraDialog(window, event, language) self.assertEqual(extradialog.window, window) self.assertEqual(extradialog.event, event) self.assertEqual(extradialog.dialog.master, window.root) self.assertEqual(extradialog.extra_file.get(), str(window.extra_file)) self.assertEqual(extradialog.label1['text'], reversi.window.TEXTS[language]['EXTRA_PLAYER_TEXT']) self.assertEqual(extradialog.label2['text'], reversi.window.TEXTS[language]['EXTRA_FILE_TEXT']) self.assertEqual(extradialog.entry['textvariable'], str(extradialog.extra_file)) self.assertEqual(extradialog.button1['text'], reversi.window.TEXTS[language]['EXTRA_REF_TEXT']) self.assertEqual(extradialog.button2['text'], reversi.window.TEXTS[language]['EXTRA_LOAD_TEXT']) extradialog.dialog.destroy()
def test_window_cputimedialog_set_parameter(self): window = Window(root=tk.Tk(), black_players=['b'], white_players=['w']) cputimedialog = reversi.window.CpuTimeDialog(window, threading.Event(), 'Japanese') # NOT MATCH new_cputime = -1.0 cputimedialog.parameter.set(new_cputime) cputimedialog.button.invoke() self.assertNotEqual(window.cputime, new_cputime) # IS ZERO new_cputime = 00.0 cputimedialog.parameter.set(new_cputime) cputimedialog.button.invoke() self.assertNotEqual(window.cputime, new_cputime) # OK new_cputime = 1.0 cputimedialog.parameter.set(new_cputime) cputimedialog.button.invoke() self.assertEqual(window.cputime, new_cputime) self.assertTrue(cputimedialog.event.is_set())
def test_window_init(self): root = tk.Tk() b = ['Easy1', 'Normal1', 'Hard1'] w = ['Easy2', 'Normal2', 'Hard2'] window = Window(root=root, black_players=b, white_players=w) self.assertEqual(window.root, root) self.assertEqual(window.size, reversi.window.DEFAULT_BOARD_SIZE) self.assertEqual(window.player['black'], 'Easy1') self.assertEqual(window.player['white'], 'Easy2') self.assertEqual(window.assist, 'OFF') self.assertEqual(window.language, 'English') self.assertEqual(window.cancel, 'OK') self.assertEqual(window.cputime, reversi.window.CPU_TIME) self.assertEqual(window.extra_file, '') self.assertIsInstance(window.menu, reversi.window.Menu) self.assertIsInstance(window.canvas, tk.Canvas) self.assertEqual(window.canvas['width'], str(reversi.window.WINDOW_WIDTH)) self.assertEqual(window.canvas['height'], str(reversi.window.WINDOW_HEIGHT)) self.assertEqual(window.canvas['bg'], str(reversi.window.COLOR_SLATEGRAY))
def test_window_menu_command(self): root = tk.Tk() b = ['Easy1', 'Normal1', 'Hard1'] w = ['Easy2', 'Normal2', 'Hard2'] window = Window(root=root, black_players=b, white_players=w) # size test_size = 12 command = window.menu._command('size', test_size) self.assertFalse(window.menu.event.is_set()) self.assertEqual(window.menu.size, reversi.window.DEFAULT_BOARD_SIZE) command() self.assertTrue(window.menu.event.is_set()) self.assertEqual(window.menu.size, test_size) window.menu.event.clear() # black test_black_player = 'Hard1' command = window.menu._command('black', test_black_player) self.assertFalse(window.menu.event.is_set()) self.assertEqual(window.menu.black_player, b[0]) command() self.assertTrue(window.menu.event.is_set()) self.assertEqual(window.menu.black_player, test_black_player) window.menu.event.clear() # white test_white_player = 'Hard2' command = window.menu._command('white', test_white_player) self.assertFalse(window.menu.event.is_set()) self.assertEqual(window.menu.white_player, w[0]) command() self.assertTrue(window.menu.event.is_set()) self.assertEqual(window.menu.white_player, test_white_player) window.menu.event.clear() # cputime command = window.menu._command('cputime', '') self.assertFalse(window.menu.event.is_set()) command() self.assertTrue(window.menu.event.is_set()) window.menu.event.clear() self.assertIsInstance(window.menu.cputimedialog, reversi.window.CpuTimeDialog) window.menu.cputimedialog.dialog.destroy() # extra command = window.menu._command('extra', '') self.assertFalse(window.menu.event.is_set()) command() self.assertTrue(window.menu.event.is_set()) window.menu.event.clear() self.assertIsInstance(window.menu.extradialog, reversi.window.ExtraDialog) window.menu.extradialog.dialog.destroy() # assist test_assist = 'ON' command = window.menu._command('assist', test_assist) self.assertFalse(window.menu.event.is_set()) self.assertEqual(window.menu.assist, reversi.window.ASSIST_MENU[1]) command() self.assertTrue(window.menu.event.is_set()) self.assertEqual(window.menu.assist, test_assist) window.menu.event.clear() # language test_language = 'JAPANESE' command = window.menu._command('language', test_language) self.assertFalse(window.menu.event.is_set()) self.assertEqual(window.menu.language, reversi.window.LANGUAGE_MENU[0]) command() self.assertTrue(window.menu.event.is_set()) self.assertEqual(window.menu.language, test_language) window.menu.event.clear() # cancel test_cancel = 'TEST_ON' command = window.menu._command('cancel', test_cancel) self.assertFalse(window.menu.event.is_set()) self.assertEqual(window.menu.cancel, 'OK') command() self.assertTrue(window.menu.event.is_set()) self.assertEqual(window.menu.cancel, test_cancel) window.menu.event.clear()
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