找回密码
 点一下
查看: 2918|回复: 6

Timer-Location 存储系统

[复制链接]
发表于 2009-4-28 17:00:32 | 显示全部楼层 |阅读模式
[jass]
//说明:
//    这是一个通过点保存Handle,并组成链表的存储系统。存储的单元式项。每个项都可以构成一个链表以存储Handle、Integer、Real型的变量。
//    这个系统需要在初始化时建立,SetUpSystem为建立系统的过程,参数max为这个系统的最大项数,因为这个系统没有使用数组,所以这个最大值可以超过数组上限8192。
//    不过具体值请根据需要设置,过高会降低系统中某些函数的效率,过低有可能因为存储系统存满而出现问题。
//    为了通用化并减少代码,输入的参数是一个可以三种类别的值(Real、Handle、Integer三种皆可以,一般都是存储的或用于查找的变量)时,都是只写了Real型参数的函数,其他型请自行转换成Real型参数。
//     
//定义:
//    英文名称的都是变量类型,也对应这种类型的变量,比如Timer指计时器变量,Location指点变量。
//    项:就是包括一个Timer,一个作为索引和辅助的Location,一个保存存储链表的第一个元素的Location,以及通过一系列Location组成的链表。
//    节点:项中的链表的存储映像,实际上就是一个Location,这个Location的X轴坐标值是下一个结点的Handle,Y轴坐标是这个结点存储的值。也就是说Location的X轴为指针域,Y轴为数据域。
//    点:特指初始化给每个项的那两个Location,即项中的辅助点和链表的第一个结点这两个Location,分别以第一点和第二点命名。
//    第一点:每一项所包含的固定内容之一,实质是一个Location,X轴坐标存储的是这一项的链表的最后一个结点的Hnadle值,Y轴坐标存储的是自定义内容,这里我作为索引项。
//    第二点,是项中链表的第一个结点,X轴坐标是第二个结点的Handle值,Y轴是存储的数据。
//    序号:项在整个系统中的序号,即在以物理地址为序的表中的位置,第二点的序号为0,其后依次增加。
//    存储上限:即系统能够存储的项的最大值,这个是初始化时自行给定的。
//    Handle值:不同于Handle代表着一个Handle型变量,Handle值代表的是Handle型变量转换成的整数。
//
globals
    timer                   udg_UseTimer               = null
    //当前使用的Timer                                 
    location                udg_UseLocat               = null
    //当前使用Location                                         
    integer                 udg_UseAddress             = 0
    //正在使用的Handle值
    integer                 udg_Maxnumber              = 0
    //预置的存储上限,可以大于8192
    integer                 udg_FirstAddress           = 0
    //存储系统首的第一个Timer的Handle值
    integer                 udg_NowNum                 = 0
    //当前使用的项的序号
endglobals

function SetUpSystem takes integer max returns nothing
    local integer N=1
    local integer udg_UseAddress =0
    local timer udg_UseTimer = null
    local location udg_UseLocat = null
    set udg_Maxnumber = max
    //设置存储上限为参数max
    set udg_UseTimer = CreateTimer()  
    set udg_FirstAddress = udg_UseAddress
    set udg_UseLocat = Location(I2R(udg_UseAddress + 2), -1)
    //第一点的X坐标是这个链表最后一个结点的handle值,Y坐标是用于判断项的索引的handle值(或integer与real,也可以保存其他内容),-1代表未使用。
    set udg_UseLocat = Location(-1, -1)  
    //第二点的X坐标是这个链表下一个结点的handle值,Y坐标是这个节点存储的handle(或integer与real)。
    //链表的每个结点都是:X轴为指针域,Y轴为数据域,指针域、数据域为-1时代表空
    loop
        set N = N + 1
        exitwhen N > max
        set udg_UseTimer = CreateTimer()
        set udg_UseLocat = Location(I2R(udg_UseAddress + 2), -1)
        set udg_UseLocat = Location(-1, -1)
    endloop
    set udg_UseTimer = null
    set udg_UseLocat = null
    return
endfunction

function H2I takes handle h returns integer
    return h
    return 0
endfunction

function R2H takes integer i returns handle
    return i
    return null
endfunction

