Files
snake/test_snake.py
T
2026-09-27 22:55:32 +08:00

110 lines
3.6 KiB
Python
Raw 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.
# 无头测试:桩替代 pygame,验证 snake 游戏核心逻辑
import sys, types, os, shutil, tempfile
# ---------------- pygame 桩 ----------------
class Surf:
def fill(self, *a, **k): pass
def blit(self, *a, **k): pass
class Font:
def __init__(self, *a, **k): pass
def render(self, text, aa, color):
s = Surf()
s.get_width = lambda: 10 * len(str(text))
s.get_height = lambda: 20
return s
class Rect:
def __init__(self, x, y, w, h, *a, **k):
self.x, self.y, self.width, self.height = x, y, w, h
@property
def right(self): return self.x + self.width
class Clock:
def tick(self, *a): return 0
def get_time(self): return 16
fake = types.ModuleType("pygame")
fake.init = lambda: None
fake.quit = lambda: None
fake.joystick = types.SimpleNamespace(init=lambda: None, Joystick=lambda i: None,
get_count=lambda: 0)
fake.display = types.SimpleNamespace(set_mode=lambda s: Surf(), set_caption=lambda s: None,
flip=lambda: None)
fake.font = types.SimpleNamespace(Font=Font)
fake.Rect = Rect
fake.draw = types.SimpleNamespace(rect=lambda *a, **k: None, line=lambda *a, **k: None)
fake.time = types.SimpleNamespace(Clock=Clock)
for name, val in dict(K_ESCAPE=27, K_UP=273, K_DOWN=274, K_LEFT=276, K_RIGHT=275,
K_w=119, K_s=115, K_a=97, K_d=100, K_RETURN=13, K_SPACE=32,
QUIT=256, KEYDOWN=768, JOYBUTTONDOWN=769, JOYHATMOTION=770,
JOYAXISMOTION=771).items():
setattr(fake, name, val)
sys.modules["pygame"] = fake
sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)),
"games", "snake"))
import importlib.util
spec = importlib.util.spec_from_file_location(
"snake_main", os.path.join(os.path.dirname(os.path.abspath(__file__)),
"games", "snake", "main.py"))
m = importlib.util.module_from_spec(spec)
spec.loader.exec_module(m)
# 把存档指到临时目录,避免污染
tmp = tempfile.mkdtemp()
m.SAVE_DIR = tmp
m.SAVE_FILE = os.path.join(tmp, "snake_best.txt")
g = m.SnakeGame()
# 1. 初始为菜单态
assert g.state == "menu"
g.confirm()
assert g.state == "play"
assert len(g.snake) == 3
print("1. 菜单→开始 OK")
# 2. 移动两步,蛇头前进
head0 = g.snake[0]
g.step()
assert g.snake[0] == (head0[0] + 1, head0[1]), g.snake[0]
assert len(g.snake) == 3
print("2. 移动 OK")
# 3. 禁止 180° 掉头
g.push_dir((-1, 0))
g.step()
assert g.dir == (1, 0), g.dir
print("3. 禁止掉头 OK")
# 4. 吃到苹果:加分 + 变长
g.apple = (g.snake[0][0] + 1, g.snake[0][1])
score0, len0 = g.score, len(g.snake)
g.step()
assert g.score == score0 + 1 and len(g.snake) == len0 + 1
print("4. 吃苹果 OK")
# 5. 撞墙 → 结束并保存最高分
g.snake = [(m.COLS - 1, 5), (m.COLS - 2, 5), (m.COLS - 3, 5)]
g.dir, g.pending = (1, 0), []
g.score = 12
g.step()
assert g.state == "over" and g.best == 12
assert open(m.SAVE_FILE).read() == "12"
print("5. 撞墙/最高分保存 OK")
# 6. 重新开始
g.confirm()
assert g.state == "play" and g.score == 0 and len(g.snake) == 3
print("6. 重开 OK")
# 7. 存档路径在仓库外(约定 games/_saves)
m.SAVE_DIR = os.path.normpath(os.path.join(
os.path.dirname(os.path.abspath(__file__)), "games", "snake", "..", "_saves"))
assert "_saves" in m.SAVE_DIR and "snake" not in m.SAVE_DIR.replace("_saves", "", 1).rstrip(os.sep).split(os.sep)[-1]
print("7. 存档位于仓库外 OK")
shutil.rmtree(tmp, ignore_errors=True)
print("\n游戏逻辑全部测试通过 ✔")