背景
概率论的书上有这样一个示例:设想某人在平面上从零点出发,手持一个均匀四面体,四面分别标有1,2,3,4,每个面代表一个方向(东南西北),他随意抛出后,按照这个方向走一单位长度,若干次后观测他走过的路线的轨迹,由此你有什么联想?
联想倒是没啥,出于好奇编了个简单的程序,看看这个轨迹会是什么样的。
流程
先是用随机数取余,然后把前后位置的线连起来
direction = rand() % 4;
line(X + N * a[0], Y + N * a[1], X + N * a[2], Y + N * a[3]);
得到的图形挺有意思的(说实话我不会相信那个人如果真的丢起四面体来他的路径会长这样)
然后出于好玩,我加了渐变的颜色
color = getlinecolor();
RGBtoHSL(color, &H, &S, &L);
H += 0.5;
setlinecolor(HSLtoRGB(H, S, L));
后来又加了四个方向(左上,左下,右上,右下),经历512571步才回到原点。
在这里方向的设定为:
数字 |
0 |
1 |
2 |
3 |
4 |
5 |
6 |
7 |
方向 |
左 |
左上 |
上 |
右上 |
右 |
右下 |
下 |
左下 |
上面的设定很有次序,但是如果我把顺序打乱:
数字 |
0 |
1 |
2 |
5 |
3 |
4 |
7 |
6 |
方向 |
左 |
左上 |
上 |
右上 |
右 |
右下 |
下 |
左下 |
虽然还是能看到那个小点在同一个轨迹上运动,但是没有了对称性。
于是我用了一个数组和一个函数,将方向和数字随机匹配(随机匹配过程还是用的同样的随机数生成方法rand()),得到的图像:
与之前的相比,轨迹运动周期反而更小了,而且每个周期运动的轨迹没有重叠在一起
全部代码:
#include<stdio.h>
#include<graphics.h>
#include<conio.h>
#include<time.h>
#include<math.h>
#define X 500//坐标
#define Y 300
#define N 0.5//图案大小
void fun(int* p)//将8个数字随机排列
{
int i, j, k;
for (i = 0; i < 8; i++)
{
p[i] = 9;
}
for (i = 0; i < 8; i++)
{
while (1)
{
j = rand() % 8;
if (p[j] == 9)
{
p[j] = i;
break;
}
}
}
}
void main()
{
initgraph(1000, 600, SHOWCONSOLE);
setbkcolor(WHITE);
cleardevice();
srand(time(NULL));
int direction;
int a[4] = { 0 };
int b[8] = { 0,1,2,3,4,5,6,7 };//按顺序来形成的图片才对称
double n = 0;
float H = 0, S = 0.8, L = 0.8;
int color;
setwritemode(R2_COPYPEN);
setlinestyle(PS_SOLID, 1);
setlinecolor(RED);
while (1)
{
n = 0;
H = 0, S = 0.5, L = 0.5;
/*while (1)
{
a[2] = a[0];
a[3] = a[1];
setlinecolor(BLACK);
direction = rand() % 4;
if (direction == 0)//左
{
a[0]--;
}
else if (direction == 1)//上
{
a[1]--;
}
else if (direction == 2)//右
{
a[0]++;
}
else if (direction == 3)//下
{
a[1]++;
}
line(X + N * a[0], Y + N * a[1], X + N * a[2], Y + N * a[3]);
}*/
while (1)
{
a[2] = a[0];
a[3] = a[1];
n++;
color = getlinecolor();
RGBtoHSL(color, &H, &S, &L);
H += 0.5;
setlinecolor(HSLtoRGB(H, S, L));
direction = rand() % 8;
//fun(b);
if (direction == b[0])//左
{
a[0]--;
}
else if (direction == b[1])//左上
{
a[0]--;
a[1]--;
}
else if (direction == b[2])//上
{
a[1]--;
}
else if (direction == b[3])//右上
{
a[0]++;
a[1]--;
}
else if (direction == b[4])//右
{
a[0]++;
}
else if (direction == b[5])//右下
{
a[0]++;
a[1]++;
}
else if (direction == b[6])//下
{
a[1]++;
}
else if (direction == b[7])//左下
{
a[0]--;
a[1]++;
}
line(X + N * a[0], Y + N * a[1], X + N * a[2], Y + N * a[3]);
printf("%d,%d,%.lf\n", a[0], a[1], n);
if (a[0] == 0 && a[1] == 0)
{
printf("^_^\t%.lf", n);
break;
}
}
//_getch();
}
}
看到这样的图形我总是想到分形并努力想找到自相似的特征。但是后来想形成图案的根本原因还是在随机数的生成机制。而且这些图应该也能反映这种伪随机数的一些特征。
由于是上网课的时候突然想到这个问题,考虑到第一次概率论,讲的应该还是高中的衔接部分,就没认真听讲。。。结果后来突然发现讲到了上极限下极限。。。听不懂了
给人的感觉就是
哈哈
希望懂得随机数生成原理的大佬能给我解释下这些魔性的图案背后的原理