Files
deep2048/tests/test_game_engine.py
2025-07-23 07:04:10 +08:00

290 lines
9.0 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""
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"])