zsdsgjb 发表于 2012-7-23 22:50:09

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

本帖最后由 zsdsgjb 于 2012-7-23 22:51 编辑

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

anzedick 发表于 2012-7-24 21:41:01

1# zsdsgjb
不错,顶起。最好放出源码,方便改进

水瓜 发表于 2012-7-25 10:18:33

这不就是杨辉三角么

鸣人之子 发表于 2012-7-26 08:57:03

这个程序在没有LUA之前就已经有了

936854586 发表于 2012-7-27 17:50:41

你有兴趣坐下游戏吗??

zsdsgjb 发表于 2012-7-27 23:29:28

本帖最后由 zsdsgjb 于 2012-7-27 23:34 编辑

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

zsdsgjb 发表于 2012-7-27 23:32:19

2楼朋友,直接用最新的教师版软件可以打开看源码的。附源码在后:

-- 程序版权所有: 广东中山 高建彪QQ: 76456245E-mail:[email protected]
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("按:[菜单],",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 = psb+1
      syzs = syzs + 1
      pl = math.floor(psb/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,w/szws,h/szzd*psb)         
            zs0 = zs0 + pl*qcbh
            gc:setFont("serif","r",6)
            gc:drawString(pl*100,x+(w/szws)*(n-1)+3,y+h+15)
            gc:drawString(psb,x+(w/szws)*(n-1)+3,y+h+25)
            gc:drawString(qcbh,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-pjz)^2 * psb
      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 then
            max0 = psb
      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 = 0
      qcbh = i
      pl = 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 == 1then
      ksaj()
    elseif anxz == 2 then
      kszt = 2
      timer.stop()
    elseif anxz == 3 then
      csjs()
    elseif anxz == 4then
      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 = psb+1
            syzs = syzs + 1            
            pl = math.floor(psb/syzs*100)/100            
      end
    end
    tzaj()
    platform.window:invalidate()
end

936854586 发表于 2012-7-28 07:55:34

回ls,lua程序编译后无法查看源代码

zsdsgjb 发表于 2012-7-28 11:51:17

到http://education.ti.com/educationportal/sites/CHINA/homePage/index.html,点击【下载中心】→ 【教师软件 V3.2】,可以查看Lua写出来的TNS的源代码。

936854586 发表于 2012-7-29 10:24:47

模拟器过期的飘过

zhang2665123 发表于 2012-8-1 11:04:56

最新的学生版注册后可以直接edit LUA
也就是查看源码
页: [1]
查看完整版本: 耗时一天折腾出《高尔顿钉板实验》的lua程序