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

C语言游戏地图模块:插入/删除/打印区域函数修复请求

C语言恐怖游戏循环链表地图函数修复

问题背景

开发基于C语言的恐怖题材游戏,游戏地图采用循环链表存储Zona_mappa结构体。当前实现中,inserisci_zona(区域插入)、cancella_zona(区域删除)、stampa_mappa(地图打印)三个函数存在功能异常,需针对性修复。

修复需求

  • 区域类型需等概率随机生成
  • 区域物品需符合概率规则:NESSUN_OGGETTO占40%,其余物品等概率分配剩余60%
  • 确保循环链表的插入、删除、打印操作逻辑完全正确

完整修复代码

头文件(gioco_horror.h)

#ifndef GIOCO_HORROR_H
#define GIOCO_HORROR_H

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

// 区域类型枚举
typedef enum {
    CORRIDOIO,
    STANZA,
    LABIRINTO,
    SALA_ATTESA,
    NUM_TIPI_ZONA // 用于计算类型总数
} TipoZona;

// 物品类型枚举
typedef enum {
    NESSUN_OGGETTO,
    CHIAVE,
    POTIONE_SALUTE,
    ARMA,
    AMULETTO,
    NUM_OGGETTI // 用于计算物品总数
} TipoOggetto;

// 地图区域结构体
typedef struct Zona_mappa {
    TipoZona tipo;
    TipoOggetto oggetto;
    struct Zona_mappa* prossima;
} Zona_mappa;

// 函数声明
void inizializza_srand();
TipoZona genera_tipo_zona();
TipoOggetto genera_oggetto();
Zona_mappa* inserisci_zona(Zona_mappa* testa, TipoZona tipo, TipoOggetto oggetto);
Zona_mappa* cancella_zona(Zona_mappa** testa, int indice);
void stampa_mappa(Zona_mappa* testa);
void libera_mappa(Zona_mappa* testa);

#endif

源文件(gioco_horror.c)

#include "gioco_horror.h"

// 初始化随机数种子
void inizializza_srand() {
    srand(time(NULL));
}

// 等概率生成区域类型
TipoZona genera_tipo_zona() {
    return (TipoZona)(rand() % NUM_TIPI_ZONA);
}

// 按概率生成物品:NESSUN_OGGETTO占40%,其余等概率
TipoOggetto genera_oggetto() {
    int rand_val = rand() % 100;
    if (rand_val < 40) {
        return NESSUN_OGGETTO;
    } else {
        // 剩余60%分配给其余4种物品,每种15%
        int oggetto_idx = (rand_val - 40) % (NUM_OGGETTI - 1);
        return (TipoOggetto)(oggetto_idx + 1);
    }
}

// 循环链表插入区域(尾部插入)
Zona_mappa* inserisci_zona(Zona_mappa* testa, TipoZona tipo, TipoOggetto oggetto) {
    Zona_mappa* nuova_zona = (Zona_mappa*)malloc(sizeof(Zona_mappa));
    if (!nuova_zona) {
        perror("Errore allocazione memoria");
        exit(EXIT_FAILURE);
    }
    nuova_zona->tipo = tipo;
    nuova_zona->oggetto = oggetto;

    if (!testa) {
        // 空链表,新节点自己形成循环
        nuova_zona->prossima = nuova_zona;
        return nuova_zona;
    }

    // 找到最后一个节点(prossima指向testa的节点)
    Zona_mappa* corrente = testa;
    while (corrente->prossima != testa) {
        corrente = corrente->prossima;
    }

    corrente->prossima = nuova_zona;
    nuova_zona->prossima = testa;
    return testa;
}

// 按索引删除循环链表节点
Zona_mappa* cancella_zona(Zona_mappa** testa, int indice) {
    if (!*testa) {
        printf("Mappa vuota, nessuna zona da cancellare.\n");
        return NULL;
    }

    Zona_mappa* corrente = *testa;
    Zona_mappa* precedente = NULL;

    // 处理只有一个节点的情况
    if (corrente->prossima == *testa) {
        free(corrente);
        *testa = NULL;
        return NULL;
    }

    // 找到目标节点
    int i = 0;
    while (i < indice && corrente->prossima != *testa) {
        precedente = corrente;
        corrente = corrente->prossima;
        i++;
    }

    if (i != indice) {
        printf("Indice fuori dai limiti.\n");
        return *testa;
    }

    // 删除节点:如果是头节点
    if (corrente == *testa) {
        // 找到最后一个节点,让它指向新的头节点
        Zona_mappa* ultimo = *testa;
        while (ultimo->prossima != *testa) {
            ultimo = ultimo->prossima;
        }
        *testa = corrente->prossima;
        ultimo->prossima = *testa;
    } else {
        precedente->prossima = corrente->prossima;
    }

    free(corrente);
    return *testa;
}

// 打印循环链表所有区域
void stampa_mappa(Zona_mappa* testa) {
    if (!testa) {
        printf("Mappa vuota.\n");
        return;
    }

    Zona_mappa* corrente = testa;
    int contatore = 0;
    char* tipo_nomi[] = {"Corridoio", "Stanza", "Labirinto", "Sala d'attesa"};
    char* oggetto_nomi[] = {"Nessun oggetto", "Chiave", "Pozione di salute", "Arma", "Amuletto"};

    do {
        printf("Zona %d:\n", contatore);
        printf("  Tipo: %s\n", tipo_nomi[corrente->tipo]);
        printf("  Oggetto: %s\n\n", oggetto_nomi[corrente->oggetto]);
        corrente = corrente->prossima;
        contatore++;
    } while (corrente != testa);
}

// 释放循环链表内存
void libera_mappa(Zona_mappa* testa) {
    if (!testa) return;

    Zona_mappa* corrente = testa;
    Zona_mappa* prossima;

    do {
        prossima = corrente->prossima;
        free(corrente);
        corrente = prossima;
    } while (corrente != testa);
}

// 测试主函数
int main() {
    inizializza_srand();
    Zona_mappa* mappa = NULL;

    // 插入5个随机区域
    for (int i = 0; i < 5; i++) {
        TipoZona tipo = genera_tipo_zona();
        TipoOggetto oggetto = genera_oggetto();
        mappa = inserisci_zona(mappa, tipo, oggetto);
    }

    printf("=== Mappa iniziale ===\n");
    stampa_mappa(mappa);

    // 删除索引2的区域
    printf("\n=== Dopo cancellazione zona indice 2 ===\n");
    mappa = cancella_zona(&mappa, 2);
    stampa_mappa(mappa);

    libera_mappa(mappa);
    return 0;
}

关键修复点说明

  1. 区域类型随机生成:

    • 新增NUM_TIPI_ZONA枚举值,避免硬编码类型数量
    • genera_tipo_zona函数通过rand() % NUM_TIPI_ZONA实现等概率随机
  2. 物品概率控制:

    • 新增NUM_OGGETTI枚举值,方便扩展物品类型
    • genera_oggetto函数通过100份概率分配:前40份返回NESSUN_OGGETTO,剩余60份平均分配给其他4种物品(每种15%)
  3. 循环链表操作修复:

    • 插入函数:处理空链表情况,确保新节点形成循环;非空链表时找到最后一个节点(指向头节点的节点),将其prossima指向新节点,新节点再指向头节点
    • 删除函数:单独处理单节点链表;删除头节点时需更新最后一个节点的prossima指向新头节点;处理索引越界情况
    • 打印函数:使用do-while循环确保循环链表的所有节点都被遍历,避免遗漏头节点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 03:30:39