有些需求介于「写个程序太重」和「手动做又嫌烦」之间。这一篇收了六个偏向「小项目」的脚本:有能直接在终端玩起来的数独、井字棋、生命游戏,也有能落地到日常的文件处理——把文本里的链接收齐、生成能在系统日历里打开的日程、顺手画一批矢量图标。它们单个都不长,凑一起正好覆盖算法小玩具和办公零碎活两头的缝。
想练手回溯算法,或单纯想随时来一局,用标准库就能写一个:先随机生成一整个合法盘面,再写个求解器把空格填满。
(标准库,无需安装)
import random
defis_safe(board, r, c, n):
for i in range(9):
if board[r][i] == n or board[i][c] == n:
returnFalse
br, bc = (r // 3) * 3, (c // 3) * 3
for i in range(br, br + 3):
for j in range(bc, bc + 3):
if board[i][j] == n:
returnFalse
returnTrue
defsolve(board):
for r in range(9):
for c in range(9):
if board[r][c] == 0:
for n in range(1, 10):
if is_safe(board, r, c, n):
board[r][c] = n
if solve(board):
returnTrue
board[r][c] = 0
returnFalse
returnTrue
defgenerate():
board = [[0] * 9for _ in range(9)]
for k in range(0, 9, 3):
nums = list(range(1, 10)); random.shuffle(nums)
for i in range(3):
for j in range(3):
board[k + i][k + j] = nums[i * 3 + j]
solve(board)
return board
defshow(board):
for r in range(9):
print(" ".join(str(x) if x else"."for x in board[r]))
puzzle = generate()
print("—— 题目(完整解示意)——")
show(puzzle)
print("—— 求解后 ——")
solve(puzzle)
show(puzzle)
小提示:generate 给的是完整解;想做成「出题」效果,在 show 之前随机把若干格置 0 即可。求解器基于回溯法,普通难度的数独都能解出来。
终端里和电脑下井字棋,纯标准库实现。电脑的走法做了优先级:能赢就赢、该堵就堵,否则随机,玩起来不算太菜。
(标准库,无需安装)
import random
defshow(b):
for i in range(0, 9, 3):
print(b[i], b[i + 1], b[i + 2])
defwin(b, p):
lines = [(0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6)]
return any(b[a] == b[c] == b[e] == p for a, c, e in lines)
defempty(b):
return [i for i, v in enumerate(b) if v == "."]
defai(b):
for p in ("O", "X"):
for i in empty(b):
b[i] = p
if win(b, p):
b[i] = "."
return i
b[i] = "."
return random.choice(empty(b))
b = ["."] * 9
whileTrue:
show(b); print()
i = int(input("你的位置(0-8): "))
if b[i] != ".":
continue
b[i] = "X"
if win(b, "X"):
print("你赢了"); break
ifnot empty(b):
print("平局"); break
b[ai(b)] = "O"
if win(b, "O"):
show(b); print("电脑赢了"); break
小提示:这里的电脑只做了「能赢就赢、该堵就堵」的一步预判,水平有限但够玩;想要永远不败的版本,可以把 ai 换成极小化极大(minimax)算法。
收藏了一堆资料、想把里面的网址统一收进清单,用正则把 http/https 链接揪出来,顺手去重。
(标准库,无需安装)
import re
defextract_links(text):
pat = r"https?://[^\s,。、))]+"
links = re.findall(pat, text)
seen, out = set(), []
for u in links:
if u notin seen:
seen.add(u)
out.append(u)
return out
text = "参考 https://a.com 和 https://a.com 还有 http://b.org/x 都不错"
print(extract_links(text))
小提示:正则只认 http/https 开头;遇到被中文标点截断的链接,把字符集里的 ,。、)) 按需增减即可。返回的是去重后的列表,直接落文件就是一份干净的链接清单。
约好的事想落进日历,不依赖任何平台,直接用标准库写一份 .ics 文件,双击就能导入系统日历或邮件客户端。
(标准库,无需安装)
from datetime import datetime, timedelta
defmake_ics(path, title, start, dur_min=60):
end = start + timedelta(minutes=dur_min)
fmt = "%Y%m%dT%H%M%S"
ics = [
"BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//py//CN",
"BEGIN:VEVENT",
f"UID:{id(title)}@py",
f"DTSTART:{start.strftime(fmt)}",
f"DTEND:{end.strftime(fmt)}",
f"SUMMARY:{title}",
"END:VEVENT", "END:VCALENDAR",
]
with open(path, "w", encoding="utf-8") as fp:
fp.write("\n".join(ics))
make_ics("meeting.ics", "周会", datetime(2026, 9, 1, 10, 0), 30)
小提示:生成的 meeting.ics 双击即可导入 Windows 日历、Outlook 等;时间按本地时间写,若需要 UTC 把格式改成 Z 结尾并补 TZID 字段即可。
做界面、写文档常常缺几个占位图标,SVG 是纯文本格式,用标准库直接拼字符串就能批量产,浏览器或编辑器都能直接开。
(标准库,无需安装)
defsvg_icon(path, color="#4f8cff", shape="circle"):
if shape == "circle":
body = f'<circle cx="50" cy="50" r="40" fill="{color}"/>'
elif shape == "rect":
body = f'<rect x="15" y="15" width="70" height="70" rx="10" fill="{color}"/>'
else:
body = f'<polygon points="50,10 90,90 10,90" fill="{color}"/>'
svg = f'<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100">{body}</svg>'
with open(path, "w", encoding="utf-8") as f:
f.write(svg)
for name, c, s in [("a.svg", "#ff6b6b", "circle"),
("b.svg", "#4ecdc4", "rect"),
("c.svg", "#ffd93d", "triangle")]:
svg_icon(name, c, s)
小提示:SVG 是矢量图,放大不糊;改 cx/cy/r 或往里加 <text> 元素,就能做成带字的小图标,批量生成一套 UI 占位图很方便。
Conway 生命游戏是经典的元胞自动机:给一个初始格局,按固定规则一代代演化。用标准库在终端里跑动画,看图案自己生长、消散,挺上头。
(标准库,无需安装)
import os, time
defstep(g):
h, w = len(g), len(g[0])
n = [[0] * w for _ in range(h)]
for y in range(h):
for x in range(w):
k = sum(g[(y + dy) % h][(x + dx) % w]
for dy in (-1, 0, 1) for dx in (-1, 0, 1)
if (dy, dx) != (0, 0))
n[y][x] = 1if (g[y][x] and k in (2, 3)) or (not g[y][x] and k == 3) else0
return n
g = [[1if (x * y) % 3 == 0else0for x in range(20)] for y in range(10)]
for _ in range(20):
os.system("cls"if os.name == "nt"else"clear")
print("\n".join("".join("█"if c else" "for c in row) for row in g))
g = step(g)
time.sleep(0.2)
小提示:示例用的是随机初值;想看经典图形,把 g 换成「滑翔机」「脉冲星」等固定坐标即可。规则是「活细胞周围 2~3 个活邻居存活,死细胞恰好 3 个邻居诞生」,边界用取模做成环形相连。
这六个脚本一半是能直接在终端玩起来的小项目(数独、井字棋、生命游戏),一半是能落进日常的零碎处理(链接提取、日程文件、矢量图标)。它们共同点是「用标准库就能跑、代码量都不大」,正好适合攒成一个自己的小仓库,随用随取。