Closed. This question needs details or clarity. It is not currently accepting answers. Learn more
想改进这个问题吗?添加细节并通过editing this post澄清问题。
三年前关闭。
我有以下文件:
例19.c:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "object.h"
#include "ex19.h"
//#include "gamemechanics.h"


int main(int argc, char *argv[])
{
    // simple way to setup the randomness
    srand(time(NULL));

    // make our map to work with
    Map *game = NEW(Map, "The Hall of the Minotaur.");

    /*printf("You enter the ");
    game->location->_(describe)(game->location);

    while(process_input(game)) {
    }*/

    return 0;
}

游戏力学c:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "ex19.h"
#include "object.h"
//#include "gamemechanics.h"

int Monster_attack(void *self, int damage)
{
    Monster *monster = self;

    printf("You attack %s!\n", monster->_(description));

    monster->hit_points -= damage;

    if(monster->hit_points > 0) {
        printf("It is still alive.\n");
        return 0;
    } else {
        printf("It is dead!\n");
        return 1;
    }
}

int Monster_init(void *self)
{
    Monster *monster = self;
    monster->hit_points = 10;
    return 1;
}

Object MonsterProto = {
    .init = Monster_init,
    .attack = Monster_attack
};


void *Room_move(void *self, Direction direction)
{
    Room *room = self;
    Room *next = NULL;

    if(direction == NORTH && room->north) {
        printf("You go north, into:\n");
        next = room->north;
    } else if(direction == SOUTH && room->south) {
        printf("You go south, into:\n");
        next = room->south;
    } else if(direction == EAST && room->east) {
        printf("You go east, into:\n");
        next = room->east;
    } else if(direction == WEST && room->west) {
        printf("You go west, into:\n");
        next = room->west;
    } else if(direction == SOUTHWEST && room->southwest) {
        printf("You go southwest, into:\n");
        next = room->southwest;
    } else if(direction == NORTHEAST && room->northeast) {
        printf("You go northeast, into: \n");
        next = room->northeast;
    } else if(direction == NORTHWEST && room->northwest) {
        printf("You go northwest, into: \n");
        next = room->northwest;
    } else if(direction == SOUTHEAST && room->southeast) {
        printf("You go southeast, into: \n");
        next = room->southeast;
    } else {
        printf("You can't go that direction.");
        next = NULL;
    }

    if(next) {
        next->_(describe)(next);
    }

    return next;
}


int Room_attack(void *self, int damage)
{
    Room *room = self;
    Monster *monster = room->bad_guy;

    if(monster) {
        monster->_(attack)(monster, damage);
        return 1;
    } else {
        printf("You flail in the air at nothing. Idiot.\n");
        return 0;
    }
}


Object RoomProto = {
    .move = Room_move,
    .attack = Room_attack
};


void *Map_move(void *self, Direction direction)
{
    Map *map = self;
    Room *location = map->location;
    Room *next = NULL;

    next = location->_(move)(location, direction);

    if(next) {
        map->location = next;
    }

    return next;
}

int Map_attack(void *self, int damage)
{
    Map* map = self;
    Room *location = map->location;

    return location->_(attack)(location, damage);
}


