• command三国杀开发日记20200915


    一句话进展

    1. 完善了程序结构,分离.c和.h
    2. 搭建了6个阶段函数
    3. 实现了玩家摸牌
    4. 封装实现了日志打印函数

    日志打印

    想要区分日志等级,包括DEBUGINFOWARNERRROPANIC,提供统一的日志打印接口,能够按级别打开、关闭日志

    大体实现是定义了一个变量now_log_level记录当前日志打印级别,提供一个接口去修改

    enum Log_Level {LDEBUG=0, LINFO, LWARN, LERROR, LPANIC};
    
    void Set_Log_Level(enum Log_Level ll)
    {
        now_log_level = ll;
    }
    

    然后封装了一个Log函数

    void Log(enum Log_Level ll,va_list va_alist,...)
    {
        va_list args;
        va_start(args ,va_alist);
        if(now_log_level <= ll)    //注意&和<<优先级
        {
            switch (ll) {
            case LDEBUG:
                printf("[DEBUG] ");
                break;
            case LINFO:
                printf("[INFO ] ");
                break;
            case LWARN:
                printf("[WARN ] ");
                break;
            case LERROR:
                printf("[ERROR] ");
                break;
            case LPANIC:
                printf("[PANIC] ");
                break;
            default:
                break;
            }
            vfprintf(stderr, va_alist, args);
        }
        va_end(args);
    
        if (ll == LPANIC) {
            exit(1);
        }
    }
    

    实现效果:

    六大阶段

    准备阶段判定阶段摸牌阶段出牌阶段弃牌阶段结束阶段

    目前只是打了桩函数,流程大概长这样:

    for (int i = 0; i < 5; i++) {
                Stage_Preparation(player[i]);
                Stage_Determination(player[i]);
                Stage_Touch(player[i]);
                UI_draw_my_card(player[0]);
                Stage_Play(player[i]);
                Stage_Discard(player[i]);
                Stage_Finish(player[i]);
                system("pause");
    }
    

    牌堆初始化

    维护一个Card_List,叫做card_heap_unused,代表剩余的牌堆

    struct Card_List{
    	struct Card* card;
    	struct Card_List *next;
    };
    
    struct Card_List *card_heap_unused;
    

    采用带哨兵节点的链表来实现,初始化牌堆,创建哨兵节点

    card_heap_unused = malloc(sizeof(struct Card_List));
    card_heap_unused->next = NULL;
    

    将所有定义在结构体数组cards中的卡牌加入牌堆。
    结构体数组已经分配了内存空间,这里不再为 struct Card变量分配额外的空间,而是选择直接将指针指向结构体的元素
    只分配struct Card_List元数据所需要的内存

    struct Card_List *ch = card_heap_unused;
    for (int i = 0; i < card_total_cnt; i++) {
        ch->next = malloc(sizeof(struct Card_List));
        ch = ch->next;
        ch->card = &cards[i];
        ch->next = NULL;
        Log(LDEBUG, "初始化卡牌 [%s] [花色 %d - 点数 %d]
    ", ch->card->name, ch->card->color, ch->card->point);
        card_head_unused_number++;
    }
    
    

    摸牌

    维护了一个全局变量card_head_unused_number记录牌堆中剩余牌数量

    摸牌阶段

        if (card_head_unused_number >= 2) {
            if (p->id == 0) { // 目前只调试玩家摸牌
                Touch_Card(p);
                Touch_Card(p);
            }
        } else {
            Log(LPANIC, "牌堆数量不够!
    ");
        }
    

    摸牌函数

    void Touch_Card(struct Player *p) {
        if (card_heap_unused == NULL) {
            Log(LPANIC, "card_heap_unused == NULL");
        }
    
        struct Card_List *tmp = malloc(sizeof(struct Card_List));
        tmp->card = card_heap_unused->next->card;
    
        // 将这张牌插入手牌
        tmp->next = p->hand_card->next;
        p->hand_card->next = tmp;
        // 从牌堆中移除
        card_heap_unused->next = card_heap_unused->next->next;
        card_head_unused_number -= 1;
    
    }
    

    入参为摸牌者,将牌堆card_heap_unused顶部的Card移入玩家p的手牌链表hand_card

    效果

    可以看到,经过摸牌阶段后,正确摸取了牌堆最顶的两张卡牌。

  • 相关阅读:
    『转载』优秀ASP.NET程序员的修炼之路
    [转]给年轻工程师的十大忠告
    [转]谈谈技术原则,技术学习方法,代码阅读及其它
    【转贴】你必须知道的20个故事
    谈谈建站心得(转载)[精华]
    HTTP和SOAP完全就是两个不同的协议
    数据集的理解IDataset
    学习在 ArcEngine 中使用 Geoprocessing
    程序执行过程
    How to Run a Geoprocessing Tool
  • 原文地址:https://www.cnblogs.com/velscode/p/13676438.html
Copyright © 2020-2023  润新知