C竞争模式模拟抢红包程序

程序设计范式四

要求
从txt文件里面读入群成员名称
输入红包个数:10
输入红包金额:88.88
随机分配金额到10个小红包里面,要考虑特殊情况(红包数量不能超过总人数,不能是负数,要够分)
(金有额一定要对得上,要足够随机,不要太平均)
20个线程---去抢红包。用互斥锁,锁住竞争资源,不要导致分配错误,抢的过程添加一些随机延时
显示人员---金额的分配表
 

实现代码中对金额的随机分配集中在avg左右,随机幅度除去最后一个数后较小。

#include <iostream>  
#include <cstring>  
#include <pthread.h>  
#include <cmath> // 引入cmath头文件来使用round函数  
#include <cstdlib>  
#include <ctime> 
#include <unistd.h> 
#define MAX_NAMES 100  
#define MAX_PACKETS 100  
  
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;  
char names[MAX_NAMES][100];  
int num_names = 0;  
double remaining_sum = 0.0; // 剩余总金额  
int total = 0; // 剩余红包数量  
  
double getRandMoney(){  
    if(remaining_sum <= 0 || total <= 0){  
        return 0;  
    }  
    if (total == 1) {
        total--;
        return remaining_sum;
    } 
    double avg = remaining_sum / total;  
    double min = avg / 2;  
    if (min < 0.01) min = 0.01; // 避免分配过小的红包  
    double max = (avg * 2 > remaining_sum) ? remaining_sum : avg * 2;  
      
    double money = min + (max - min) * ((double)rand() / RAND_MAX);  
    money = std::round(money * 100) / 100.0; // 四舍五入到小数点后两位  
      
    if (money > remaining_sum) {  
        money = remaining_sum;  
    }  
      
    remaining_sum -= money;  
    total--;  
      
    return money;  
}
void* distribute_to_name(void* arg) {  
    char* name = (char*)arg;  
    double money = 0.0;
    pthread_mutex_lock(&mtx);  
    if (total > 0) {  
        money = getRandMoney(); // 尝试获取红包金额  
        if (money > 0.0) {  
            printf("%s抢到了%.2lf元\n", name, money);  
        }
    }
    else {  
            printf("%s没有抢到红包\n", name);  
        } 
    pthread_mutex_unlock(&mtx);  
    return NULL;  
}  
  
void readNamesFromFile(const char* filename, int max_names) {  
    FILE* file = fopen(filename, "r");  
    if (!file) {  
        perror("无法打开文件");  
        exit(1);  
    }  
    while (num_names < max_names && fscanf(file, "%99s", names[num_names]) == 1) {  
        num_names++;  
    }  
    fclose(file);  
}  


void distributeRedPacket(int numPackets, double totalAmount, int numNames) {  
    if (numPackets > MAX_PACKETS) {  
        fprintf(stderr, "红包个数不能超过%d个\n", MAX_PACKETS);  
        exit(1);  
    }  
    num_names = numNames;  
    remaining_sum = totalAmount; // 设置剩余总金额  
    total = numPackets; // 假设每个名字都可以分到一个红包  
      
    srand(time(NULL)); // 初始化随机数生成器  
  	
    pthread_t threads[num_names];
    
    for (int i = 0; i < num_names; i++) {  
        pthread_create(&threads[i], NULL, distribute_to_name, (void*)names[i]);
        sleep(rand() % 2);
    }  
    for (int i = 0; i < num_names; i++) {  
        pthread_join(threads[i], NULL);  
    }  
}  
  
int main() {  
    char filename[] = "D:\\class1.txt";  
    readNamesFromFile(filename, MAX_NAMES);  
  
    int numPackets;
    double totalAmount;
    printf("红包个数:");  
    scanf("%d", &numPackets);  
    printf("总金额:");  
    scanf("%lf", &totalAmount);  
  
    distributeRedPacket(numPackets, totalAmount, num_names);  
    return 0;  
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值