MFC模拟高尔顿板实验
先上效果图,图中小球是动态下落的,下落到对应桶里会更新相应计数。
《1》建立基于单文档的应用程序,名为:GEDB。
《2》为类CDEDBView添加成员函数void CGEDBView::DrawFrame(CDC *pDC),并添加如下代码:
void CGEDBView::DrawFrame(CDC *pDC)
{
CRect rc;//定义一个矩形区域变量
GetClientRect(rc);//获取当前窗口的客户区大小
CPoint point[12] ;
point[0] = (85 ,5) ;//画图区域的左上角
point[1] = (685 ,403) ;//画图区域的右下角
//设置每个钉子的半径为12
int R = 12 ;
//绘制图形区域的边缘(灰色)
CPen pen(PS_INSIDEFRAME,1,RGB(192,192,192));//定义画笔
CPen* oldPen=pDC->SelectObject(&pen); //将pen选入设备环境
CRect recttempt(85,5,685,403) ;
pDC->Rectangle(recttempt) ;
//绘制显示小球的所在区域
CRect rect1(85 -4*R ,300-23*R ,85-2*R ,300+7*R) ;
pDC->Rectangle(rect1) ;
pDC->SetBkColor(RGB(250,250,0)) ;
CString str[2]= {"顶部","底部"};
pDC->TextOut(85 -4*R,300-25*R,str[0]) ;
pDC->TextOut(85 -4*R,300+8*R,str[1]) ;
//绘制不同桶间的分割线(蓝色)
CPen Lpen0 ;
Lpen0.CreatePen(PS_SOLID ,2 ,RGB(0,0,255)) ;
pDC->SelectObject(Lpen0) ;
for (int i = 1 ;i<12 ;i++)
{
pDC->MoveTo(100 + i*4*R ,400) ;
pDC->LineTo(100 + i*4*R ,300) ;
}
//绘制高尔顿版的边缘(肖贡土色)
CPen Lpen1 ;
Lpen1.CreatePen(PS_DASH ,5 ,RGB(197,97,20)) ;
pDC->SelectObject(Lpen1) ;
pDC->MoveTo(100,400) ;
pDC->LineTo(100 ,300) ;
pDC->MoveTo(676,400) ;
pDC->LineTo(676 ,300) ;
pDC->MoveTo(100,400) ;
pDC->LineTo(676 ,400) ;
pDC->MoveTo(100 ,300) ;
pDC->LineTo(375 ,25) ;
pDC->MoveTo(676 ,300) ;
pDC->LineTo(406 ,25) ;
pDC->MoveTo(375 ,25) ;
pDC->LineTo(375 ,10) ;
pDC->MoveTo(406 ,25) ;
pDC->LineTo(406 ,10) ;
CPen Lpen3(PS_NULL ,1 ,RGB(0,0,0)) ;//创建无边缘的画笔
pDC->SelectObject(Lpen3) ;
CBrush brush(RGB(0,255,0)) ;
CBrush *OldBrush = pDC->SelectObject(&brush) ;
for (i = 0 ;i<12;i++)
{
for (int j = 1 ;j <12-i ;j++)
{
//绘制钉子
pDC->Ellipse(100+j*4*R-R + i*2*R ,300+R - i*2*R,100+j*4*R+R+ i*2*R ,
300-R - i*2*R) ;
//绘制小球下落位置的提示球
pDC->Ellipse(85 - 4*R ,300+R - i*2*R ,85 - 2*R ,300-R - i*2*R) ;
}
}
//因为提示球的行数比钉子多三个,故还需要画3个
for (i =1 ;i<4;i++)
{
CRect rectRange;
rectRange.left = 85 - 4*R ;
rectRange.top = 300 - R ;
rectRange.right = 85 - 2*R ;
rectRange.bottom = 300 + R ;
//绘制小球下落位置的提示球
pDC->Ellipse(rectRange.left ,rectRange.top + i*2*R ,
rectRange.right ,rectRange.bottom + i*2*R) ;
}
pDC->SelectObject(OldBrush) ;
pDC->SelectObject(oldPen);//恢复原来画笔的属性
}
《3》在函数void CGEDBView::OnDraw(CDC* pDC)中添加如下代码:
void CGEDBView::OnDraw(CDC* pDC)
{
CGEDBDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
pDC->SetViewportExt(800,400);//设置视口范围
if (CGEDBView::N == CPublic::BallNumber)//实验次数大于设定的时候
{
AfxMessageBox("程序结束!") ;
Return ;
}
DrawFrame(pDC) ;//画框架
//总共有11块板
const int N = 11 ;//高尔顿版板的数目
}
《4》为类CGEDBViw添加成员变量public:
CButton m_MyButton1;
CButton m_MyButton2;//用于创建两个按钮
CButton m_MyButton3;
添加消息响应函数OnInitialUpdate,并添加如下代码:
void CGEDBView::OnInitialUpdate()
{
CView::OnInitialUpdate();
//创建开始按钮
m_MyButton1.Create("开始试验",WS_CHILD|BS_DEFPUSHBUTTON,CRect(700,0,800,50),
this,ID_MyButton1);
m_MyButton1.ShowWindow(SW_SHOWNORMAL);
//创建终止按钮
m_MyButton2.Create("暂停试验",WS_CHILD|BS_DEFPUSHBUTTON,CRect(850,0,950,50),
this,ID_MyButton2);
m_MyButton2.ShowWindow(SW_SHOWNORMAL);
//创建退出按钮
m_MyButton3.Create("退出",WS_CHILD|BS_DEFPUSHBUTTON,CRect(850,370,950,420),
this,ID_MyButton3);
m_MyButton3.ShowWindow(SW_SHOWNORMAL);
}
《5》为类CGEDBViw添加消息响应函数OnDestroy,并添加如下代码:
void CGEDBView::OnDestroy()
{
CView::OnDestroy();
// TODO: Add your message handler code here
//此函数可以删除
//KillTimer(1) ;//清除定时器
}
《6》为类CGEDBViw添加消息响应函数OnTimer,并添加如下代码:
void CGEDBView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
if (CGEDBView::N == CPublic::BallNumber) //实验进行了设定的次数
{
KillTimer(1) ;//销毁计时器
return ;
}
CDC *pDC = GetDC() ;
CGEDBView::OnDrawBall(pDC) ;//画球
CView::OnTimer(nIDEvent);
}
《7》在CGEDBViw类中添加成员变量数组;
public:
static int Backet[12] ;//统计各个区间的珠子的数目
static int N ;//定义实验次数
static int BallRound;
并在CGEDBViw.Cpp中初始化,在其构造函数CGEDBView::CGEDBView()前添加初始化语句,int CGEDBView::Backet[12]={0,0,0,0,0,0,0,0,0,0,0,0};
int CGEDBView::N = 0 ;//初始化计数器
int CGEDBView::BallRound = 0 ;
《8》为类CGEDBView添加成员函数OnDrawBall,并添加如下代码:
//绘制小球下落轨迹
void CGEDBView::OnDrawBall(CDC *pDC)
{
CGEDBView::BallRound++ ;//计数器加一
//设置每个钉子的半径为12
int R = 12 ;
static CRect rc(400-2*R,50,400,25) ;
//先擦除上一个圆
CPen pen;
pen.CreateStockObject(NULL_PEN);
CPen *pOld = pDC-> SelectObject(&pen);
pDC->Ellipse(rc.left ,rc.top,rc.right ,rc.bottom);//把圆擦除
pDC->SelectObject(pOld) ;
//将显示小球位置提示球的颜色还原(还原为蓝色)
CPen Lpen3(PS_NULL ,1 ,RGB(0,0,0)) ;//创建无边缘的画笔
pDC->SelectObject(Lpen3) ;
CBrush Lbrush(RGB(0,255,0)) ;
pDC->SelectObject(&Lbrush) ;
pDC->Ellipse(85 - 4*R ,rc.top,85 - 2*R ,rc.bottom) ;
//重新绘制下一个圆
//创建画笔
CPen newpen(PS_NULL ,1 ,RGB(0,0,0)) ;
CPen *OldPen = pDC->SelectObject(&newpen) ;
//创建画刷(画球)
CBrush brush(CPublic::Ballref) ;
CBrush *OldBrush = pDC->SelectObject(&brush) ;
//前面的12步小球都可以向左或者右运动,
//但是第13、14、15步设置的是直接下落过程
if (CGEDBView::BallRound == 13||CGEDBView::BallRound == 14)
{
rc.top += 2*R ;
rc.bottom += 2*R ;
pDC->Ellipse(rc.left ,rc.top,rc.right ,rc.bottom) ;
//将显示小球位置提示球的颜色改变
pDC->Ellipse(85 - 4*R ,rc.top,85 - 2*R ,rc.bottom) ;
pDC->SelectObject(OldBrush) ;
pDC->SelectObject(OldPen);//恢复原来画笔的属性
return ;
}
if (CGEDBView::BallRound == 15)
{
CGEDBView::N++ ;//计数器加一
//更新下落的球的总数
CString tstr ,tstr2;
tstr2.Format("%-5d" ,CGEDBView::N) ;
tstr = "下落的小球数目" ;
pDC->SetBkColor(RGB(250,250,0)) ;
pDC->TextOut(800,100,tstr) ;
pDC->TextOut(820,130,tstr2) ;
rc.top += 2*R ;
rc.bottom += 2*R ;
pDC->Ellipse(rc.left ,rc.top,rc.right ,rc.bottom) ;
pDC->Ellipse(85 - 4*R ,rc.top,85 - 2*R ,rc.bottom) ;
pDC->SelectObject(OldBrush) ;
pDC->SelectObject(OldPen);//恢复原来画笔的属性
CGEDBView::BallRound = 0 ;//计数器置零
return ;
}
//新一轮的开始,将小球置于高尔顿板进口处
if (CGEDBView::BallRound == 1)
{
rc.left = 400-2*R ;
rc.top = 50 ;
rc.right = 400;
rc.bottom = 25;
//画球(小球)
pDC->Ellipse(rc.left ,rc.top,rc.right ,rc.bottom) ;
pDC->Ellipse(85 - 4*R ,rc.top,85 - 2*R ,rc.bottom) ;
return ;
}
//参数N为该小球下落的第N步(0<=N<12);参数direction为小球下落方向
//direction=0表示向左,direction=1表示向右.
const int N = 11 ;//高尔顿版板的数目
//sum=0则落在最左边的区间,sum=N-1则落在最右边的区间
static int sum = 0 ;//小球向左一次则加零,向右一次则加一
int direction = 0 ;//小球在某一步的方向
//产生(0,1)区间上的随机数
float x = 0 ;
x = (float) (rand()%100)/100.0 ;
if (x >= 1-CPublic::RightChance)
direction = 1 ;
else
direction = 0 ;
sum += direction ;
//一个小球需要15步才能落入桶中,
//前面的12步就可以决定落入的桶的编号
if (CGEDBView::BallRound == 12)
{
CGEDBView::Backet[sum]++ ;//对应的桶的小球数目加一
CGEDBView::InitialBallAmount();//初始化公共类的BallAmount[12]数组
sum = 0 ;
}
for (int k = 0 ;k<N+1 ;k++)
{
CString str ;
str.Format("%-4d" ,CGEDBView::Backet[k]) ;
pDC->SetBkColor(RGB(250,250,0)) ;
pDC->TextOut(110+k*50 ,405 ,str) ;
}
if (direction == 0)//向左
{
//将小球向左移动一个位置,并且向下移动一个位置
rc.left -= 2*R ;
rc.top += 2*R ;
rc.right -= 2*R ;
rc.bottom += 2*R ;
}
else if (direction == 1)//向右
{
//将小球向右移动一个位置,并且向下移动一个位置
rc.left += 2*R ;
rc.top += 2*R ;
rc.right += 2*R ;
rc.bottom += 2*R ;
}
else
{
MessageBox("程序出错!") ;
return ;
}
pDC->Ellipse(rc.left ,rc.top,rc.right ,rc.bottom) ;
pDC->Ellipse(85 - 4*R ,rc.top,85 - 2*R ,rc.bottom) ;
pDC->SelectObject(OldBrush) ;
pDC->SelectObject(OldPen);//恢复原来画笔的属性
}
《9》为类CGEDBView添加成员函数void CGEDBView::InitialBallAmount(),用于初始化公共类的数组BallAmount[12],并添加如下代码:
void CGEDBView::InitialBallAmount()
{
const int Backet = 12 ;
for (int i = 0 ;i<Backet ;i++)
{
CPublic::BallAmount[i] = CGEDBView::Backet[i] ;
}
}
并在GEDBView.cpp中包含头文件#include "Public.h"。
《10》打开资源中的“String Table”,在空白行上双击鼠标,这时会弹出一个ID属性对话框,在其中的ID编辑框中输入ID_MyButton1,标题:开始试验,其值为:61446再次添加,输入ID:ID_MyButton2,标题:暂停试验,其值为:61447。在编辑框中输入ID:ID_MyButton3,标题:退出,其值为:61448.
在GEDBView.h类的定义中添加如下代码:
protected:
//{{AFX_MSG(CGEDBView)
afx_msg void OnDestroy();
afx_msg void OnTimer(UINT nIDEvent);
//}}AFX_MSG
afx_msg void OnMybut1();
afx_msg void OnMybut2();
afx_msg void OnMybut3();
DECLARE_MESSAGE_MAP()
在GEDBView.cpp中添加如下代码:
BEGIN_MESSAGE_MAP(CGEDBView, CView)
//{{AFX_MSG_MAP(CGEDBView)
ON_WM_DESTROY()
ON_WM_TIMER()
//}}AFX_MSG_MAP
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
ON_BN_CLICKED(ID_MyButton1, OnMybut1)
ON_BN_CLICKED(ID_MyButton2, OnMybut2)
ON_BN_CLICKED(ID_MyButton3, OnMybut3)
END_MESSAGE_MAP()
《11》在GEDBView.cpp中实现开始试验按钮与终止试验按钮的消息响应函数:
void CGEDBView::OnMybut1()
{
AfxMessageBox("程序开始!") ;
SetTimer(1,CPublic::Fallpace ,NULL) ;//安装定时器1
srand((unsigned int)time(NULL));//随机数种子
}
void CGEDBView::OnMybut2()
{
KillTimer(1) ;//清除定时器
//每个桶中的球都置空
for (int i = 0 ;i<12 ;i++)
{
CPublic::BallAmount[i] = 0 ;
CGEDBView::Backet[i] = 0 ;
}
AfxMessageBox("程序暂停!") ;
}
void CGEDBView::OnMybut3()
{
AfxMessageBox("程序结束!") ;
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_CLOSE,0,0);
}
在
《10》效果如下所示:
《11》为MessageBox()消息框添加自动关闭功能
(1)在函数void CGEDBView::OnInitialUpdate() 中添加如下代码:
SetTimer(2,1000,NULL) ;//为MessageBox()函数添加定时器
(2)在GEDBView.cpp中定义如下变量及常量:
#define Wait_MessageBox 2 //定义自动关闭MessageBox消息框的时间
#define Message_Title "GEDB"消息框的标题,用于查找消息框的句柄
BOOL fgMsgDlgShow = FALSE; //消息框弹出标记
UINT nMsgDlgTimer = 0; //消息框计数器
(3)在void CGEDBView::OnTimer(UINT nIDEvent)中做如下修改
void CGEDBView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
CDC *pDC = GetDC() ;
switch(nIDEvent)
{
case 1:
if (CGEDBView::N == CPublic::BallNumber)//实验进行了设定的次数
{
KillTimer(1) ;//销毁计时器
return ;
}
CGEDBView::OnDrawBall(pDC) ;//画球
CView::OnTimer(nIDEvent);
break ;
case 2:
if(fgMsgDlgShow)
{
nMsgDlgTimer++;
if(nMsgDlgTimer >= Wait_MessageBox)
{
fgMsgDlgShow = FALSE ;//撤销标记
CWnd* hWnd;
hWnd = FindWindow(NULL,Message_Title); //根据标题,查找消息框句柄
if(hWnd) hWnd->SendMessage(WM_CLOSE, NULL, NULL); //找到后,向其发关闭消息
}
}
break ;
default:
break ;
}
}
(4)在void CGEDBView::OnMybut1()作如下修改:
void CGEDBView::OnMybut1()
{
fgMsgDlgShow = TRUE;
nMsgDlgTimer = 0;
AfxMessageBox("程序开始!") ;
CPublic::CPublic();//初始化实验设置
SetTimer(1,CPublic::Fallpace ,NULL) ;//安装定时器1
srand((unsigned int)time(NULL));//随机数种子
}
(5)在void CGEDBView::OnMybut2()中作如下修改:
void CGEDBView::OnMybut2()
{
KillTimer(1) ;//清除定时器
//每个桶中的球都置空
for (int i = 0 ;i<12 ;i++)
{
CPublic::BallAmount[i] = 0 ;
CGEDBView::Backet[i] = 0 ;
}
fgMsgDlgShow = TRUE;
nMsgDlgTimer = 0;
AfxMessageBox("程序暂停!") ;
}
(6)在void CGEDBView::OnMybut3()中作如下修改:
void CGEDBView::OnMybut3()
{
fgMsgDlgShow = TRUE;
nMsgDlgTimer = 0;
AfxMessageBox("程序结束!") ;
::PostMessage(AfxGetMainWnd()->GetSafeHwnd(),WM_CLOSE,0,0);//关闭对话框
}
MFC模拟高尔顿板实验相关推荐
- matlab模拟高尔顿板实验,高尔顿钉板试验模拟
public void galton(int sumOfGrid, int sumOfBall){ int[] grid = new int[sumOfGrid]; int number = 0; / ...
- MATLAB模拟伽尔顿板实验
MATLAB模拟伽尔顿板实验代码展示: clear;b=1;k=1;dxdy=0.81;r=0.1;ttt=0:pi/300:2*pi;xxx=r*exp(i*ttt);for n=1:80for m ...
- 拉普拉斯分布_中心极限定理:从高尔顿板到麦克斯韦分布
神奇的正态分布源于"加". 撰文 | 张和持 时隔多年,或许你早就记不得16岁那年夏天高中闷热的教室,但可能会记得有一天数学老师说着要给大伙看个稀奇--一块祖传的高尔顿板.尽管班 ...
- matlab仿真高尔顿正态分布源码,中心极限定理:从高尔顿板到麦克斯韦分布
神奇的正态分布源于"加". 撰文 | 张和持 时隔多年,或许你早就记不得16岁那年夏天高中闷热的教室,但可能会记得有一天数学老师说着要给大伙看个稀奇--一块祖传的高尔顿板.尽管班上 ...
- 模拟撞击_模玩资讯:EPOCH 汽车撞击测试用模拟假人与实验车辆
日本著名玩具制造商 EPOCH(エポック社),最近又准备推出一款很特别的有趣主题之扭蛋玩具,就是将电视上常见的汽车撞击测试的模拟用假人,以及实验专用的测试车辆,这两项物品的实体化扭蛋玩具!预计在 20 ...
- 计算机网络模拟校园,计算机网络课程设计-模拟校园网组网实验
计算机网络课程设计-模拟校园网组网实验 福建农林大学金山学院 信息工程类 课程实习报告 课程名称: 计算机网络 实习题目: 校园网组网方案 姓 名: 严夫 系: 信息与机电工程系 专 业: 计算机科学 ...
- 计算机网络模拟校园,计算机网络课程设计模拟校园网组网实验.doc
计算机网络课程设计模拟校园网组网实验.doc 福建农林大学 金山 学院 信息工程 类 课程实习报告 课程名称: 计算机网络 实习题目: 校园网组网方案 姓 名: 严夫 系: 信息与机电工程系 专 业: ...
- 读取usb口数据_Mixly 第12课 模拟值读取实验串口使用
第12课 模拟值读取实验--串口使用 串行通信是在实现在PC机与微控制器进行交互的最简单的办法.以常见的Arduino UNO为例,面板上只有一组串行端口,即引脚 0(RX)和1(TX).电脑与Ar ...
- HCIA/HCIP使用eNSP模拟VRRP配置实验(接入层 汇聚层 核心层 VLAN OSPF VRRP STP DHCP的综合应用)
使用eNSP模拟 VRRP配置实验 接入层 汇聚层 核心层 VLAN OSPF VRRP STP DHCP的综合应用 目录 使用eNSP模拟 VRRP配置实验 拓扑预览 实验要求 知识总结 1 VRR ...
最新文章
- 有关定时任务的表达式--cron 详细解
- 【Java 网络编程】UDP 服务器 与 客户端持续交互 案例
- 函数09 - 零基础入门学习C语言40
- ERP物料采购系统需求分析与效果展示 ERP实施以失败告终的四个原因分析
- R语言 非中心化F分布
- 数字化转型生态的三个层级(平台 场景 工具/技术)
- FTP服务器之pure-ftpd常见问题及解决方法
- React开发(132):ant design学习指南之form中控制展开和关闭逻辑
- python第一行左对齐_关于Python的第一行语句
- 骨骼的动作识别数据集_基于关节数据的人体动作识别
- 磁盘分区命令fdisk、parted和gdisk
- 调频广播如何发明的?
- TCP模拟HTTP请求
- Docker - 使用Docker Compose部署应用
- Simultaneous Feature Learning and Hash Coding with Deep Neural Networks
- JS可选链操作符 (?.)
- STM32平台的USART串口通信
- 读文献——一些专有名词的学习记录
- 用HTML加CSS模仿的W3school的主页
- python清空文件_python清空文件
热门文章
- graylog+kafka+zookeeper(单机测试及源码),graylog收集kafka(脚本创建发布订阅方式)存储的消息(四)
- html win10虚拟键盘,笔记本电脑win10虚拟键盘打开的方法
- apollo学习之---(17)commen-math学习
- 苹果手机浏览器下拉会闪动的解决办法
- 个人开发者的项目如何接入支付宝登录功能(保姆级教学)(Java的后台为例,其他语言类似)
- 纯CSS3流光边框特效
- 用Django编写邮箱注册以及验证码
- postman 获取接口参数_postman 接口参数化操作
- Win10如何进行兼容性视图设置,教程来啦!怎么设置兼容性视图
- 科罗拉多州奥罗拉市用基于磁盘的ExaGrid系统取代磁带备份