返回列表 发帖

[游戏娱乐] 批处理生成UBB彩虹代码

本帖最后由 CrLf 于 2015-12-26 05:16 编辑

改进自:http://www.bathome.net/redirect. ... id=38720&pid=179971
优化算法,提升效率,平衡取值,并加上了详细注释

....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................
....................................................................................................................................................................................................


代码和详解:
@echo off & setlocal enabledelayedexpansion
rem 此处变量用于设置彩虹的各项参数
set /a n1=400,n2=250
rem n1 = 大圆半径
rem n2 = 小圆半径
set /a Lines=350
rem Lines = 彩虹行数
set /a stepCol=4,stepRow=17
rem stepCol = 列的间隔比例,用于定义一个字符的宽度对应半径中多少点
rem stepRow = 行的间隔比例,用于定义一个字符的高度对应半径中多少点
rem 关键代码从这里开始
if !stepCol! lss !stepRow! (
        set /a stepTest=stepCol
) else (
        set /a stepTest=stepRow
)
rem 若列的间隔小于行,则将在 x 轴上计算 RGB,否则在 y 轴上计算
rem 选用最小的间隔可以保证在计算 RGB 时取得较大的精度
set "Count=0"
rem Count 变量用于统计取样计算的 r2 和 RGB 总数
for /l %%b in (0 %stepTest% %n1%) do (
        rem 从原点出发在 x 轴或 y 轴上的半径范围内取样
        set /a r1=%%b*%%b-n1*n1
        rem r1 是该点上勾股算法的结果,用于判断是否在大圆内
        if !r1! leq 0 (
                rem 若在大圆内,则再进行小圆判断
                set /a r2=%%b*%%b-n2*n2
                rem r2 是该点上勾股算法的结果,用于判断是否在小圆内
                if !Count!==0 set /a rMin=r[0]=!r2!
                rem 若没有触碰过小圆,则记录 r2 为最小值,并顺便设置 r[0]
                if !r2! geq 0 (
                        rem 若在小圆内,则进行记录
                        set /a Count+=1,rMax=r2
                        rem Count 加一,并记录 r2 为最大值
                        for %%z in (!Count!) do set "r[%%z]=!r2!"
                        rem 记录 r2 到 r[*] 变量组
                )
        )
)
for /l %%a in (1 1 7) do set /a "p%%a=Count-(7-%%a)*Count/7"
rem 计算将 Count 切分为 7 段时每段的边界,并保存在 p* 变量组
for /l %%z in (0 1 !Count!) do (
        rem 对 r[*] 中的每一个 r2 计算对应 RGB 值
        set /a R=G=B=0
        rem 初始化 R G B 变量,默认为 0
        if %%z lss !p2! set /a "R=255-255*(%%z)/(p2)"
        if %%z geq !p3! if %%z lss !p4! set /a "R=(255*(%%z-p3)/(p4-p3))"
        if %%z geq !p4! set /a "R=255"
        rem 计算 R 值:
        rem 0~1 段 : 0xff -> 0x00
        rem 3~4 段 : 0x00 -> 0xff
        rem 4~7 段 :         0xff
        if %%z lss !p2! set /a "G=255*(%%z)/(p2)"
        if %%z geq !p2! if %%z lss !p4! set /a "G=255"
        if %%z geq !p4! if %%z lss !p7! set /a "G=255-255*(%%z-p4)/(p7-p4)"
        rem 计算 G 值:
        rem 1~2 段 : 0x00 -> 0xff
        rem 2~4 段 :         0xff
        rem 4~7 段 : 0xff -> 0x00
        if %%z lss !p2! set /a "B=255"
        if %%z geq !p2! if %%z lss !p3! set /a "B=255-255*(%%z-p2)/(p3-p2)"
        rem 计算 B 值:
        rem 0~2 段 :         0xff
        rem 2~3 段 : 0xff -> 0x00
        set /a RGB=R*256*256+G*256+B
        rem 组合 RGB 值
        cmd /c "exit /b %%RGB%%"
        set "RGB[%%z]=#!=ExitCode:~-6!"
        rem 转 16 进制并截取后 6 位,保存到 RGB[*] 数组中
)
set /a StartRow=stepCol/2-n1
set /a StartCol=stepRow/2
rem 计算起始点
rem 为了尽量避免出现单点的行,从小圆半径向外偏移半步处开始计数
set /a EndRow=Lines-n1
set /a EndCol=n1-stepCol/2
rem 计算终止点
rem 在大圆半径向内偏移半步处终止
(for /l %%a in (%StartRow% %stepRow% %EndRow%) do (
        rem 从顶部遍历到 Lines 指定的位置
        set "ubb="
        rem 在行首将 ubb 变量设置为空
        for /l %%b in (%StartCol% %stepCol% %EndCol%) do (
                rem 从原点偏半步处向右计算,将计算的结果左右对称,以减半计算量
                set "fontcolor=white"
                rem 字体颜色默认为白
                set /a r2=%%a*%%a+%%b*%%b-n2*n2
                rem 计算 r2,用于和前面生成的索引进行比对
                if !r2! geq !rMin! if !r2! leq !rMax! (
                        rem 如果 r2 在最大值和最小值之间,则判断该点离圆心的距离最接近 r[*] 中的哪个点
                        for /l %%z in (0 1 !Count!) do (
                                if !r[%%z]! leq !r2! set "fontcolor=!RGB[%%z]!"
                                rem 根据比对结果的索引号到 RGB[*] 数组中取得相应 RGB 值
                        )
                )
                set "ubb=[color=!fontcolor!].[/font]!ubb![color=!fontcolor!].[/font]"
                rem 将结果对称附加到该行 ubb 左右
        )
        echo;!ubb!
        rem 输出该行 ubb
)) >ubb.txt
start ubb.txt
rem ......COPY

本帖最后由 aa77dd@163.com 于 2015-12-26 18:09 编辑

我用了一个位运算选择器:
令 t 的可选值为 0 或者 -1,
~t & a | t & b
上式的值: 当 t = 0, 得 a; 否则, 得 b

这个选择器可以多层嵌套
~t & a | t & (~t1 & b | t1 & c) 以此类推

这样多层嵌套后, 就可以实现在小范围内索引区间搜索, 最开始我也想用 for + if 的方式实现, 然后又觉得效率不高, 特别是批处理的 for 代码在退出前 都不能 break

但 set /a 构造 的这种多层嵌套选择器 是否 比 for + if 效率要高, 也只是我想当然, 实际上我并没有测试比较过

以下示例 在 5 个数中找出 不大于 x 的最大的一个数
@echo off
setlocal enableDelayedExpansion
set "@1=18225"
set "@2=17956"
set "@3=17689"
set "@4=17424"
set "@5=17161"
set "exp=0"
for /L %%i in (5 -1 1) do (
    set "exp=t=x-@%%i>>31,~t&@%%i|t&(!exp!)"
)
set exp
set /a "x=17688,result=(%exp%)"
set result
pause
exitCOPY

TOP

本帖最后由 CrLf 于 2015-12-26 21:28 编辑

回复 2# aa77dd@163.com


    位运算是不错,应该比 if 快
    再优化一下,!(@%%i/t) 仔细想一想还是减法配合 >> 更快

TOP

返回列表