You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

x86汇编Powerball模拟器问题:宏调用与代码简化求助

Powerball抽奖模拟器:宏数组传参与代码简化方案

一、正确传递数组到宏的方法

宏在预处理阶段直接展开代码,数组作为参数传入时会退化为指针,无法直接获取数组长度,因此必须显式传递数组长度,同时用do-while(0)包裹宏代码避免语法陷阱(比如if分支后不加括号引发的逻辑错误)。

示例宏定义

// 宏参数:用户主号码数组、用户数组长度、开奖主号码数组、开奖数组长度、用户Powerball号、开奖Powerball号
#define CHECK_POWERBALL_WIN(user_nums, user_len, draw_nums, draw_len, pb_user, pb_draw) \
do { \
    int main_match = 0; \
    // 统计主号码匹配数
    for (int i = 0; i < user_len; i++) { \
        for (int j = 0; j < draw_len; j++) { \
            if ((user_nums[i]) == (draw_nums[j])) { \
                main_match++; \
                break; \
            } \
        } \
    } \
    // 判断Powerball匹配情况
    int pb_match = ((pb_user) == (pb_draw)) ? 1 : 0; \
    // 输出中奖结果
    if (main_match == 5 && pb_match == 1) { \
        puts("头奖!恭喜你赢得Powerball大奖!"); \
    } else if (main_match == 5) { \
        puts("二等奖:匹配5个主号码"); \
    } else if (main_match == 4 && pb_match == 1) { \
        puts("三等奖:匹配4个主号码+Powerball"); \
    } else { \
        printf("未中奖,匹配%d个主号码,Powerball%s匹配\n", main_match, pb_match ? "" : "未"); \
    } \
} while(0)

宏调用方式

#include <stdio.h>

int main() {
    int user_main[] = {12, 23, 34, 45, 56};
    int draw_main[] = {23, 34, 56, 78, 90};
    int user_pb = 7;
    int draw_pb = 7;

    // 调用宏,传递数组、长度及Powerball号码
    CHECK_POWERBALL_WIN(
        user_main, sizeof(user_main)/sizeof(user_main[0]),
        draw_main, sizeof(draw_main)/sizeof(draw_main[0]),
        user_pb, draw_pb
    );
    return 0;
}

注意:宏中所有参数引用都加括号(),避免因参数是表达式导致的运算符优先级错误。

二、代码简化方案

1. 用排序+双指针替代双重循环,提升效率与简洁度

把主号码数组排序后,用双指针遍历统计匹配数,比嵌套循环更高效,代码更简洁:

#include <stdio.h>
#include <stdlib.h>

// 整数比较函数,用于qsort排序
int int_cmp(const void* a, const void* b) {
    return *(int*)a - *(int*)b;
}

#define CHECK_POWERBALL_WIN(user_nums, user_len, draw_nums, draw_len, pb_user, pb_draw) \
do { \
    qsort(user_nums, user_len, sizeof(int), int_cmp); \
    qsort(draw_nums, draw_len, sizeof(int), int_cmp); \
    \
    int main_match = 0; \
    int i = 0, j = 0; \
    while (i < user_len && j < draw_len) { \
        if ((user_nums[i]) == (draw_nums[j])) { \
            main_match++; \
            i++; j++; \
        } else if ((user_nums[i]) < (draw_nums[j])) { \
            i++; \
        } else { \
            j++; \
        } \
    } \
    \
    int pb_match = ((pb_user) == (pb_draw)) ? 1 : 0; \
    // 中奖判断逻辑同前... \
} while(0)

2. 封装重复逻辑为辅助函数

将号码生成、用户输入等非核心逻辑封装成函数,让宏只负责核心比对:

// 生成指定范围的不重复随机开奖号码
void generate_draw_numbers(int* nums, int len, int min, int max) {
    // 实现随机生成+去重逻辑(可结合rand()和循环判断)
}

// 获取用户输入的号码
void get_user_numbers(int* nums, int len, int min, int max) {
    printf("请输入%d个主号码(范围%d-%d):", len, min, max);
    for (int i = 0; i < len; i++) {
        scanf("%d", &nums[i]);
    }
}

3. 用枚举定义中奖等级,提升代码可读性

typedef enum {
    NO_WIN,
    WIN_3,
    WIN_3_PB,
    WIN_4,
    WIN_4_PB,
    WIN_5,
    JACKPOT
} WinRank;

在宏中根据匹配数映射到对应的枚举值,再输出结果,代码逻辑更清晰易维护。

内容的提问来源于stack exchange,提问作者Kasizah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 14:35:20