ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

用Python实现六爻起卦算法:从随机数生成到卦象匹配的完整项目实践

用Python实现六爻起卦算法:从随机数生成到卦象匹配的完整项目实践 简介这是一套面向易学研究者、前端开发者及传统文化爱好者的六爻占卜工具开源实现解决传统起卦流程繁琐、解析门槛高、跨端体验不一致等问题。资源为纯前端TypeScript工程共23个文件含10个tsx核心组件、5个ts业务逻辑与工具类、3个json配置文件含元数据与环境变量、2个html入口与资源页包体仅31KB轻量易部署。已有152人学习下载适合希望快速理解六爻排盘原理、定制化扩展卦辞解读或集成至自有应用的中初级开发者。源码结构清晰分层views层组织功能视图components封装卦象渲染如HexagramLines.tsx、摇卦交互Coin.tsx等原子模块services与utils提供时间排盘、六亲推演、伏神计算等核心算法预留接口支持历史记录、AI卦解等二次开发README.md详述运行与拓展方式。1. 项目概述从“玄学”到“算法”的现代实践最近在整理个人项目仓库时翻出了一个几年前写的“六爻起卦工具”的源码。这个项目源于一个非常个人化的需求我身边有不少对传统文化感兴趣的朋友他们偶尔会想用六爻来辅助决策或思考但传统的蓍草或铜钱起卦法步骤繁琐且随机性难以保证对于现代人来说时间和环境都不太允许。于是我就琢磨着能不能用代码来模拟这个“随机”的过程做一个既尊重传统逻辑又方便快捷的数字化工具这个工具的核心就是用程序来模拟三次投掷硬币或铜钱的过程根据正反面的组合生成一个“爻”重复六次得到完整的卦象并自动匹配《周易》六十四卦的卦辞、爻辞进行解读。这听起来有点“跨界”一边是古老的东方智慧一边是冰冷的计算机代码。但实际操作下来你会发现这本质上是一个随机数生成、状态映射和规则解析的经典编程问题。它不涉及任何“超自然”的信仰而是对一套既定规则系统的数字化实现。对于开发者而言这是一个绝佳的练手项目可以深入理解状态机、数据建模如何优雅地存储和查询六十四卦的复杂信息、以及如何设计一个清晰的用户界面来呈现结构化结果。对于传统文化爱好者它则是一个随时可用的“数字卦筒”消除了起卦过程中的物理限制和心理干扰让关注点回归到卦象本身的思考上。今天我就把这个项目的完整源码和设计思路分享出来。无论你是想学习如何用代码处理复杂规则系统还是单纯想拥有一个属于自己的起卦工具相信这份“干货”都能给你带来启发。我们将从核心算法讲起一步步拆解数据结构的构建、前后端的实现以及那些我踩过坑后才总结出的注意事项。2. 核心算法与规则的数字建模六爻起卦的规则是整個项目的基石。用代码实现的第一步就是必须把这些流传千年的规则毫无歧义地翻译成计算机能理解的逻辑。2.1 爻的生成三变得一爻传统方法是用50根蓍草经过“三变”得出一爻我们常用更简易的“钱币法”来模拟设定硬币正面有字面为数字3反面有图案面为数字2。一次投掷三枚硬币其总和只有四种可能6 222 三反老阴记为▅▅ ▅▅ X变爻7 322 一正两反少阳记为▅▅▅▅▅不变爻8 332 两正一反少阴记为▅▅ ▅▅不变爻9 333 三正老阳记为▅▅▅▅▅ O变爻在代码中这就是一个典型的随机数生成与条件判断。我们需要一个函数模拟一次投掷返回爻的类型和其对应的数值表示。import random def generate_yao(): 模拟三枚硬币投掷生成一个爻。 返回: (yao_type, yao_symbol, is_change) # 模拟三枚硬币随机生成3或2 coins [random.choice([2, 3]) for _ in range(3)] total sum(coins) if total 6: return old_yin, ▅▅ ▅▅ X, True # 老阴变爻 elif total 7: return young_yang, ▅▅▅▅▅, False # 少阳不变 elif total 8: return young_yin, ▅▅ ▅▅, False # 少阴不变 elif total 9: return old_yang, ▅▅▅▅▅ O, True # 老阳变爻 else: # 理论上不会发生但保持健壮性 raise ValueError(fInvalid coin sum: {total})注意这里的随机数生成器random使用的是伪随机算法对于此类应用完全足够。如果你追求更不可预测的随机源可以考虑接入系统熵池如os.urandom或让用户参与随机过程如要求用户输入一个随机字符串作为种子。但核心在于算法本身是对物理过程的模拟其“随机性”的哲学意义应由使用者自行理解。2.2 卦的构成从下到上的堆叠一个完整的卦由六个爻组成顺序是从下往上初爻、二爻、三爻、四爻、五爻、上爻。在程序中我们用一个列表来存储这六个爻的信息列表的第一个元素是初爻。def generate_gua(): 生成一个完整的六爻卦 gua [] for i in range(6): yao_info generate_yao() # 存储信息位置、类型、符号、是否为变爻 gua.append({ position: i 1, # 位置1为初爻 type: yao_info[0], symbol: yao_info[1], is_changing: yao_info[2] }) return gua2.3 本卦、变卦与动爻核心逻辑解析这是六爻推算中最精妙也最容易出错的部分。本卦最初生成的六个爻所直接对应的卦。动爻变爻在生成过程中标记为is_changing为True的爻即老阴或老阳。变卦将本卦中的所有动爻进行阴阳转换老阴变少阳老阳变少阴后得到的新卦。例如本卦的初爻是老阳▅▅▅▅▅ O那么在变卦中初爻就变为少阴▅▅ ▅▅。不变爻则保持不变。def get_changing_yao_indices(gua): 获取卦中所有变爻的位置索引0-based从初爻开始 return [i for i, yao in enumerate(gua) if yao[is_changing]] def apply_change(gua, changing_indices): 根据变爻索引生成变卦的爻列表 changed_gua [] for i, yao in enumerate(gua): if i in changing_indices: # 阴阳互变 if yao[type] old_yang: # 老阳 - 少阴 new_yao {position: yao[position], type: young_yin, symbol: ▅▅ ▅▅, is_changing: False} elif yao[type] old_yin: # 老阴 - 少阳 new_yao {position: yao[position], type: young_yang, symbol: ▅▅▅▅▅, is_changing: False} else: # 非动爻理论上不会进入此分支 new_yao yao.copy() changed_gua.append(new_yao) else: # 不变爻直接复制 changed_gua.append(yao.copy()) return changed_gua2.4 卦象匹配构建六十四卦数据库有了爻的列表我们需要将其映射到具体的六十四卦之一。六爻卦可以看作是两个三爻的“经卦”上下叠加而成。上卦四、五、上爻和下卦初、二、三爻各对应八卦之一。首先定义八卦# 用三位二进制表示八卦0为阴-1为阳—从下往上读。 # 例如乾 (111)坤 (000)震 (001)巽 (110)... BAGUA_MAP { (1, 1, 1): (乾, 天, ☰), (0, 0, 0): (坤, 地, ☷), (1, 0, 0): (震, 雷, ☳), (0, 1, 0): (坎, 水, ☵), (1, 1, 0): (艮, 山, ☶), (0, 0, 1): (巽, 风, ☴), (1, 0, 1): (离, 火, ☲), (0, 1, 1): (兑, 泽, ☱), }将爻转换为二进制少阳阳爻为1少阴阴爻为0。老阳和老阴在成卦时按其变化前的状态算即老阳为阳1老阴为阴0在变卦时则按变化后的状态算。然后根据上下卦的组合查询预置的六十四卦数据库。这个数据库需要包含卦序、卦名、拼音、上下卦组合、卦辞、彖辞、大象辞以及每一爻的爻辞和象辞。我选择用JSON文件来存储结构清晰且易于维护。// gua_data.json 片段 { 1: { sequence: 1, name: 乾, pinyin: Qián, upper: 乾, lower: 乾, hexagram: ䷀, gua_ci: 元亨利贞。, tuan_zhuan: 大哉乾元万物资始乃统天..., da_xiang: 天行健君子以自强不息。, yao: [ {position: 1, yao_ci: 潜龙勿用。, xiang_ci: 潜龙勿用阳在下也。}, {position: 2, yao_ci: 见龙在田利见大人。, xiang_ci: 见龙在田德施普也。}, // ... 其余四爻 ] }, 2: { sequence: 2, name: 坤, pinyin: Kūn, upper: 坤, lower: 坤, hexagram: ䷁, // ... 其他字段 } // ... 其余62卦 }实操心得构建这个数据库是最耗时但也是最基础的一步。务必核对古籍确保卦辞、爻辞的准确性。我最初从网络爬取的数据存在不少错漏和格式问题手动校对了一遍才敢用。此外爻辞的索引一定要与爻位初、二、三、四、五、上严格对应这是后续查询的关键。3. 系统架构与模块化实现一个完整的工具不能只有算法还需要考虑用户交互和数据流转。我采用了前后端分离的简单架构后端提供核心计算和卦辞查询API前端负责展示和交互。3.1 后端设计Python Flask 应用后端主要负责三件事生成卦象、查询卦辞、提供API接口。使用Flask是因为它轻量、快速非常适合这类小型工具。核心文件结构/backend ├── app.py # Flask主应用 ├── gua_generator.py # 起卦算法模块 ├── gua_lookup.py # 卦象查询模块 ├── data/ │ └── gua_data.json # 六十四卦数据库 └── requirements.txt # 依赖列表app.py主要代码片段from flask import Flask, jsonify, request from gua_generator import generate_full_guas # 导入封装的起卦函数 from gua_lookup import lookup_gua_by_yao, get_gua_detail import json app Flask(__name__) app.route(/api/generate, methods[GET]) def api_generate(): 生成卦象的API端点 try: # 调用核心算法得到本卦、变卦、动爻信息 original_gua, changed_gua, changing_positions generate_full_guas() # 查询本卦和变卦的详细信息 original_gua_detail lookup_gua_by_yao(original_gua) changed_gua_detail lookup_gua_by_yao(changed_gua) # 获取动爻的爻辞只取本卦中动爻的爻辞 changing_yao_details [] for pos in changing_positions: # pos是1-based的爻位 yao_info original_gua_detail[yao][pos-1] # 获取对应爻辞 changing_yao_details.append({ position: pos, yao_ci: yao_info[yao_ci], xiang_ci: yao_info[xiang_ci] }) response { success: True, data: { original_gua: original_gua_detail, changed_gua: changed_gua_detail, changing_yao: changing_yao_details, changing_positions: changing_positions } } return jsonify(response) except Exception as e: return jsonify({success: False, error: str(e)}), 500 app.route(/api/gua/int:sequence, methods[GET]) def api_get_gua(sequence): 根据卦序查询卦的详细信息 detail get_gua_detail(sequence) if detail: return jsonify({success: True, data: detail}) else: return jsonify({success: False, error: 卦未找到}), 404 if __name__ __main__: app.run(debugTrue, port5000)gua_generator.py封装这个文件整合了第二章节的所有算法函数提供一个干净的接口generate_full_guas()一次性返回本卦爻列表、变卦爻列表和动爻位置。3.2 前端设计Vue.js 单页应用前端的目标是提供一个直观、美观的界面展示卦象、爻变、卦辞和爻辞。我选择了Vue 3因为它响应式系统能很好地处理卦象状态变化。核心组件GuaDisplay.vue负责渲染卦象。将六个爻垂直排列从初爻到上爻并用不同的样式或颜色高亮显示动爻如老阳加红色边框老阴加蓝色边框。变卦可以并列显示或通过切换查看。InfoPanel.vue展示卦的详细信息。包括卦名、卦象图、卦辞、彖传、大象传。通过标签页Tabs切换显示本卦和变卦的信息。YaoDetail.vue如果存在动爻这个组件会突出显示所动之爻的爻辞和小象传这是解卦时重点参考的内容。ControlPanel.vue包含“起卦”按钮。点击后调用后端/api/generate接口获取新卦数据并更新整个应用状态。关键交互逻辑在Vue的setup中import { ref } from vue; import axios from axios; const originalGua ref(null); const changedGua ref(null); const changingYao ref([]); const isLoading ref(false); const generateGua async () { isLoading.value true; try { const response await axios.get(http://localhost:5000/api/generate); if (response.data.success) { const data response.data.data; originalGua.value data.original_gua; changedGua.value data.changed_gua; changingYao.value data.changing_yao; // 更新UI... } } catch (error) { console.error(起卦失败:, error); // 提示用户 } finally { isLoading.value false; } };注意事项前端展示爻象时字符的兼容性很重要。我使用了▅▅▅▅▅和▅▅ ▅▅这样的Unicode块字符来模拟阳爻和阴爻并在动爻后加上O和X标记。虽然不如真正的卦画美观但在绝大多数终端和浏览器中都能正确显示。如果你想追求更完美的显示可以考虑使用SVG绘制或者引入专门的易经字体。4. 数据持久化与高级功能探讨基础功能实现后可以考虑增加一些提升用户体验和项目深度的功能。4.1 起卦记录与复盘很多使用者希望回顾之前的卦象。我们可以增加简单的本地存储功能。前端使用localStorage或IndexedDB存储每次起卦的结果时间戳、卦象数据、用户输入的简要问题。数据结构const record { id: Date.now(), timestamp: new Date().toISOString(), question: userQuestion, // 用户输入的问题 originalGua: originalGua.value, changedGua: changedGua.value, changingYao: changingYao.value }; // 存入 localStorage const history JSON.parse(localStorage.getItem(gua_history) || []); history.unshift(record); // 新的放前面 localStorage.setItem(gua_history, JSON.stringify(history.slice(0, 100))); // 只保留最近100条界面增加一个“历史”页面以列表形式展示记录点击可查看详情。4.2 手动指定动爻与自定义起卦为了满足学习或特定场景的需求可以增加“手动模式”。功能提供一个交互式的六爻画板让用户可以点击每个爻来切换阴阳状态少阳/少阴并手动标记某个爻为“动爻”老阳/老阴。实现这需要修改后端的api/generate接口使其能接收一个代表六个爻状态的数组作为POST参数然后根据这个固定状态生成卦象和变卦而不是随机生成。app.route(/api/generate/custom, methods[POST]) def api_generate_custom(): data request.json custom_yao_states data.get(yao_states) # 例如 [young_yang, old_yin, ...] # 根据自定义状态生成卦...4.3 卦象解读提示系统谨慎实现这是一个更进阶也更敏感的功能。核心是不提供“算命式”的断言而是建立一个关键词库或语境提示系统。思路为每一卦、每一爻的辞句提取关键意象如“乾卦”关联“刚健”、“开创”、“领导”“潜龙勿用”关联“等待时机”、“积蓄力量”。当用户输入一个简短的问题如“问事业发展”时系统可以高亮显示卦辞爻辞中与“事业”、“发展”、“行动”相关的关键词句。实现在gua_data.json中为每条辞句增加一个tags字段包含一些中性关键词。前端提供一个简单的输入框让用户描述所问之事。后端进行非常基础的文本匹配或使用更简单的规则返回匹配到的标签前端据此进行视觉上的强调。重要警告这个功能必须严格设计只能作为“文本高亮”或“信息归类”工具绝不能输出任何结论性、预测性的语句。界面应明确标注“以下内容为古籍原文解读因人因事而异仅供参考与思考。”5. 部署、优化与常见问题5.1 项目部署指南想让别人也能用上你的工具就需要部署。后端部署推荐使用Vercel(Python Runtime) 或Railway。它们对Flask应用支持友好有免费额度。关键是修改app.py最后一行监听0.0.0.0和PORT环境变量提供的端口。if __name__ __main__: port int(os.environ.get(PORT, 5000)) app.run(host0.0.0.0, portport)前端部署构建生产版本 (npm run build)将生成的dist文件夹内的静态文件部署到Netlify、Vercel (Static)或GitHub Pages。这些平台都提供免费的自动化部署。连接前后端部署后前端需要知道后端API的地址。在Vue项目中可以通过环境变量来配置。// .env.production VITE_API_BASE_URLhttps://your-flask-backend.vercel.app然后在代码中引用axios.create({ baseURL: import.meta.env.VITE_API_BASE_URL })。5.2 性能优化与代码质量卦辞数据库加载每次请求都读取和解析JSON文件是低效的。应该在服务启动时就将gua_data.json加载到内存中作为一个全局字典或缓存对象。import json with open(data/gua_data.json, r, encodingutf-8) as f: GUADATA json.load(f) # 后续查询都从 GUADATA 这个字典中获取前端懒加载如果卦辞内容非常长可以考虑在用户点击查看详情时再动态加载该卦的完整爻辞而不是一次性全部加载。错误处理与日志在后端关键函数中添加try...except并记录日志便于排查线上问题。5.3 常见问题与排查实录在开发和用户反馈中我遇到了以下几个典型问题生成的卦象总是某几个卦排查检查随机数生成函数generate_yao。最常见的原因是随机数种子被固定或者硬币正反面的概率模拟不均等random.choice([2, 3])是等概率的没问题。确保在每次起卦时没有重置随机种子。解决使用random.SystemRandom()或在生成前引入时间戳等变化量作为种子。变卦查询结果错误或为空排查这是最复杂的逻辑错误。首先打印出本卦和变卦的爻列表确认阴阳转换是否正确。其次检查lookup_gua_by_yao函数。确保它正确地将爻列表包含老阴老阳转换成了用于查询的“成卦”二进制码老阴作阴老阳作阳。调试技巧写一个单元测试固定一组爻手动计算它应该对应的卦然后看程序输出是否一致。前端显示乱码或卦画错位排查Unicode字符渲染问题。确保HTML文件指定了UTF-8编码 (meta charsetUTF-8)。对于卦画字符有些字体可能不支持可以在CSS中指定一个更通用的字体族如font-family: SimSun, NSimSun, serif;宋体通常支持较好。部署后API请求失败CORS错误现象前端控制台报错Access-Control-Allow-Origin。解决在后端Flask应用中安装并启用CORS支持。from flask_cors import CORS app Flask(__name__) CORS(app) # 允许所有来源生产环境应指定具体前端地址用户觉得“不灵”或“不准”定位这不是技术问题而是产品定位问题。应对在工具醒目位置添加说明明确告知“本工具是一个基于随机数生成算法对传统六爻起卦方法的程序化模拟其结果不具备任何神秘学意义。旨在为传统文化爱好者提供一种便捷的参考和研习方式请理性看待切勿沉迷。” 将工具的定位从“占卜”转向“文化学习与模拟”可以避免很多不必要的争议。这个项目从构思到实现再到不断打磨让我深刻体会到将一套复杂的传统规则系统进行数字化封装最大的挑战不是技术而是对原始规则的精确理解和严谨翻译。每一行代码背后都需要对古籍原文的反复揣摩。最终产出的不仅是一个工具更是一个结构化的、可交互的“周易”数据模型。无论你对它的态度是文化研究、编程练习还是单纯的兴趣使然这个过程本身就是一种充满乐趣的探索。本文还有配套的精品资源点击获取
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进