cnCalc计算器论坛

 找回密码
 注册
搜索
查看: 5959|回复: 10

[Lua] 耗时一天折腾出《高尔顿钉板实验》的lua程序

[复制链接]
发表于 2012-7-23 22:50:09 | 显示全部楼层 |阅读模式
本帖最后由 zsdsgjb 于 2012-7-23 22:51 编辑

高尔顿钉板,又称高尔顿板,是英国生物统计学家高尔顿设计的用来研究随机现象的模型。     实验时,自板上端放入一小球,任其自由落下。在下落过程中,当小球碰到钉子时,从左边落下与从右边落下的机会相等,碰到下一排钉子也是如此。当投入大量的球时,其分布遵循正态分布。关于高尔顿及钉板实验详细介绍见:http://wenku.baidu.com/view/51b5ae95dd88d0d233d46a65.html      
    用Lua程序写出一个模拟实验程序,见如下截图:
23-07-2012 Image001.jpg
23-07-2012 Image002.jpg
23-07-2012 Image003.jpg
23-07-2012 Image004.jpg
23-07-2012 Image005.jpg
23-07-2012 Image006.jpg

高尔顿钉板 V1.0.tns

6.05 KB, 下载次数: 224

相关帖子

发表于 2012-7-24 21:41:01 | 显示全部楼层
1# zsdsgjb
不错,顶起。最好放出源码,方便改进
发表于 2012-7-25 10:18:33 | 显示全部楼层
这不就是杨辉三角么
发表于 2012-7-26 08:57:03 | 显示全部楼层
这个程序在没有LUA之前就已经有了
发表于 2012-7-27 17:50:41 | 显示全部楼层
你有兴趣坐下游戏吗??
 楼主| 发表于 2012-7-27 23:29:28 | 显示全部楼层
本帖最后由 zsdsgjb 于 2012-7-27 23:34 编辑

3楼朋友,这不是杨辉三角。5楼朋友,游戏我可能写不出来,只能写点简单的数学实验程序。4楼朋友,没Lua之前确实有这个TNS,但我研究了很久,一直不知道如何做出来的。附三个我一直没有研究清楚的TNS在后,欢迎大家研究作者是如何制作出来的,只是感觉这三个制作方法好像类似。

云登弹珠台.tns

15.15 KB, 下载次数: 176

骰子模拟器.tns

39.97 KB, 下载次数: 179

Buffon的针.tns

7.16 KB, 下载次数: 167

 楼主| 发表于 2012-7-27 23:32:19 | 显示全部楼层
2楼朋友,直接用最新的教师版软件可以打开看源码的。附源码在后:

-- 程序版权所有: 广东中山 高建彪  QQ: 76456245  E-mail:[email protected]  2012.07.23
platform.apiLevel = '1.0'
psb = {0,0,0,0,0,0,0,0,0,0} --频数初始值
syzs = 0 --实验总次数
anxz = 0 --按钮选择
andj = 0 --按钮点击
kszt = 2 --开始按钮状态, 2准备开始,1准备暂停,0准备继续
cs = 9 --层数
sdbl = 8 --速度变量
xqx = 0 -- 小球水平位置
xqy = 0 -- 小球垂直位置
kk  = 5 -- 开口宽度
cszd = 12 --层数最大
cszx = 6 --层数最小
pjz = "" --平均值
bzc = "" --标准差
function create()
    psbcsh()
end