function GetIndex takes nothing returns  integer
    //获取一个新的空白项的序号  (0~udg_Maxnumber-1)
    local integer udg_UseAddress = 0
    local location udg_UseLocat  = null
    local integer TempInt = udg_NowNum
    loop  
        set udg_NowNum = udg_NowNum + 1   
        if udg_NowNum>=udg_Maxnumber then
             set udg_NowNum = 0
        endif
        set udg_UseAddress = udg_FirstAddress  + udg_NowNum * 3 + 2         
        exitwhen GetLocationY(udg_UseLocat) == -1
        //空白项的第二个点的Y坐标为-1,默认
        if udg_NowNum == TempInt then
             return -1
        endif
        //当前所有项都在使用中返回-1
    endloop
    set udg_UseLocat  = null
    return  udg_NowNum
endfunction
function InputData takes integer n ,real r returns nothing
    //存储某个值。n为存储到的项的序号,r为存储内容。
    local integer TempIntA = 0  
    local integer TempIntB = 0
    local location udg_UseLocat = null
    local integer udg_UseAddress = udg_FirstAddress  + n * 3 + 2
    if  GetLocationY(udg_UseLocat) == -1 then
        call MoveLocation( udg_UseLocat, GetLocationX(udg_UseLocat), r )
        return
    endif
    //当存储在第二点(链表第一个结点)时
    set udg_UseLocat = Location(-1, r)
    //创建Location并记录数据
    set TempIntA = udg_UseAddress
    //保存刚创建的点的Handle值
    set udg_UseAddress = udg_FirstAddress  + n * 3 + 1
    //获取序号为n的项第一点
    set TempIntB = R2I(GetLocationX(udg_UseLocat))
    //记录下当前的项的链表的最后一个结点的Handle值
    call MoveLocation( udg_UseLocat, I2R(TempIntA), GetLocationY(udg_UseLocat) )
    //修改项第一点所记录的最后一个结点的Handle值
    set udg_UseAddress = TempIntB
    //获得链表的最后一个结点
    call MoveLocation( udg_UseLocat, I2R(TempIntA), GetLocationY(udg_UseLocat) )
    //修改最后一个Location的X坐标(下一个结点的handle值),记录为存储输入数据的点的Handle值
    set  udg_UseLocat = null
    return
endfunction


function GetTimerByIndex takes integer n returns timer
    //通过序号获得对应Timer
    local timer udg_UseTimer = null
    local integer udg_UseAddress = udg_FirstAddress + n * 3
    return udg_UseTimer
endfunction


function SetIndexHandle takes integer n ,real r returns nothing
    //为项n添加索引的内容
    local location udg_UseLocat = null
    local integer udg_UseAddress = udg_FirstAddress  + n * 3 + 1
    call MoveLocation( udg_UseLocat, GetLocationX(udg_UseLocat), r )
    set udg_UseLocat = null  
    return
endfunction

function OutputLocationByTimer takes timer t,location l returns location
    //通过Timer获得对应项的第一个结点的Location ,参数中的Location是用于返回值的,使用时给为null就可以。
    local location udg_UseLocat = null
    local integer udg_UseAddress = 0
    local timer udg_UseTimer  = t
    //第一个结点的handle一定是对应计时器的handle+2
    set udg_UseAddress = udg_UseAddress + 2
    set l = udg_UseLocat
    set udg_UseLocat = null
    return l
endfunction

function OutputLocationByAll takes real r,location l returns location
    //通过作为索引的数据r获得第一个结点的Location。如果返回null则代表没有找到,索引内容参数中的Location是用于返回值的,使用时给为null就可以。
    //这里是用项的第一点的Y轴的值作为引对象的,也可直接使用第二点的Y轴的值来索引
    //为了不用为通过Integer或者Real来索引再写个函数,所以这里的参数类型 为Real,如果通过索引的是Handle或者Integer,请先转成Real再运行函数。
    local integer udg_UseAddress = 0
    local location udg_UseLocat  = null
    local integer N = udg_FirstAddress + 1
    loop  
        if N > udg_FirstAddress+udg_Maxnumber*3 then
             return null
        endif
        set udg_UseAddress = N         
        exitwhen GetLocationY(udg_UseLocat) == r
        set N = N + 3
    endloop
    set udg_UseAddress = udg_UseAddress + 1
    set l = udg_UseLocat
    set udg_UseLocat = null
    return l
endfunction

function OutputLocationByIndex takes integer n,location l returns location
    //通过项的序号n获得对应项的第一个结点的Location ,参数中的Location是用于返回值的,使用时给为null就可以。
    local location udg_UseLocat  = null
    local integer udg_UseAddress = udg_FirstAddress  + n * 3 + 2
    set l = udg_UseLocat
    set udg_UseLocat = null
    return l
endfunction

