算法之分钱问题小Demo

分钱问题是这样的:假设房间有100人,每人都有100园区,并且这100个人都自己创造该有的财富,如果你需要别人的商品,你需要拿1元钱去购买。那么最后的结果该会是如何呢?

显然这个问题就类似于生活在的日常,在持有相同金钱的社会中,随着社会的改变人们会产生商品并且消费。那么结果是如何呢?是持续着平均的经济体系还是加剧社会的分化呢?点击详情即可查看实现。

我们呢先不说结果,来跟着这个小Demo尝试一下自己探索吧。

环境介绍:

  • 语言:Java
  • 使用JDK:java 1.8
  • 工具:eclipse或者IDEA都可。
  • 主要技术:Swing awt

我们这里不介绍swing和awt的实现,而是直接借用模板来操作。模板中封装好了需要的一些简要实现。
需要的可以在这里下载模板源代码。

https://gitee.com/xiangzi1019/template_code/tree/master

首先介绍一下模板:

1.主要包含了一个框架AlgoFrame,其中内容主要用于绘制内部信息,和双缓存的实现。
2.AlgoVishelper看名称也可以知道,主要封装了一些帮助函数,例如绘制实体或者空心的圆、矩形、颜色等函数
3.AlgoVisualizer主要就是视图可见的操作,例如你想事先声明功能都可以写在这里,然后调用数据和帮助类就可以实现。

导入文档包之后呢,我们就先操作AlgoVisualizer类。我们根据我们的需求实现人和钱。这里呢主要创建了100个人,每人100元钱。

// TODO: 创建自己的数据
private int[] money;        // 数据
private AlgoFrame frame;    // 视图
private static int DELAY = 40;
public AlgoVisualizer(int sceneWidth, int sceneHeight){

    // 初始化数据
    //创建100个人,每人手里都有100元钱
    money = new int[100];
    for(int i = 0; i < money.length; i++) {
        money[i] = 100;
    }

关于视图对话框呢,这里使用的是JDK1.8的函数实编程,我们呢只需要改变它的标题即可。主要的意思就是,我们申请了一个线程,防止与主线程同步导致我们对话框难以其他操作。线程里调用了run方法实现我们的动画效果。然后直接start开始启动线程。

// 初始化视图
EventQueue.invokeLater(() -> {
    frame = new AlgoFrame("分钱问题", sceneWidth, sceneHeight);

    new Thread(() -> {
        run();
    }).start();
});

run的逻辑基本为,当我们运行时候,对我们人用于钱数排序,sort其实调用的就是快排思想。然后调用frame的重绘着色,线程延迟DELAY(ms)时间,开始实现我们的给钱功能。实际上就是我们每一帧给定每个人都向外给1元钱来保证自己每日的需求。然后呢随机卖商品的人得到一元钱加入自己的总量。(实际上是不科学的,因为现实社会中我们会购买更好的东西或者花更多的钱消费高档次的生活,这里只做模拟,不考虑任何其他消费)

// 动画逻辑
private void run(){
    while(true) {
        // TODO: 编写自己的动画逻辑
        //排序输出
        Arrays.sort(money);
        //重绘着色
        frame.render(money);
        //延迟
        AlgoVisHelper.pause(DELAY);
        for(int k = 0; k < 40; k++) {
            for(int i = 0; i < money.length; i++) {
                int j = (int)(Math.random()*money.length);
                money[i]-=1;
                money[j]+=1;
            }
        }
    }
}

其余本函数中不需要再做任何改变。因为得到了数据然后我们去AlgoFrame中去实现画面的显示操作。
首先我们也是设置数据,要求呢和之前数据保存一致。

 // TODO: 设置自己的数据
private int[] money;
public void render(int[] money){
    this.money = money;
    repaint();
}

然后就直接跳到具体绘制,因为绘制图形需要着色或者说调用系统函数,所以我们把数据放到绘制中,结合双缓存和抗锯齿实现更加精美的效果。

//设置宽度
int w = canvasWidth/money.length;
for(int i = 0;i < money.length; i++) {
    //当前为证显示红色,为负显示绿色
    //g2d为绘制的图形
    if(money[i] > 0) {
        AlgoVisHelper.setColor(g2d, AlgoVisHelper.Red);
        //设置矩形大小
        AlgoVisHelper.fillRectangle(g2d, i*w+1, canvasHeight/2-money[i], w-1, money[i]);
    }else {
        AlgoVisHelper.setColor(g2d, AlgoVisHelper.Green);
        AlgoVisHelper.fillRectangle(g2d, i*w+1, canvasHeight/2, w-1, -money[i]);
    }
}

我们可以看到,先设置颜色,告诉系统我要什么什么颜色,然后再设置矩形大小,数据依次为:绘制的图形,宽度,左,右像素,宽度,高度。

鉴于此我们就把这个程序弄完了,现在点击运行,就能得到结果。

刚开始显示:

持续一段时间出现了负值:

又一段时间后,出现了函数式的曲线样式:

由此可以我们分析一下,这应该挺符合资本社会中贫富差距巨大化的原因吧。提醒一点的是,我们看到的最大正负值不一定是同一个人,因为下一次它可能会给别人钱,然后有的人又成为了新的首富或者最穷。类比一下有可能大老板破产了呢,资金也能为负数。当然负数值意味着花呗?借呗?现在生活中的大量借记卡吧。

声明:本文章是基于liuyubo老师的代码实例所写。只用于学习。别无其他。

感谢您的鼓励.如果喜欢可以送我一包辣条。