int Map_init(void *self)
{
    Map *map = self;

    // make some rooms for a small map
    Room *hall = NEW(Room, "The great Hall");
    Room *throne = NEW(Room, "The throne room");
    Room *arena = NEW(Room, "The arena, with the minotaur");
    Room *kitchen = NEW(Room, "Kitchen, you have the knife now");
    Room *bathroom = NEW(Room, "The bathroom, place where people shit");
    Room *playroom = NEW(Room, "A child's playroom");
    Room *dungeon = NEW(Room, "The dungeon with the witch");
    Room *jail = NEW(Room, "The jail with crooked criminals");

    // put the bad guy in the arena
    arena->bad_guy = NEW(Monster, "The evil minotaur");
    //ashwini is adding a new monster
    dungeon->bad_guy = NEW(Monster,"Witch");
    dungeon->bad_guy->hit_points = 20;

    // setup the map rooms
    hall->north = throne;

    throne->west = arena;
    throne->east = kitchen;
    throne->south = hall;

    arena->east = throne;
    kitchen->west = throne;

    //ashwini's addition to the map
    throne->northeast = dungeon;
    kitchen->north = dungeon;
    dungeon->southwest = throne;
    dungeon->south = kitchen;
    dungeon->east = jail;

    throne->northwest = jail;
    arena->north = jail;
    jail->southeast = throne;
    jail->south = arena;
    jail->east = dungeon;

    throne->southeast = playroom;
    kitchen->south = playroom;
    playroom->north = kitchen;
    playroom->west = hall;
    playroom->northwest = throne;

    throne->southwest = bathroom;
    arena->south = bathroom;
    bathroom->northeast = throne;
    bathroom->north = arena;
    bathroom->east = hall;

    // start the map and the character off in the hall
    map->start = hall;
    map->location = hall;

    return 1;
}

Object MapProto = {
    .init = Map_init,
    .move = Map_move,
    .attack = Map_attack
};



int process_input(Map *game)
{
    printf("\n> ");

    char ch = getchar();
    getchar(); // eat ENTER

    int damage = rand() % 4;

    switch(ch) {
        case -1:
            printf("Giving up? You suck.\n");
            return 0;
            break;

        case 'n':
            game->_(move)(game, NORTH);
            break;

        case 'N':
            game->_(move)(game,NORTHEAST);
            break;

        case 's':
            game->_(move)(game, SOUTH);
            break;

        case 'S':
            game->_(move)(game,SOUTHWEST);
            break;

        case 'e':
            game->_(move)(game, EAST);
            break;

        case 'E':
            game->_(move)(game,SOUTHEAST);
            break;

        case 'w':
            game->_(move)(game, WEST);
            break;

        case 'W':
            game->_(move)(game,NORTHWEST);
            break;

        case 'a':

            game->_(attack)(game, damage);
            break;

        case 'l':
            printf("You can go:\n");
            if(game->location->north) printf("NORTH(n)\n");
            if(game->location->south) printf("SOUTH(s)\n");
            if(game->location->east) printf("EAST(e)\n");
            if(game->location->west) printf("WEST(w)\n");
            if(game->location->northeast) printf("NORTHEAST(N)\n");
            if(game->location->northwest) printf("NORTHWEST(W)\n");
            if(game->location->southeast) printf("SOUTHEAST(E)\n");
            if(game->location->southwest) printf("SOUTHWEST(S)\n");
            break;

        default:
            printf("What?: %d\n", ch);
    }

    return 1;
}

例19.h
#ifndef _ex19_h
#define _ex19_h

#include "object.h"

struct Monster {
    Object proto;
    int hit_points;
};

typedef struct Monster Monster;

int Monster_attack(void *self, int damage);
int Monster_init(void *self);

struct Room {
    Object proto;

    Monster *bad_guy;

    struct Room *north;
    struct Room *south;
    struct Room *east;
    struct Room *west;
    struct Room *southwest;
    struct Room *southeast;
    struct Room *northeast;
    struct Room *northwest;
};

typedef struct Room Room;

void *Room_move(void *self, Direction direction);
int Room_attack(void *self, int damage);
int Room_init(void *self);


struct Map {
    Object proto;
    Room *start;
    Room *location;
};

typedef struct Map Map;

void *Map_move(void *self, Direction direction);
int Map_attack(void *self, int damage);
int Map_init(void *self);

#endif

对象c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "object.h"
#include <assert.h>

void Object_destroy(void *self)
{
    Object *obj = self;
    assert(obj != NULL);
    if(obj) {
        if(obj->description) free(obj->description);
        free(obj);
    }
}

void Object_describe(void *self)
{
    Object *obj = self;
    assert(obj!=NULL);
    printf("%s.\n", obj->description);
}

int Object_init(void *self)
{
    // do nothing really
    return 1;
}

void *Object_move(void *self, Direction direction)
{
    printf("You can't go that direction.\n");
    return NULL;
}

