用c语言做的简易的动态显示直方图和一个有趣的反直觉财富分配实验
2017-07-12 19:23
323 查看
PS:这是我的第一篇博客,有很多地方不懂,所以有做的不对的地方希望大家谅解。
PS2:我是大一的软工的学生,这个程序也只是突发奇想做的,我的编程技术并不是很好,所以大家不要太在意我的一些错误,技术有限,主要是这么个原理嘛。
问题:
房间内有100个人,每人拥有100元钱,每分钟随机给另一个人1块,最后这个房间内的财富分配是怎么样的?这个问题是我在知乎上看到的,同时这个文章的作者给出了一个关于这个问题的gif图,就是一个动态的直方图,感觉非常的帅气,于是自己试着做了个。个人感觉还不错,希望大家喜欢。原文链接:https://zhuanlan.zhihu.com/p/27797001?utm_source=qq&utm_medium=social
原理:1.构建直方图。用for循环构建就行了,每一行的第一个字符根据行数来判断是否输出为分段的数字,就是,5,15,20那些,第二个字符的话固定输出为边界“|”这个字符。
然后行数从上往下从0到你输入的行数循环,也可反向,然后再在每行的第三个字符用for循环来判断接下来的位置开始根据行数判断是输出空格(两个)还是黑方格。
这里的判断是根据样本数组来判断,样本数组中存储着每个样本的初始资金,若行数所在位置高于资金,就printf空格,反之printf方格。
2.资金交换。这里是根据随机出来的下标来进行交换的,随机数的话需要stdlib.h头文件,然后如下。
3.清除屏幕的函数。动态显示其实就是通过不断清除屏幕后再显示出新的内容。和动画的制作原理是一样的。
4.延迟函数。
所有代码:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
int times,ntime;//ntime为当前时间,times为刷新次数
void draw(int XZ[],int Y,int X,int ifps)//ifps为当前给出钱的人数
{
int i,j;
printf("当前分钟给出钱的人数:%d\n\n",ifps);
printf("当前时间:第%d分钟\n\n",ntime);
for(i=0;i<Y;i++)//行数for循环
{
if(i%5==0)
{
printf("%2d",Y-i);//纵坐标参照
}
else
{
printf(" ");
}
printf("|");
for(j=0;j<X;j++)//在每行中进行每列的for循环
{
printf(" ");//空格
if(i<Y-XZ[j]-1)
printf(" "); //为便于计数,程序中i从上往下数,也就是从0到Y,而现实中当此列从下往上数时的行数大于此列的金钱时输出为两个空格,两个空格才能和一个黑方格等宽。
if(i==Y-XZ[j]-1)
printf("%2d",XZ[j]);
if(i>=Y-XZ[j])
printf("█");//程序中的i从上往下数时大于金钱的行数时,也就是现实中从下往上数小于等于金钱数时,输出为黑方格、
}
printf("\n");
}
printf(" 0");
for(i=0;i<Y+2;i++)
{
printf("一 ");//画出横坐标线
}
}
void cal(int XZ[],int Y,int X,int ms)//计算
{
int i,temp,ifps=0;
for(i=0;i<X;i++)
{
srand((unsigned) time(NULL)); //用时间做种,每次产生随机数不一样,需要stdlib.h头文件
temp=rand()%(X);//rand()%x为从0到x随机取值,rand()%x+1则为从1到x+1取值。
while(temp==i)//当取得随机下标为本身时,从新取随机值,此处用while是为了取随机值直到不等于本身。
{
temp=rand()%(X);//防止取到本身值,将钱给自己。
}
if(XZ[i]>0)//有钱时才能给
{
XZ[temp]++;//目标的金钱加一
XZ[i]--;//自己金钱减一
ifps++;//给出钱人数(次数)
draw(XZ,Y,X,ifps);//画出表格
Sleep(ms);//延迟函数,需要添加#include <windows.h>
system("cls");//清除屏幕,需要添加#include<stdlib.h>
}
}
}
int main()
{
int X,Y,num,*XZ,i,j,ms;//x,y为横纵轴,num为初始金钱,i,j为for循环计数使用,ms为刷新时间,即几毫秒刷新一次屏幕,times为刷新次数。
printf("******************************************************************************\n\n");
printf("-------------------控制台动态直方图(一个有趣的财富分配问题)-----------------\n\n");
printf("----------------------------完成时间:2017年7月12日---------------------------\n\n");
printf("----------------------------大一渣作,轻喷------------------------------------\n\n");
printf("----------------------------by:云空-------------------------------------------\n\n");
printf("******************************************************************************\n\n");
printf("房间内有50个人,每人拥有50元钱,每分钟随机给另一个人1块,最后这个房间内的财富\n\n分配是怎么样的?这个问题是我在知乎上看到的,同时这个文章的作者给出了一个关于这\n\n个问题的gif图,就是一个动态的直方图,感觉非常的帅气,于是自己试着做了个。\n\n个人感觉还不错,希望大家喜欢。\n\n原文链接:https://zhuanlan.zhihu.com/p/27797001?utm_source=qq&utm_medium=social\n\n");
printf("请输入金钱初始值:\n");
scanf("%d",&num);
printf("请输入样本数:\n");
scanf("%d",&X);
printf("请输入y轴最大值:\n");
scanf("%d",&Y);
printf("请输入运算次数:\n");
scanf("%d",×);
printf("请输入刷新时间间隔:\n");
scanf("%d",&ms);
XZ=(int *)malloc(X*sizeof(XZ));//动态开辟内存,创建数组;
for(j=0;j<X;j++)
{
XZ[j]=num;//初始化数组为金钱初始值
}
for(i=0;i<times;i++)
{
cal(XZ,Y,X,ms);//计算金钱流动并显示
ntime=i;
}
printf("运算完成!\n");
return 0;
}
上图为前文提到的知乎的gif图,下面为我的效果图=-=我也不知道怎么才能弄清楚一些,哎=-=
由于C语言控制台刷新率太低,所以会变成最下面那张图的效果,但增大刷新时间间隔即可改善。
PS2:我是大一的软工的学生,这个程序也只是突发奇想做的,我的编程技术并不是很好,所以大家不要太在意我的一些错误,技术有限,主要是这么个原理嘛。
问题:
房间内有100个人,每人拥有100元钱,每分钟随机给另一个人1块,最后这个房间内的财富分配是怎么样的?这个问题是我在知乎上看到的,同时这个文章的作者给出了一个关于这个问题的gif图,就是一个动态的直方图,感觉非常的帅气,于是自己试着做了个。个人感觉还不错,希望大家喜欢。原文链接:https://zhuanlan.zhihu.com/p/27797001?utm_source=qq&utm_medium=social
原理:1.构建直方图。用for循环构建就行了,每一行的第一个字符根据行数来判断是否输出为分段的数字,就是,5,15,20那些,第二个字符的话固定输出为边界“|”这个字符。
然后行数从上往下从0到你输入的行数循环,也可反向,然后再在每行的第三个字符用for循环来判断接下来的位置开始根据行数判断是输出空格(两个)还是黑方格。
这里的判断是根据样本数组来判断,样本数组中存储着每个样本的初始资金,若行数所在位置高于资金,就printf空格,反之printf方格。
2.资金交换。这里是根据随机出来的下标来进行交换的,随机数的话需要stdlib.h头文件,然后如下。
srand((unsigned) time(NULL)); //用时间做种,每次产生随机数不一样,需要stdlib.h头文件 temp=rand()%(X);//rand()%x为从0到x随机取值,rand()%x+1则为从1到x+1取值。 while(temp==i)//当取得随机下标为本身时,从新取随机值,此处用while是为了取随机值直到不等于本身。 { temp=rand()%(X);//防止取到本身值,将钱给自己。 } if(XZ[i]>0)//有钱时才能给 { XZ[temp]++;//目标的金钱加一 XZ[i]--;//自己金钱减一
3.清除屏幕的函数。动态显示其实就是通过不断清除屏幕后再显示出新的内容。和动画的制作原理是一样的。
system("cls");//清除屏幕,需要添加#include<stdlib.h>
4.延迟函数。
Sleep(ms);//延迟函数,需要添加#include <windows.h>
所有代码:
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<time.h>
int times,ntime;//ntime为当前时间,times为刷新次数
void draw(int XZ[],int Y,int X,int ifps)//ifps为当前给出钱的人数
{
int i,j;
printf("当前分钟给出钱的人数:%d\n\n",ifps);
printf("当前时间:第%d分钟\n\n",ntime);
for(i=0;i<Y;i++)//行数for循环
{
if(i%5==0)
{
printf("%2d",Y-i);//纵坐标参照
}
else
{
printf(" ");
}
printf("|");
for(j=0;j<X;j++)//在每行中进行每列的for循环
{
printf(" ");//空格
if(i<Y-XZ[j]-1)
printf(" "); //为便于计数,程序中i从上往下数,也就是从0到Y,而现实中当此列从下往上数时的行数大于此列的金钱时输出为两个空格,两个空格才能和一个黑方格等宽。
if(i==Y-XZ[j]-1)
printf("%2d",XZ[j]);
if(i>=Y-XZ[j])
printf("█");//程序中的i从上往下数时大于金钱的行数时,也就是现实中从下往上数小于等于金钱数时,输出为黑方格、
}
printf("\n");
}
printf(" 0");
for(i=0;i<Y+2;i++)
{
printf("一 ");//画出横坐标线
}
}
void cal(int XZ[],int Y,int X,int ms)//计算
{
int i,temp,ifps=0;
for(i=0;i<X;i++)
{
srand((unsigned) time(NULL)); //用时间做种,每次产生随机数不一样,需要stdlib.h头文件
temp=rand()%(X);//rand()%x为从0到x随机取值,rand()%x+1则为从1到x+1取值。
while(temp==i)//当取得随机下标为本身时,从新取随机值,此处用while是为了取随机值直到不等于本身。
{
temp=rand()%(X);//防止取到本身值,将钱给自己。
}
if(XZ[i]>0)//有钱时才能给
{
XZ[temp]++;//目标的金钱加一
XZ[i]--;//自己金钱减一
ifps++;//给出钱人数(次数)
draw(XZ,Y,X,ifps);//画出表格
Sleep(ms);//延迟函数,需要添加#include <windows.h>
system("cls");//清除屏幕,需要添加#include<stdlib.h>
}
}
}
int main()
{
int X,Y,num,*XZ,i,j,ms;//x,y为横纵轴,num为初始金钱,i,j为for循环计数使用,ms为刷新时间,即几毫秒刷新一次屏幕,times为刷新次数。
printf("******************************************************************************\n\n");
printf("-------------------控制台动态直方图(一个有趣的财富分配问题)-----------------\n\n");
printf("----------------------------完成时间:2017年7月12日---------------------------\n\n");
printf("----------------------------大一渣作,轻喷------------------------------------\n\n");
printf("----------------------------by:云空-------------------------------------------\n\n");
printf("******************************************************************************\n\n");
printf("房间内有50个人,每人拥有50元钱,每分钟随机给另一个人1块,最后这个房间内的财富\n\n分配是怎么样的?这个问题是我在知乎上看到的,同时这个文章的作者给出了一个关于这\n\n个问题的gif图,就是一个动态的直方图,感觉非常的帅气,于是自己试着做了个。\n\n个人感觉还不错,希望大家喜欢。\n\n原文链接:https://zhuanlan.zhihu.com/p/27797001?utm_source=qq&utm_medium=social\n\n");
printf("请输入金钱初始值:\n");
scanf("%d",&num);
printf("请输入样本数:\n");
scanf("%d",&X);
printf("请输入y轴最大值:\n");
scanf("%d",&Y);
printf("请输入运算次数:\n");
scanf("%d",×);
printf("请输入刷新时间间隔:\n");
scanf("%d",&ms);
XZ=(int *)malloc(X*sizeof(XZ));//动态开辟内存,创建数组;
for(j=0;j<X;j++)
{
XZ[j]=num;//初始化数组为金钱初始值
}
for(i=0;i<times;i++)
{
cal(XZ,Y,X,ms);//计算金钱流动并显示
ntime=i;
}
printf("运算完成!\n");
return 0;
}
上图为前文提到的知乎的gif图,下面为我的效果图=-=我也不知道怎么才能弄清楚一些,哎=-=
由于C语言控制台刷新率太低,所以会变成最下面那张图的效果,但增大刷新时间间隔即可改善。
相关文章推荐
- 关于堆,栈,动态分配,静态分配的一个小实验
- 关于javascript程序内存占用的一个有趣的实验
- 一个c语言构造函数调用的问题(有趣)
- C语言中关于指针,二维数组等的问题,一个有趣的发现
- [转贴] 一个关于C语言字串有趣的小题目
- C语言中实现动态分配二维数组
- 链表的C语言实现(含动态内存分配)
- 动态链接库中分配内存引起的问题-- windows已在XX.exe中触发一个断点
- 一个简洁的(javascript时钟)动态显示日期时间
- 给Swing程序添加一个动态显示内存情况的状态条
- 实验: 用CxImage在同一个DC上显示多幅PNG
- 链表的C语言实现之动态内存分配(转载)
- ComponentArt 动态加载的TreeView, 添加一个新节点后,新节点为什么在页面中不会显示?
- 用JAVASCIRPT写的一个动态显示日期的函数!
- Windows Memory - Memeory View 一个动态显示内存使用的SDK
- 哪位大哥知道怎么用new动态分配一个指针数组?
- 一个简单的能显示动态图片的类(一)
- C语言实现用程序数据段空间模拟内存的动态分配
- 今天研究了一个有趣的网络问题:双网卡DHCP(动态获取IP)
- 单片机实验——电子表(数码管动态显示技术)