随机游走模型是非常重要的一个模型,在经济学,计算机,化学,生物,物理中都有重要的应用呵呵。具体的各个专业的应该都比较清楚,就不再赘述了。
图形界面以及种子数输入框
图形界面以及模式输入框:无轨迹模式,轨迹模式,混合模式
图形界面以及游走步数输入框
无轨迹模式
轨迹模式
混合模式
布朗运动
================================
源码和exe文件照例上传到:
http://code.google.com/p/c-programming-language/downloads/list
===============================
///////////////////////////////////////////////////
// 程序名称:随机游走模拟机
// 编译环境:Visual C++ 6.0,EasyX
// 作 者:Geodesic
// 最后修改:2012-4-24
///////////////////////////////////////////////////
#include <graphics.h>
#include <conio.h>
#include <time.h>
#include <windows.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
//最大原子数
#define MAX 10000 //最大种子数
//定义全局变量
IMAGE imgAtom, imgEmpty; //定义原子图案
int Atom[MAX][2]; //定义MAX个原子
unsigned long Total; //总步数
unsigned long Step_num; //已执行步数
int Seed; //种子数
int Delay = 100; //延时时间(毫秒)
char Mode = 'a'; //模式:a为无轨迹,t为轨迹模式,m为混合模式
//函数声明
void ImgInit();
void DataInit();
void AtomSeed(int num);
void Step(int num);
void DrawStep(int num, int Mode);
void DrawWalkAtom(int num);
void DrawWalkTrace(int num);
void DrawMix(int num);
void Data();
//主函数
int main(void)
{
char c;
char instr[20];
while(true){
printf("任意键开始程序\n");
if(getch() == 27) break;
Step_num = 0; //步数清零
ImgInit(); //绘图初始化
DataInit(); //数据初始化
AtomSeed(Seed); //种子初始化
while(Step_num < Total){
Data();
if(kbhit()){
c = getch();
if(c == 27) goto END; //Esc退出
else if(c == ' ') { //空格暂停游戏
DrawStep(Seed, 0); //绘制原子
setcolor(GREEN);
circle(264, 304, (int)sqrt(Step_num) * 4); //绘制根方距离圆
if(getch() == 27) goto END;
DrawStep(Seed, 1); //擦除原子
setcolor(BLACK);
circle(264, 304, (int)sqrt(Step_num) * 4); //擦除根方距离圆
}
else if(c == 's' || c == 'S'){ //调整速度(延时)
InputBox(instr, 9, "请输入延时×20ms,速度区间[0, 50]。\
注意延时较小时,会出现视觉暂留现象");
Delay = abs(atoi(instr));
if(Delay > 50) Delay = 1000;
if(Delay == 0) Delay = 0;
Delay = 50 * Delay;
}
else if(c == 'r' || c == 'R') break; //R刷新游戏
}
if(Mode == 'a') DrawWalkAtom(Seed);
else if(Mode == 't') DrawWalkTrace(Seed);
else if(Mode == 'm') DrawMix(Seed); //根据模式,绘图
}
DrawStep(Seed, 0);
}
END:
setcolor(YELLOW);
setfont(50, 0, "黑体");
outtextxy(100, 270, "常写程序,青春不老"); //结束
Sleep(2000);
closegraph();
return 0;
}
//初始化
void ImgInit()
{
//创建绘图窗口730×571像素
initgraph(730, 571);
//设置随机种子
srand((unsigned)time(NULL));
//调整原子图案大小2×2像素
Resize(&imgAtom, 4, 4);
Resize(&imgEmpty, 4, 4);
//绘制原子的图案
SetWorkingImage(&imgAtom);
setcolor(YELLOW);
setfillstyle(YELLOW);
fillellipse(0,0,4,4);
//绘制无原子的图案
SetWorkingImage(&imgEmpty);
setcolor(BLACK);
setfillstyle(BLACK);
fillellipse(0,0,4,4);
//恢复对默认窗口的绘图
SetWorkingImage(NULL);
//输出标题
setfont(24, 0, "黑体");
outtextxy(230, 18, "Geodesic 随 机 游 走");
// 输出简单说明
RECT r = {530, 65, 710, 550};
setfont(12, 0, "宋体");
drawtext("随机游走:\n \n \
随机游走,又称无规则行走。与其联系的核心概念是:任何\
无规则行走者所带的守恒量都各自对应着一个扩散运输定律。\
扩散定律是普适的,只要给定独立随机行走的某种分布,它\
就不依赖于具体的模型。涨落是随机的、混沌的,无规则行走\
的结果就是扩散,这包括物质扩散、动量扩散、热量扩散等。\
这也意味着结晶学、天文学、生物学、气象学、流体力学、经\
济学都将用到扩散定律。\
\n\n\
游戏控制:\n\n\
Esc : 退出\n\
空格 : 暂停 | 继续\n\
S : 速度调节(Delay)\n\
A : 无轨迹模式(Atom)\n\
T : 轨迹模式(trace)\n\
M : 混合模式(mix)\n\n\
R : 重新开始(restart)\n\n\
本程序认为粒子是玻色子,不考虑粒子间的碰撞占位,但是与器壁\
碰撞时会发生反射现象\n", &r, DT_WORDBREAK);
//绘制工作区边框
rectangle(10, 52, 517, 559);
rectangle(517, 52, 720, 559);
line(517, 419, 720, 419);
line(517, 454, 720, 454);
line(517, 489, 720, 489);
line(517, 524, 720, 524);
//清空绘图区
setfillstyle(BLACK);
bar(11, 53, 516, 558);
}
//数据初始化:种子数,模式,总步数
void DataInit()
{
char instr[20];
InputBox(instr, 9, "请输入种子数,最大种子数10 000"); //读入种子数
Seed = abs(atoi(instr));
if(Seed > 1024) Seed = 1024;
if(Seed == 0) Seed = 1;
InputBox(instr, 9, "请输入模式,A:无轨迹 T:轨迹 M:混合模式");
if(instr[0] == 'a' || instr[0] == 'A' || instr[0] == 't' || instr[0] == 'T'|| //读入模式
instr[0] == 'm' || 'M')
Mode = instr[0];
InputBox(instr, 9, "请输入总步数,最大值999 999 999"); //读入总步数
Total = abs(atoi(instr));
if(Total > 999999999) Total = 999999999;
else if(Total == 0) Total = 1;
}
//绘制数据显示区
void Data()
{
char outstr[20];
//擦除痕迹
setcolor(WHITE);
setfillstyle(BLACK);
bar(518, 490, 719, 523);
bar(518, 525, 719, 554);
//设置字体
setfont(16, 0, "黑体");
//输出总步数
itoa(Total, outstr, 10);
outtextxy(522, 430, "总步数:");
outtextxy(650, 430, outstr);
//输出均方根距离
itoa((int)sqrt(Step_num), outstr, 10);
outtextxy(522, 465, "均方根距离(×4):");
outtextxy(650, 465, outstr);
//输出已执行步数
itoa(Step_num + 1, outstr, 10);
outtextxy(522, 500, "已执行步数:");
outtextxy(650, 500, outstr);
//输出种子数
itoa(Seed, outstr, 10);
outtextxy(522, 535, "种子数:");
outtextxy(650, 535, outstr);
}
//单步随机游走
void Step(int num)
{
int x, y;
for(int i = 0; i < num; i++){
switch(abs(rand()) % 4)
{
case 0 : x = 4, y = 0; break; //向右一步
case 1 : x = 0, y = 4; break; //向下一步
case 2 : x = -4, y = 0; break; //向左一步
case 3 : x = 0, y = -4; break; //向上一步
}
if(Atom
[0] + x > 513) x = -1 * x;
else if(Atom[0] + x < 14) x = -1 * x;
if(Atom[1] + y > 555) y = -1 * y;
else if(Atom[1] + y < 56) y = -1 * y; //边界反射操作
Atom[0] += x;
Atom[1] += y; //随机游走一步
}
++Step_num; //计算已执行步数
}
//原子种子初始化
void AtomSeed(int num)
{
for(int i = 0; i < num; i++){
Atom[0] = 262;
Atom[1] = 304;
}
}
//绘制单步随机游走,模式0绘图,模式1擦图
void DrawStep(int num, int Mode)
{
if(Mode == 0) //绘制原子
for(int i = 0; i < num; i++)
putimage(Atom[0], Atom[1], &imgAtom);
if(Mode == 1) //擦除原子
for(int i = 0; i < num; i++)
putimage(Atom[0], Atom[1], &imgEmpty);
}
//绘制标度
void Scale()
{
setcolor(GREEN);
line(265, 53, 265, 558);
line(11, 304, 516, 304);
}
//绘制随机游走,原子模式
void DrawWalkAtom(int num)
{
DrawStep(num, 0); //画原子
Scale(); //画标度
Sleep(Delay); //延时
DrawStep(num, 1);
Step(num); //计算出下一步
}
//绘制随机游走,轨迹模式
void DrawWalkTrace(int num)
{
int xy[MAX][2];
setcolor(LIGHTMAGENTA);
for(int i = 0; i < num; i++){
xy[0] = Atom[0];
xy[1] = Atom[1];
}
Step(num); //计算出下一步
for(i = 0; i < num; i++){
line(xy[0], xy[1], Atom[0], Atom[1]);
} //绘制轨迹
Scale(); //绘制标度
Sleep(Delay);
}
//绘制随机游走,混合模式
void DrawMix(int num)
{
int xy[MAX][2];
for(int i = 0; i < num; i++){
xy[0] = Atom[0];
xy[1] = Atom[1];
}
DrawStep(num, 0); //画原子
Sleep(Delay); //延时
DrawStep(num, 1); //擦原子
Step(num); //计算出下一步
setcolor(LIGHTMAGENTA); //绘制轨迹
for(i = 0; i < num; i++)
line(xy[0], xy[1], Atom[0], Atom[1]);
}