--主程序
function on.paint(gc)
    gc:drawString("实验总次数: "..syzs,10,90)
    gc:drawString("平均值μ: "..pjz,10,120)
    gc:drawString("标准差σ: "..bzc,10,150)
    gc:setColorRGB(0,150,150)
    gc:drawString("按:[菜单],[Tab]",5,190)
    gc:drawString("或-,+,R,S,J,T",25,210)
   
    local kstxt = ""
    if kszt == 2 then
        kstxt = "开始(R)"
    elseif kszt == 1 then
        kstxt = "暂停(S)"   
    elseif kszt == 0 then
        kstxt = "继续(J)"        
    end
    anks = anniu(70,5,60,20,kstxt)
    anks:paint(gc)
    antz = anniu(70,30,60,20,"停止(T)")
    antz:paint(gc)
    gc:drawString("层数",15,25)
    local cspc = 10 - 5 * math.ceil(cs/9)
    gc:drawString(cs,22+cspc,50)
    anjs = anniu(5,30,15,20,"-")
    anjs:paint(gc)
    anzj = anniu(40,30,15,20,"+")
    anzj:paint(gc)
    if anxz > 0 then
        gc:setColorRGB(255,0,0)
        gc:setPen("medium","smooth")   
    end
    if anxz == 1 then
        gc:drawRect(70,5,60,20)
    elseif anxz == 2 then
        gc:drawRect(70,30,60,20)   
    elseif anxz == 3 then
        gc:drawRect(5,30,15,20)         
    elseif anxz == 4 then
        gc:drawRect(40,30,15,20)
    end
    gc:setColorRGB(0,0,0)
    gc:setPen("thin","smooth")
    db01 = dbmx(150,120,150,110,cs,xqx,xqy)
    db01:paint(gc)
    psb01 = psfbt(150,120,150,70,cs+1)
    psb01:paint(gc)

    if kszt == 2 then
        toolpalette.enable("实验控制","暂停",false)
        toolpalette.enable("实验控制","停止",false)
        toolpalette.enable("实验控制","继续",false)
        toolpalette.enable("实验控制","开始",true)        
    end
    if kszt == 1 then
        toolpalette.enable("实验控制","暂停",true)
        toolpalette.enable("实验控制","开始",false)
        toolpalette.enable("实验控制","停止",true)      
    elseif kszt == 0 then
        toolpalette.enable("实验控制","暂停",false)
        toolpalette.enable("实验控制","继续",true)
    end

end

function on.timer()
    xqy = xqy + 1
    local fx = math.random(0,1)
    if fx > 0.5 then
        xqx = xqx + 1
    else
        xqx = xqx - 1
    end
    if xqy > cs then
        xqy = 0
        xqx = 0
    end
    if xqy == cs then
        local ld = math.floor((cs+xqx)/2+1)
        psb[ld] = psb[ld]+1
        syzs = syzs + 1
        pl[ld] = math.floor(psb[ld]/syzs*100)/100
    end
    platform.window:invalidate()
end

--钉板模型
dbmx = class()
function dbmx:init(x,y,w,h,n,qx,qy)
    self.x = x   --钉板左下角x坐标
    self.y = y   --钉板左下角y坐标
    self.w = w   --钉板宽度
    self.h = h   --钉板高度
    self.n = n   --钉板层数
    self.qx = qx
    self.qy = qy
end

function dbmx:paint(gc)
    local x, y, w, h, n, qx, qy = self.x, self.y, self.w, self.h, self.n, self.qx, self.qy
    gc:drawLine(x-kk,y,x+w/2-kk,y-h)
    gc:drawLine(x+kk+w,y,x+w/2+kk,y-h)
    for i=1,n do
        for j=1,n+1-i do
            gc:drawArc(x+w/(n+1)*(i+(j-1)/2)-2,y-h/(n+1)*j,3,3,0,360)
        end
    end
    gc:setColorRGB(150,150,150)
    local wqx = x+w/2 - 4 + w/(2*(cs+1))*qx
    local wqy = y-h+3 + h/(cs+1)*qy
    gc:fillArc(wqx,wqy,8,8,0,360)
    gc:setColorRGB(0,0,0)
    gc:drawArc(wqx,wqy,8,8,0,360)
end

-- 频数图模型
psfbt = class()
function psfbt:init(x,y,w,h,s)
    self.x = x   --频数图左上角x坐标
    self.y = y   --频数图左上角y坐标
    self.w = w   --频数图宽图
    self.h = h   --频数图高度
    self.s = s   --频数图数据
end