function OutputIndexByTimer takes timer t returns integer
    //通过Timer返回使用的项的INDEX (0~udg_Maxnumber-1)     
    local integer udg_UseAddress = 0
    local timer udg_UseTimer  = t
    local integer TempInt = (udg_UseAddress - udg_FirstAddress) / 3
    //第一个结点的handle一定是对应计时器的handle+2
    set udg_UseTimer =null
    return TempInt
endfunction

function OutputIndexByAll takes real r returns integer
    //通过作为索引的数据r获得Index
    //这里是用项的第一点的Y轴的值作为引对象的,也可直接使用第二点的Y轴的值来索引
    //为了不用为通过Integer或者Real来索引再写个函数,所以这里的参数类型 为Real,如果通过索引的是Handle或者Integer,请先转成Real再运行函数。  
    local integer udg_UseAddress = 0
    local location udg_UseLocat  = null
    local integer N = udg_FirstAddress - 2
    loop  
        set N = N + 3
        if N > udg_FirstAddress + udg_Maxnumber * 3 then
             return -1
             //-1代表没有找到对应索引。
        endif
        set udg_UseAddress = N         
        exitwhen R2I(GetLocationY(udg_UseLocat)) == r
    endloop     
    set N =  (udg_UseAddress - udg_FirstAddress - 1 ) / 3
    set udg_UseLocat = null
    return N
endfunction

function OutputIndexByLocation takes location l returns integer
    //通过链表的第一个结点l(Location)获得项的索引序号
    local integer udg_UseAddress = 0
    local integer TempInt = 0
    local location udg_UseLocat = l
    set TempInt = ( udg_UseAddress - udg_FirstAddress - 2 ) / 3
    set udg_UseLocat = null
    return TempInt
endfunction

function LoadData takes integer m,location l returns real
    //通过链表的第一个结点l,返回结点序号为m(第m+1个结点)的数据域的值。
    local integer udg_UseAddress = 0
    local integer N = 1
    local location udg_UseLocat  = null
    if m == 0 then
         return GetLocationY(l)
    endif
    //如果求的是第一个结点(m为0)的数据,那么直接返回值
    set udg_UseLocat = l
    loop
         set udg_UseAddress = R2I(GetLocationX(udg_UseLocat))  
         exitwhen N == m
         set N = N + 1
    endloop
    set l = udg_UseLocat
    set udg_UseLocat = null
    return GetLocationY(l)
    //寻找对应m的结点。
endfunction

function DestoryByIndex takes integer i returns nothing
    //通过Index清空存储的项。
    local location udg_UseLocat  = null   
    local integer udg_UseAddress = udg_FirstAddress + i * 3 + 1
    local integer TempIntA = R2I(GetLocationX(udg_UseLocat))
    local integer TempIntB = 0
    set TempIntB = udg_UseAddress + 1
    call MoveLocation( udg_UseLocat, I2R(TempIntB), -1)
    //获得最后一个结点的Handle,并修复第一个点
    set udg_UseAddress = udg_UseAddress + 1
    set TempIntB = R2I(GetLocationX(udg_UseLocat))  
    call MoveLocation( udg_UseLocat, -1, -1 )
    //获得下一个结点的Handle,并修复第二个点
    if TempIntB != -1 then
        loop
            set udg_UseAddress =  TempIntB
            set TempIntB = R2I(GetLocationX(udg_UseLocat))
            //获取下一结点Handle
            call RemoveLocation( udg_UseLocat )
            //删除结点
            exitwhen TempIntB == TempIntA
            //当当前结点的Y坐标(下一个结点的Handle)等于最后一个点的Handle时结束循环
        endloop
        set udg_UseAddress =  TempIntB
        call RemoveLocation( udg_UseLocat )
        set udg_UseLocat  = null
    endif
    return
endfunction

function DestoryByTimer takes timer t returns nothing
    //通过Timer清空存储的项。
    local location udg_UseLocat  = null
    local integer udg_UseAddress = 0
    local integer TempIntA = 0
    local integer TempIntB = 0
    local timer udg_UseTimer  = t
    set udg_UseAddress = udg_UseAddress + 1
    //第一点
    set TempIntA = R2I(GetLocationX(udg_UseLocat))
    //记录最后一个结点的Handle值
    call MoveLocation( udg_UseLocat, I2R(udg_UseAddress + 1), -1)
    //修复第一个点
    set udg_UseAddress = udg_UseAddress + 1
    //第二个点  
    set TempIntB = R2I(GetLocationX(udg_UseLocat))
    call MoveLocation( udg_UseLocat, -1, -1 )
    //获得下一个结点的Handle,并修复第二个点
    if TempIntB != -1 then
        loop
            set udg_UseAddress =  TempIntB
            set TempIntB = R2I(GetLocationX(udg_UseLocat))
            //获取下一结点Handle
            call RemoveLocation( udg_UseLocat )
            //删除结点
            exitwhen TempIntB == TempIntA
            //当当前结点的Y坐标(下一个结点的Handle)等于最后一个点的Handle时结束循环
        endloop
        set udg_UseAddress =  TempIntB
        call RemoveLocation( udg_UseLocat )
        set udg_UseLocat  = null
    endif
    return  
