1.0 准备开始
我们先制定一个计算结构体,一切开始于此。
我们首先需要知道参与计算的 算子有多少,我们就按最常用的数49来制定。
type DataTao struct {
DefMean map[int]string // 卦象坐标名称
DefValue map[int]string // 卦象坐标值 4个
GuaData []int // 卦象的 6爻初始值
Indent int // 格式化输出间隔
Env int // 影响偏差,Env 把一年分为 3个部分,每个部分4个月,这个值可以影响天地分开的比例,自己随意
Total int // 大衍之数 个数
PrintLevel int // 计算过程显示控制,如果为 1 则显示
Coordinate map[int]string //卦象坐标的 爻,古称
}
制作该计算对象的构造函数
/*
@param env 环境参数
@param indent 格式化输出的缩进
@param total 天地 大衍数 49
*/
func MakeNewDataTao(env string, indent, total int) *DataTao {
envNum := map[string]int{"A": 1, "B": 0, "C": 2}
guaCoor := map[int]string{6: "六", 7: "七", 8: "八", 9: "九"}
var envLevel = 0
if indent <= 0 {
indent = 8
}
if env != "" {
envLevel = envNum[env]
}
if total < 49 {
total = 49
}
newData := &DataTao{
DefMean: defMean,
DefValue: guaCoor,
GuaData: []int{},
Indent: indent,
Env: envLevel,
Total: total,
PrintLevel: envNum["A"],
Coordinate: Coordinates,
}
return newData
}
1.1 开天辟地,创建爻变
创建天地大衍之数,创建一个新的天地列表 大衍之数,使用49
func (dt *DataTao) NewCircle() []int {
var newCir []int
for i := 0; i < dt.Total; i++ {
newCir = append(newCir, i)
}
return newCir
}
由于每一变 除以4的余数可能为 0,此时需要拿走4个算子,所以,3变最多需要12个算子,而分天地,
默认随机算法 计算后 将其值 限定为下限 12,上限 37,为什么要如此限定,就在于变爻的初始算子数量。
func (dt *DataTao) SplitNum(topNum int) int {
/*
Seed 使用提供的种子值将生成器初始化为确定性状态。
Seed 不应与任何其他 Rand 方法同时调用。
*/
rand.Seed(time.Now().UnixNano())
top := topNum - 4
sn := rand.Intn(top) + 4 // A random int in [4, 45]
if dt.Env != 0 {
if dt.Env == 1 {
sn = sn + (dt.Env * 3)
} else {
sn = sn + (dt.Env * 2)
}
}
if sn < 4 {
sn = 4
}
if sn > topNum - 4 {
sn = topNum - 4
}
logger.Printf("outcome sn:%v with topNum:%v\n", sn, topNum)
return sn
}
1.1.1 创建爻变,得天地人三才
从天,地随机选择一方,拿出一个算子 作为天地人的 人才 // 分三才 从选定的一方 得一人
func (dt *DataTao) RandLis(lis []int) ([]int, int) {
rand.Seed(time.Now().UnixNano())
if len(lis) < 2 {
return lis, 0
}
t := rand.Intn(len(lis) - 1)
ren := lis[t]
lis = append(lis[:t], lis[t+1:]...)
return lis, ren
}
推算的主要过程就是爻变的操作,每一爻都需要有3次爻变,最后得出一爻,我们先实现一变 //做一变
/*
@param: lis, 天地混沌,需要分开的算子集合
@param: sn, 从算子集合的哪一个位置执行分开
// 做一变,为得一爻
*/
func (dt *DataTao) DoOneYao(lis []int, sn int) []int {
//分天地
tian := lis[:sn]
di := lis[sn:]
var ran int
//从天地 取一人
rand.Seed(time.Now().UnixNano())
r := rand.Intn(2)
if r == 0 {
tian, ran = dt.RandLis(tian)
} else {
di, ran = dt.RandLis(di)
}
//一变
var tia, d, newOrigin []int
xt := len(tian) % 4
if xt == 0 {
//取 4个
tia = tian[:4]
tian = tian[4:]
} else {
tia = tian[:xt]
tian = tian[xt:]
}
dtv := len(di) % 4
if dtv == 0 {
d = di[:4]
di = di[4:]
} else {
d = di[:dtv]
di = di[dtv:]
}
//返回一变
newOrigin = append(tia, d...)
newOrigin = append(newOrigin, ran)
if dt.Env == dt.PrintLevel {
SixYao = append(SixYao, newOrigin)
logger.Println("余天:", tian, "\n余地:", di, "\n变数:", newOrigin, "人才:", ran, "\n新天地:", len(tian)+len(di))
logger.Println("已变总数:", len(SixYao))
}
newDT := append(tian, di...)
return newDT
}
每一个爻都需要对 天地大衍之数做三变,最后剩下的算子数 除以4 就是 一爻,算6次爻 那么就是一卦。 // 连续三变 得一爻,返回新天地
func (dt *DataTao) TianDiYao(lis []int) ([]int, int) {
/*
分天地 进行 变一
:param lis:
:param sn:
:return: 最后的 天,地,归档人列表, 和 爻 值
*/
finalTiandi := lis
for _, k := range []int{1, 2, 3} {
if dt.Env == dt.PrintLevel {
logger.Println("第", k, "变")
}
finalTiandi = dt.DoOneYao(finalTiandi, dt.SplitNum(len(finalTiandi)))
}
yao := len(finalTiandi) / 4
if dt.Total > 49 {
db := dt.Total / 49
yao := yao / db
if dt.Env == dt.PrintLevel {
logger.Println("大衍之数:", dt.Total, "三变后的爻:", yao, "距离 倍数 db:", db, "新天地:", len(finalTiandi))
}
}
if dt.Env == dt.PrintLevel {
logger.Println("三变后的爻:", yao)
}
return finalTiandi, yao
}
1.1.2 创建爻变, 得到6爻 即一卦
计算6个爻 则需要 3变 6次,并使用上一节的双向链表保存结果。 // 推演函数,开天辟地,并计算6爻
func (dt *DataTao) SuanGua() *dlist {
// gua := []int{}
logger.Printf("开始占卜运势...")
for i := 1; i < 7; i++ {
nc := dt.NewCircle()
if dt.Env == dt.PrintLevel {
logger.Println(len(nc), nc, dt.SplitNum(len(nc)))
}
///分天地人
ft, y := dt.TianDi(nc)
if dt.Env == dt.PrintLevel {
logger.Println("新天地:", ft)
logger.Println(dt.Coordinate[i]+dt.DefValue[y], "\n第", i, "爻", y, dt.DefMean[y])
}
time.Sleep(time.Millisecond * 100)
// gua = append(gua, y)
ResultNodes.append(&node{number: y})
}
return ResultNodes
}
小结
本小节 我们实现了推演运势的过程,在下一小节,我们将实现对链表的数据读取 和 爻象的解读,然后以直观的方式给用户展示。
标签:tian,di,int,运势,链表,sn,lis,dt,爻卦 From: https://blog.51cto.com/u_16190327/6834523