function psfbt:paint(gc)
    local x, y, w, h, s = self.x, self.y, self.w, self.h, self.s
    gc:setColorRGB(0,0,0)  
    gc:setPen("thin","smooth")
    gc:drawLine(x,y+h,x+w,y+h)
    gc:drawLine(x,y,x,y+h)
    gc:drawLine(x+w,y,x+w,y+h)
    gc:setPen("thin","dotted")     
    gc:setColorRGB(150,150,150)
    local szzd = szmax(psb)
    local szws = table.getn(psb)
    for n=1,szws-1 do
        gc:drawLine(x+w/szws*n,y,x+w/szws*n,y+h)
    end
    if szzd > 0 then
        szzd = szzd + 0.5
        local zs0 = 0
        for n in pairs(psb) do
            gc:fillRect(x+(w/szws)*(n-1),y+h-h/szzd*psb[n],w/szws,h/szzd*psb[n])         
            zs0 = zs0 + pl[n]*qcbh[n]
            gc:setFont("serif","r",6)
            gc:drawString(pl[n]*100,x+(w/szws)*(n-1)+3,y+h+15)
            gc:drawString(psb[n],x+(w/szws)*(n-1)+3,y+h+25)
            gc:drawString(qcbh[n],x+(w/szws)*(n-1)+3,y+10)
        end
        gc:drawString("%",x+w,y+h+15)
        pjz = string.format("%5.2f",zs0)
        local fc0 = 0
        for n in pairs(psb) do
            fc0 = fc0 + (qcbh[n]-pjz)^2 * psb[n]
        end
        local fc1 = math.sqrt(fc0/syzs)
        bzc = string.format("%5.3f",fc1)
    end
end

function szmax(x) --数组最大值函数
    local max0 = 0
    for n in pairs(psb) do
        if max0 < psb[n] then
            max0 = psb[n]
        end
    end
    return max0
end


--按钮模型
anniu = class()
function anniu:init(x,y,w,h,t)
    self.x = x   --按钮左上角x坐标
    self.y = y   --按钮左上角y坐标
    self.w = w   --按钮宽度
    self.h  =h   --按钮高度
    self.t = t   --按钮文本
    self.s = false
end

function anniu:paint(gc)
    local x, y, w, h, t, s = self.x, self.y, self.w, self.h, self.t, self.s
    if s then
        gc:setColorRGB(255,0,0)
    else
        gc:setColorRGB(100,0,0)   
    end
    gc:setPen("thin","smooth")
    gc:drawRect(x,y,w,h)
    gc:drawString(t,x+3,y+20)
end

--鼠标指针事件
function on.mouseMove(x,y)
    if x>70 and x<130 and y>5 and y<25 then
        anxz = 1
    elseif x>70 and x<130 and y>30 and y<50 then
        anxz = 2
    elseif x>5 and x<20 and y>30 and y<50 then
        anxz = 3
    elseif x>40 and x<55 and y>30 and y<50 then
        anxz = 4
    else
        anxz = 0
    end
end

--鼠标点击事件
function on.mouseDown(x,y)
    if x>70 and x<130 and y>5 and y<25 then
        ksaj()
    elseif x>70 and x<130 and y>30 and y<50 then
        tzaj()
    elseif x>5 and x<20 and y>30 and y<50 then
        csjs()
    elseif x>40 and x<55 and y>30 and y<50 then
        cszj()
    end
    platform.window:invalidate()
end

function on.charIn(x)   --快捷键响应
    if x == "R" or x == "r" or x == "S" or x == "s" or x == "J" or x == "j"  then
        ksaj()
    elseif x == "T" or x == "t" then
        tzaj()
    elseif x == "-" then
        csjs()
    elseif x == "+"  then
        cszj()
    end
    platform.window:invalidate()
end

function csjs() --层数减少
    if cs >  cszx then
        cs =  cs - 1
        psbcsh()
        timer.stop()
        kszt = 2
    end
    platform.window:invalidate()
end

