上传文件至「/」
init
This commit is contained in:
+109
@@ -0,0 +1,109 @@
|
||||
# 无头测试:桩替代 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游戏逻辑全部测试通过 ✔")
|
||||
Reference in New Issue
Block a user