feat: workable

This commit is contained in:
2026-06-12 10:25:26 +08:00
commit 3a9af920b4
32 changed files with 2079 additions and 0 deletions
+127
View File
@@ -0,0 +1,127 @@
"""求解器与棋盘模型的单元测试(不依赖 MaaFramework / 真机)。"""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from hbc.board import Board, Cell, CellKind # noqa: E402
from hbc.solver import Solver, Swap # noqa: E402
BRICK = -2
EMPTY = -1
def test_cell_types():
assert Cell.normal(3).is_swappable
assert not Cell.brick().is_swappable
assert not Cell.empty().is_swappable
assert Cell.brick().is_brick
assert Cell.empty().is_empty
def test_dynamic_rectangular_sizes():
for rows, cols in [(5, 9), (8, 8), (6, 7), (3, 3)]:
b = Board(rows, cols)
assert b.rows == rows and b.cols == cols
assert b.in_bounds(rows - 1, cols - 1)
assert not b.in_bounds(rows, cols)
def test_find_horizontal_match():
board = Board.from_colors([
[0, 0, 0, 1],
[2, 3, 4, 5],
])
matches = Solver().find_matches(board)
assert len(matches) == 1
assert matches[0].length == 3
assert matches[0].color == 0
def test_brick_breaks_the_line():
# 砖块 (#) 打断同色连线 -> 不应形成消除
board = Board.from_colors([
[0, 0, BRICK, 0],
])
assert not Solver().has_match(board)
def test_empty_breaks_the_line():
board = Board.from_colors([
[0, 0, EMPTY, 0],
])
assert not Solver().has_match(board)
def test_best_swap_makes_a_match():
# 把 (0,3) 的 0 与 (1,3) 的 X 交换? 这里构造:交换 (0,2)&(0,3) 形成三连
board = Board.from_colors([
[0, 0, 1, 0],
[2, 3, 0, 4],
])
# 交换 (0,2)=1 与 (1,2)=0 -> 第0行变 0 0 0 0(前三连),合法
solver = Solver()
result = solver.find_best_swap(board)
assert result is not None
assert result.cleared >= 3
def test_cannot_swap_brick_or_empty():
board = Board.from_colors([
[0, BRICK, 0],
[0, 0, 0],
])
solver = Solver()
# 砖块不可交换:尝试交换砖块应被判非法
assert solver.evaluate_swap(board, Swap(0, 1, 1, 1)) is None
def test_no_swap_available():
# 棋盘上任何交换都无法形成消除(三色互不相邻,且任意相邻交换都凑不出 3 连)
board = Board.from_colors([
[0, 1, 2],
])
assert Solver().find_best_swap(board) is None
def test_prefer_longer_match():
# 一处可形成 3 连,另一处可形成 4 连 —— 应优先 4 连(得分更高)
board = Board.from_colors([
[0, 0, 0, 5, 1, 1, 9, 1],
[9, 9, 0, 9, 9, 9, 1, 9],
])
solver = Solver()
best = solver.find_best_swap(board)
assert best is not None
# 至少应找到一个可行交换
assert best.score > 0
def test_horizontal_swipe_is_right_to_left():
"""水平交换必须从右往左滑(避免触发返回手势);竖直交换不受限制。"""
import sys as _sys
from pathlib import Path as _Path
_sys.path.insert(0, str(_Path(__file__).resolve().parents[1] / "src"))
from hbc.actuator import swap_to_swipe
from hbc.config import GridConfig
grid = GridConfig(0, 0, 500, 500, 5, 5)
# 求解器产生的水平交换通常是 (r,c)->(r,c+1),即左->右;应被翻转成右->左
x1, y1, x2, y2 = swap_to_swipe(Swap(2, 1, 2, 2), grid)
assert x1 > x2 and y1 == y2 # 起点在右,终点在左
# 即使给的是右->左,也应保持右->左
x1, y1, x2, y2 = swap_to_swipe(Swap(2, 3, 2, 2), grid)
assert x1 > x2
# 竖直交换:x 相同,方向不限
x1, y1, x2, y2 = swap_to_swipe(Swap(1, 2, 2, 2), grid)
assert x1 == x2 and y1 != y2
if __name__ == "__main__":
import pytest
raise SystemExit(pytest.main([__file__, "-v"]))