function cszj()  --层数增加
    if cs <  cszd then
        cs =  cs + 1
        psbcsh()            
        timer.stop()
        kszt = 2
    end
    platform.window:invalidate()
end

saj()  --开始按键
    if kszt == 2 then
        psbcsh()        
    end
    kszt = math.fmod(kszt+1,2)
    if kszt == 1 then
        timer.start(1/sdbl)
    elseif kszt == 0 then
        timer.stop()
    end
end

function tzaj()  --停止按键
    kszt = 2
    timer.stop()
    local szzd = szmax(psb)
    if szzd >0 then   --存储数据
        var.store("ps",psb)
        var.store("pl",pl)
        var.store("qcbh",qcbh)
    end
end

function psbcsh()  --频数初始化
    psb = {}
    qcbh = {}
    pl = {}
    for i=1,cs+1 do
        psb[i] = 0
        qcbh[i] = i
        pl[i] = 0
    end
    syzs = 0
    xqx = 0
    xqy = 0
    pjz = ""
    bzc = ""
end

function on.tabKey()  -- TAB键响应
    anxz = anxz + 1
    if anxz > 4 then
        anxz = 0
    end
    platform.window:invalidate()
end

function on.enterKey() --回车键响应
    if anxz == 1  then
        ksaj()
    elseif anxz == 2 then
        kszt = 2
        timer.stop()
    elseif anxz == 3 then
        csjs()
    elseif anxz == 4  then
        cszj()
    end
    platform.window:invalidate()
end


--菜单
menu={
   {"速度设置",
      {"速度1(最低)",function () sdsz(1) end},
      {"速度2",function () sdsz(2) end},
      {"速度3",function () sdsz(3) end},
      {"速度4",function () sdsz(4) end},
      {"速度5",function () sdsz(5) end},
      {"速度6",function () sdsz(6) end},
      {"速度7",function () sdsz(7) end},
      {"速度8(最快)",function () sdsz(8) end},
   },
   {"实验控制",
      {"开始",saj() end},
      {"暂停",saj() end},
      {"继续",saj() end},
      {"停止",function () tzaj() end},
      {"增加层数",function () cszj() end},
      {"减少层数",function () csjs() end},
    },
    {"大量实验",
      {"实验1000次",function () dlsy(1000) end},
      {"实验2000次",function () dlsy(2000) end},
      {"实验5000次",function () dlsy(5000) end},
      {"实验10000次",function () dlsy(10000) end},
    },
}
toolpalette.register(menu)

function sdsz(x)  --速度设置
    sdbl = 3 * x
    if kszt == 1 then
        timer.start(1/sdbl)
    else
        timer.stop()
    end
    platform.window:invalidate()
end

function dlsy(x)
    timer.stop()
    psbcsh()
    for i=1, x*(cs+1) do
        xqy = xqy + 1
        local fx = math.random(0,1)
        if fx > 0.5 then
            xqx = xqx + 1
        else
            xqx = xqx - 1
        end
        if xqy > cs then
            xqy = 0
            xqx = 0
        end
        if xqy == cs then
            local ld = math.floor((cs+xqx)/2+1)
            psb[ld] = psb[ld]+1
            syzs = syzs + 1            
            pl[ld] = math.floor(psb[ld]/syzs*100)/100            
        end
    end
    tzaj()
    platform.window:invalidate()
end
发表于 2012-7-28 07:55:34 | 显示全部楼层
回ls,lua程序编译后无法查看源代码
 楼主| 发表于 2012-7-28 11:51:17 | 显示全部楼层
http://education.ti.com/educatio ... homePage/index.html,点击【下载中心】→ 【教师软件 V3.2】,可以查看Lua写出来的TNS的源代码。
发表于 2012-7-29 10:24:47 | 显示全部楼层
模拟器过期的飘过
发表于 2012-8-1 11:04:56 | 显示全部楼层
最新的学生版注册后可以直接edit LUA
也就是查看源码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|cnCalc计算器论坛

GMT+8, 2024-4-30 11:03 , Processed in 0.086443 second(s), 25 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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