""" 2048游戏引擎测试 验证新游戏引擎的功能和正确性 """ import numpy as np import pytest from game import Game2048, GameState class TestGame2048: """2048游戏引擎测试类""" def setup_method(self): """测试前的设置""" self.game = Game2048(height=4, width=4, seed=42) def test_initialization(self): """测试游戏初始化""" game = Game2048(height=3, width=4, seed=123) assert game.height == 3 assert game.width == 4 assert game.score == 0 assert game.moves == 0 assert not game.is_over # 应该有两个初始数字 non_zero_count = np.count_nonzero(game.board) assert non_zero_count == 2 # 初始数字应该是1或2(对数形式的2或4) non_zero_values = game.board[game.board != 0] assert all(val in [1, 2] for val in non_zero_values) def test_move_row_left(self): """测试行向左移动逻辑""" # 测试简单移动 row = np.array([0, 1, 0, 2]) result, score = self.game._move_row_left(row) expected = np.array([1, 2, 0, 0]) np.testing.assert_array_equal(result, expected) assert score == 0 # 测试合并 row = np.array([1, 1, 2, 2]) result, score = self.game._move_row_left(row) expected = np.array([2, 3, 0, 0]) np.testing.assert_array_equal(result, expected) # 分数应该是 2^2 + 2^3 = 4 + 8 = 12 assert score == 12 # 测试复杂情况 row = np.array([1, 1, 1, 1]) result, score = self.game._move_row_left(row) expected = np.array([2, 2, 0, 0]) np.testing.assert_array_equal(result, expected) # 分数应该是 2^2 + 2^2 = 4 + 4 = 8 assert score == 8 def test_move_directions(self): """测试四个方向的移动""" # 创建特定的棋盘状态 game = Game2048(height=3, width=3, seed=42) game.board = np.array([ [1, 0, 1], [0, 2, 0], [1, 0, 1] ]) initial_score = game.score # 测试向左移动 game_left = game.copy() success = game_left.move(2) # 左 assert success # 测试向右移动 game_right = game.copy() success = game_right.move(3) # 右 assert success # 测试向上移动 game_up = game.copy() success = game_up.move(0) # 上 assert success # 测试向下移动 game_down = game.copy() success = game_down.move(1) # 下 assert success # 所有移动都应该改变棋盘状态 assert not np.array_equal(game.board, game_left.board) assert not np.array_equal(game.board, game_right.board) assert not np.array_equal(game.board, game_up.board) assert not np.array_equal(game.board, game_down.board) def test_score_calculation(self): """测试分数计算""" game = Game2048(height=2, width=2, seed=42) # 设置特定棋盘状态 game.board = np.array([ [1, 2], # 2, 4 [3, 4] # 8, 16 ]) # 计算累积分数 total_score = game.calculate_total_score() # 根据论文公式:V(N) = (log2(N) - 1) * N # V(2) = 0, V(4) = 4, V(8) = 16, V(16) = 48 expected = 0 + 4 + 16 + 48 assert total_score == expected def test_game_over_detection(self): """测试游戏结束检测""" game = Game2048(height=2, width=2, seed=42) # 设置无法移动的棋盘 game.board = np.array([ [1, 2], # 2, 4 [3, 4] # 8, 16 ]) game._check_game_over() assert game.is_over # 测试可以移动的棋盘 game.board = np.array([ [1, 1], # 2, 2 (可以合并) [3, 4] # 8, 16 ]) game.is_over = False game._check_game_over() assert not game.is_over def test_valid_moves(self): """测试有效移动检测""" game = Game2048(height=2, width=2, seed=42) # 设置可以向所有方向移动的棋盘 game.board = np.array([ [1, 0], [0, 1] ]) valid_moves = game.get_valid_moves() assert len(valid_moves) == 4 # 所有方向都可以移动 # 设置无法移动的棋盘 game.board = np.array([ [1, 2], [3, 4] ]) valid_moves = game.get_valid_moves() assert len(valid_moves) == 0 # 无法移动 def test_board_display(self): """测试棋盘显示""" game = Game2048(height=2, width=2, seed=42) # 设置对数形式的棋盘 game.board = np.array([ [0, 1], # 0, 2 [2, 3] # 4, 8 ]) display_board = game.get_board_display() expected = np.array([ [0, 2], [4, 8] ]) np.testing.assert_array_equal(display_board, expected) def test_max_tile(self): """测试最大数字获取""" game = Game2048(height=2, width=2, seed=42) game.board = np.array([ [1, 2], # 2, 4 [3, 4] # 8, 16 ]) max_tile = game.get_max_tile() assert max_tile == 16 def test_state_management(self): """测试游戏状态管理""" game = Game2048(height=2, width=2, seed=42) # 获取初始状态 initial_state = game.get_state() assert isinstance(initial_state, GameState) assert initial_state.score == game.score assert initial_state.moves == game.moves assert np.array_equal(initial_state.board, game.board) # 执行移动 move_success = game.move(2) # 左移 # 获取新状态 new_state = game.get_state() # 只有移动成功时才检查移动次数 if move_success: assert new_state.moves == initial_state.moves + 1 assert not np.array_equal(new_state.board, initial_state.board) else: # 如果移动失败,尝试其他方向 for direction in range(4): if game.move(direction): new_state = game.get_state() assert new_state.moves == initial_state.moves + 1 assert not np.array_equal(new_state.board, initial_state.board) break # 恢复状态 game.set_state(initial_state) assert game.score == initial_state.score assert game.moves == initial_state.moves np.testing.assert_array_equal(game.board, initial_state.board) def test_copy_functionality(self): """测试游戏复制功能""" game = Game2048(height=3, width=3, seed=42) # 执行一些操作 game.move(2) game.move(0) # 创建副本 game_copy = game.copy() # 验证副本 assert game_copy.height == game.height assert game_copy.width == game.width assert game_copy.score == game.score assert game_copy.moves == game.moves assert game_copy.is_over == game.is_over np.testing.assert_array_equal(game_copy.board, game.board) # 修改副本不应影响原游戏 game_copy.move(1) assert game_copy.moves != game.moves def test_different_board_sizes(self): """测试不同大小的棋盘""" # 测试3x3棋盘 game_3x3 = Game2048(height=3, width=3, seed=42) assert game_3x3.board.shape == (3, 3) # 测试2x4矩形棋盘 game_2x4 = Game2048(height=2, width=4, seed=42) assert game_2x4.board.shape == (2, 4) # 测试移动功能 success = game_3x3.move(2) assert isinstance(success, bool) success = game_2x4.move(0) assert isinstance(success, bool) def test_spawn_probability(self): """测试数字生成概率""" # 测试只生成2的情况 game_only_2 = Game2048(height=4, width=4, spawn_prob_4=0.0, seed=42) # 重置并检查生成的数字 game_only_2.reset() non_zero_values = game_only_2.board[game_only_2.board != 0] assert all(val == 1 for val in non_zero_values) # 只有1(对数形式的2) # 测试只生成4的情况 game_only_4 = Game2048(height=4, width=4, spawn_prob_4=1.0, seed=42) game_only_4.reset() non_zero_values = game_only_4.board[game_only_4.board != 0] assert all(val == 2 for val in non_zero_values) # 只有2(对数形式的4) if __name__ == "__main__": # 运行测试 print("运行2048游戏引擎测试...") pytest.main([__file__, "-v"])