endfunction

function DestoryByHandle takes real r returns nothing
    //通过Handle清空存储的项。
    local integer TempInt = OutputIndexByAll( r )
    //调用 OutputHanTakeH
    call DestoryByIndex( TempInt )
    //调用 DestoryByIndex
    return
endfunction

function ChangeData takes integer n,integer m,real r returns nothing
    //通过索引n,结点序号m(0为第一个结点),替换数据r,替换索引为n的项的链表的第m个元素的内容。
    local integer udg_UseAddress = 0
    local integer N = 0  
    local location udg_UseLocat  = null
    if m < 0 then
         return
    endif
    set udg_UseAddress = udg_FirstAddress + n * 3 + 2
    loop
         if (GetLocationX(udg_UseLocat) == -1)and( N < m ) then
             return
         endif
         //保证替换的元素的序号不会大于链表最大元素数        
         exitwhen N == m
         set udg_UseAddress = R2I(GetLocationX(udg_UseLocat))
         set N = N + 1
    endloop
    //找到要插入的位置
    call MoveLocation( udg_UseLocat,GetLocationX(udg_UseLocat),r)
    set udg_UseLocat = null
    return
endfunction
[/jass]
注释写的很详细
需要说的只有一点
SetUpSystem这个函数因为执行上限的原因
不可能直接创建很多的项,不过我们可以使用某些函数来解决这个问题
不过具体哪个忘了……
另外这个代码没有纠错系统
如果获取空白点会跳出……

另外设计中这个存储系统是和数组变量系统配合使用的
数组变量系统

评分

参与人数 1威望 +55 收起 理由
kook + 55 终于看懂了一些

查看全部评分

发表于 2009-4-28 17:36:05 | 显示全部楼层
沙发入手
回复

使用道具 举报

发表于 2009-4-28 19:01:28 | 显示全部楼层
板凳一张
回复

使用道具 举报

发表于 2009-4-28 20:45:39 | 显示全部楼层
地毯一卷
回复

使用道具 举报

发表于 2009-4-29 08:53:13 | 显示全部楼层
做做沙发的人头上围观。
回复

使用道具 举报

发表于 2009-4-30 10:59:37 | 显示全部楼层
SetUpSystem那里需要初始化保证连续可用的handle地址吧,如果直接+2来设置的话

OutputIndexByAll那里是根据依次比较数据项来判断,如果多条链表中储存有相同的最后数据项(real),那不是只道第一条就跳出了吗?

希望我的理解没偏差太远。。
回复

使用道具 举报

 楼主| 发表于 2009-4-30 11:54:50 | 显示全部楼层
这个real是专门用于索引的
就是特别留出来的
如果我们绑定的不是一个计时器
那么我们就把要绑定到的对象存储在这里
(如果我们不使用提前创建的计时器,那么我们把创建的局域计时器的Handle保存在这里,因为我们不会为同一个计时器申请两个项,并且Handle值是不可能重复的,所以不会出现LS的问题)
因为我们不需要为绑定到同一Handle的内容创建两个项
所以一般式不会出现重复的
确实需要保证连续
类似TimerDataSystem

这个系统的索引方法有两个
一个是用创建好的计时器(项里那个)
一个事第一点的Y轴值(一般是索引的Handle值,比如绑定到的单位的handle)
如果用第二种方法的话,绑定到同一个handle的内容就需要放在一个项里
如果这些内容要分类的话
除了使用我那个数组变量系统把一类的东西放在一个数组里
也可以巧妙的使用这个地方的是实数这个变量类型
可以用小数部分区别
就是绑定到同一Handel的不同类别放在不同的项
这些项的索引的整数部分都是绑定到的handle值
用小数部分不同来区别
可以这样


另外,这个帖子被kook大人你忽略了
http://www.islga.org/bbs/read.php?tid=26756
未命名.JPG
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-4-24 03:38 , Processed in 0.153371 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表