int Object_attack(void *self, int damage)
{
    printf("You can't attack that.\n");
    return 0;
}

void *Object_new(size_t size, Object proto, char *description)
{
    assert(description != NULL);
    // setup the default functions in case they aren't set
    if(!proto.init) proto.init = Object_init;
    if(!proto.describe) proto.describe = Object_describe;
    if(!proto.destroy) proto.destroy = Object_destroy;
    if(!proto.attack) proto.attack = Object_attack;
    if(!proto.move) proto.move = Object_move;

    // this seems weird, but we can make a struct of one size,
    // then point a different pointer at it to "cast" it
    Object *el = calloc(1, size);
    assert(el!=NULL);
    *el = proto;

    // copy the description over
    el->description = strdup(description);

    // initialize it with whatever init we were given
    if(!el->init(el)) {
        // looks like it didn't initialize properly
        el->destroy(el);
        return NULL;
    } else {
        // all done, we made an object of any type
        return el;
    }
}

对象h
#ifndef _object_h //this is if note defined
#define _object_h //checks if there is alread an object_h
//above is usefule if we are including it multiple times, it doesn't reinclude,
//just does it once and keeps refereing back

typedef enum {
    NORTH, SOUTH, EAST, WEST, SOUTHWEST, NORTHWEST, SOUTHEAST,NORTHEAST
} Direction;

typedef struct {
    char *description;
    int (*init)(void *self);
    void (*describe)(void *self);
    void (*destroy)(void *self);
    void *(*move)(void *self, Direction direction);
    int (*attack)(void *self, int damage);
} Object;

int Object_init(void *self);
void Object_destroy(void *self);
void Object_describe(void *self);
void *Object_move(void *self, Direction direction);
int Object_attack(void *self, int damage);
void *Object_new(size_t size, Object proto, char *description);

#define NEW(T, N) Object_new(sizeof(T), T##Proto, N)
#define _(N) proto.N

#endif

我试图使ex19.c使用gamemechanics.c中的函数和结构。但是每当我尝试编译时,都会得到以下错误:
    :~/c_learning/ex19_folder$ gcc -c ex19.c gamemechanics.c object.c
In file included from ex19.c:6:0:
ex19.c: In function ‘main’:
ex19.c:17:21: error: ‘MapProto’ undeclared (first use in this function)
     Map *game = NEW(Map, "The Hall of the Minotaur.");
                     ^
object.h:26:41: note: in definition of macro ‘NEW’
 #define NEW(T, N) Object_new(sizeof(T), T##Proto, N)
                                         ^
ex19.c:17:21: note: each undeclared identifier is reported only once for each function it appears in
     Map *game = NEW(Map, "The Hall of the Minotaur.");
                     ^
object.h:26:41: note: in definition of macro ‘NEW’
 #define NEW(T, N) Object_new(sizeof(T), T##Proto, N)
                                         ^

我的问题是,我如何开始弄清楚真正发生了什么,因为在这一点上,我只是做一个混合和匹配,只是看看是什么使它工作,但这并不能帮助我理解为什么会发生错误(因为它总是失败)。所以,首先为什么我会得到一个错误的MapProto未声明,即使我在gamemechanics.c中声明了?。我试过创建游戏机制。但后来我对依赖项的工作方式感到困惑。这是ex19从学c的艰辛之路。我可以尝试创建一个gamemechanics.h来创建函数原型,但是我很困惑如何在系统中实现它。任何建议都会有帮助的。关于如何使这个问题更容易理解的建议也会有帮助。

最佳答案

当编译器解析ex19.c时,它只知道
标准标题
对象h
例19.h
例19.c
因为这些是ex19.c引用的唯一文件。即使您在命令行中指定了gamemechanics.c,编译器在编译ex19.c时也不会查看该文件。
如果希望编译器在编译ex19.c时了解MapProto,则需要创建gamemechanics.h并将该文件包含在ex19.c中
你在游戏机制中需要的声明

extern Object MapProto;

关于c - ex19通过困难的方式学习c。错误:未声明“MapProto”(此功能首次使用),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34501049/

10-10 17:12