2016-11-11 5 views
1

Cで単純なテキストアドベンチャープログラムを作成しようとしています。各部屋の名前/説明を設定しようとしたときにstrcpy()ゲーム(room_setup()を参照)。最初の2つ(NO_ROOMとKITCHEN)を除くすべての部屋の名前/説明を設定します。簡単なテストとして strcpy()は一部の文字列では機能しません。他の文字列では機能しません。

#include <stdio.h> 
#include <stdbool.h> 
#include <string.h> 
#include <ctype.h> 

#define DIRS 4 
#define DEBUG 0 
#define MAX_INPUT_LENGTH 100 

// defines numeric values for each direction 
typedef enum {NORTH, EAST, SOUTH, WEST} en_dirs; 

// defines numeric values for each room 
typedef enum { 
    KITCHEN, 
    PANTRY, 
    HALLWAY_1, 
    HALLWAY_2, 
    TROLLS_DOMAIN, 
    EMPTY_ROOM_1, 
    EMPTY_ROOM_2, 
    EXIT, 
    NO_ROOM 
} en_rooms; 

// defines numeric values for each item 
typedef enum{ 
    APPLE, 
    KEY, 
    NO_ITEM 
} en_items; 

// defines a struct type to store room data 
typedef struct room{ 
    char name[100]; 
    char desc[100]; 
    en_dirs around[DIRS]; 
} Room; 

// defines a struct type to store item data 
typedef struct items{ 
    char name[100]; 
    char desc[100]; 
} Item; 

void str_read(char *s);  // read string from console, point s to it 
void str_upper(char *s); // convert string to upper case 
void room_setup(Room *r); // fill info about rooms into r array 
void item_setup(Item *i); // fill info about items into i array 

int main(void){ 
    char input[MAX_INPUT_LENGTH]; 
    char *verb, *noun; 

    // arrays to store room and item info. NO_**** is always the final element 
    // in their respective enums, so the size of the array will never be larger 
    // than necessary. 
    Room rooms[NO_ROOM]; 
    Item items[NO_ITEM]; 

    room_setup(rooms); // fill rooms array with info 
    item_setup(items); // fill items array with info 

    en_rooms currentRoom = KITCHEN; // set the starting room to the kitchen 

    // main game loop 
    while(1){ 

     // print current room name + description 
     printf("-- %s --\n", rooms[currentRoom].name); 
     printf("%s\n", rooms[currentRoom].desc); 

     printf("\n> "); 

     // read input and convert it to upper case 
     str_read(input); 
     str_upper(input); 

     if(DEBUG){ 
      printf("Input: %s\n", input); 
      printf("Length: %d\n", strlen(input)); 
     } 

     // split input into two pieces (expects max of two words, for now) 
     verb = strtok(input, " "); 
     noun = strtok(NULL, " "); 

     if(DEBUG){ 
      printf("Verb: %s\n", verb); 
      printf("Noun: %s\n", noun); 
     } 

     /* 
     if(strcmp(input, "NORTH") == 0 && rooms[currentRoom].around[NORTH] != NO_ROOM){ 
      currentRoom = rooms[currentRoom].around[NORTH]; 
     } 

     */ 

    } 

    return 0; 
} 

// points s to new string. clears stdin if user has input more than 
// MAX_USER_INPUT characters. 
void str_read(char *s){ 
    fgets(s, MAX_INPUT_LENGTH, stdin); // point s to user input from stdin 

    // clear extra characters from stdin, if the user has input more than 
    // MAX_INPUT_LENGTH characters. 
    if(!strchr(s, '\n')){ // newline does not exist 
     while(fgetc(stdin) != '\n'); // discard until newline 
    } 
} 

// converts string s to upper case 
void str_upper(char *s){ 
    int i; 
    char c; 

    for(i = 0; i < strlen(s); i++){ 
     s[i] = toupper(s[i]); 
    } 
} 

// fills the array r with info on each room. 
void room_setup(Room *r){ 

    strcpy(r[NO_ROOM].name, "Nothing there."); 
    strcpy(r[NO_ROOM].name, "Description"); 
    r[NO_ROOM].around[NORTH] = NO_ROOM; 
    r[NO_ROOM].around[EAST] = NO_ROOM; 
    r[NO_ROOM].around[SOUTH] = NO_ROOM; 
    r[NO_ROOM].around[WEST] = NO_ROOM; 

    strcpy(r[KITCHEN].name, "Kitchen"); 
    strcpy(r[KITCHEN].desc, "This is the kitchen."); 
    r[KITCHEN].around[NORTH] = NO_ROOM; 
    r[KITCHEN].around[EAST] = PANTRY; 
    r[KITCHEN].around[SOUTH] = NO_ROOM; 
    r[KITCHEN].around[WEST] = NO_ROOM; 

    strcpy(r[HALLWAY_1].name, "Hallway"); 
    strcpy(r[HALLWAY_1].desc, "A long hallway."); 
    r[HALLWAY_1].around[NORTH] = HALLWAY_2; 
    r[HALLWAY_1].around[EAST] = NO_ROOM; 
    r[HALLWAY_1].around[SOUTH] = KITCHEN; 
    r[HALLWAY_1].around[WEST] = TROLLS_DOMAIN; 

    strcpy(r[TROLLS_DOMAIN].name, "Troll's Domain"); 
    strcpy(r[TROLLS_DOMAIN].desc, "You see a Troll."); 
    r[TROLLS_DOMAIN].around[NORTH] = NO_ROOM; 
    r[TROLLS_DOMAIN].around[EAST] = HALLWAY_1; 
    r[TROLLS_DOMAIN].around[SOUTH] = EMPTY_ROOM_1; 
    r[TROLLS_DOMAIN].around[WEST] = NO_ROOM; 

    strcpy(r[EMPTY_ROOM_1].name, "Empty Room"); 
    strcpy(r[EMPTY_ROOM_1].desc , "An empty room. There was no reason to come here."); 
    r[EMPTY_ROOM_1].around[NORTH] = TROLLS_DOMAIN; 
    r[EMPTY_ROOM_1].around[EAST] = NO_ROOM; 
    r[EMPTY_ROOM_1].around[SOUTH] = NO_ROOM; 
    r[EMPTY_ROOM_1].around[WEST] = NO_ROOM; 

    strcpy(r[HALLWAY_2].name, "Hallway"); //hallway 2 
    strcpy(r[HALLWAY_2].desc, "A long hallway."); 
    r[HALLWAY_2].around[NORTH] = EXIT; 
    r[HALLWAY_2].around[EAST] = EMPTY_ROOM_2; 
    r[HALLWAY_2].around[SOUTH] = NO_ROOM; 
    r[HALLWAY_2].around[WEST] = NO_ROOM; 

    strcpy(r[EMPTY_ROOM_2].name, "Empty Room"); 
    strcpy(r[EMPTY_ROOM_2].desc , "An empty room."); 
    r[EMPTY_ROOM_2].around[NORTH] = NO_ROOM; 
    r[EMPTY_ROOM_2].around[EAST] = NO_ROOM; 
    r[EMPTY_ROOM_2].around[SOUTH] = NO_ROOM; 
    r[EMPTY_ROOM_2].around[WEST] = HALLWAY_2; 

    strcpy(r[EXIT].name, "Exit"); 
    strcpy(r[EXIT].desc, "You win lol"); 
    r[EXIT].around[NORTH] = NO_ROOM; 
    r[EXIT].around[EAST] = NO_ROOM; 
    r[EXIT].around[SOUTH] = HALLWAY_2; 
    r[EXIT].around[WEST] = NO_ROOM; 

} 

// fills the array i with info on each item. 
void item_setup(Item *i){ 
    strcpy(i[APPLE].name, "Apple"); 
    strcpy(i[APPLE].desc, "A bright red apple."); 

    strcpy(i[KEY].name, "Key"); 
    strcpy(i[NO_ITEM].name, "A silver key."); 

    strcpy(i[NO_ITEM].name, ""); 
    strcpy(i[NO_ITEM].desc, ""); 
} 

は、私は、whileループの中にcurrentRoom増分を作って、この出力を持っていた:

-- -- 


> 
-- -- 


> 
-- Hallway -- 
A long hallway. 

> 
-- Hallway -- 
A long hallway. 

> 
-- Troll's Domain -- 
You see a Troll. 

> 
-- Empty Room -- 
An empty room. There was no reason to come here. 

> 
-- Empty Room -- 
An empty room. 

> 
-- Exit -- 
You win lol 

NO_ROOMとKITCHENは、それが思わ構造体にコピーし、その情報を持っていませんでした。誰かが私が間違っている場所で働くのを助けることができますか?

+3

"strcpy()は一部の文字列では動作しませんが、他の文字列では動作しません" - それで、どの文字列でも動作しませんか?あるいは、それがどのように動作するかを理解したら、それは文字列に作用しているでしょうか?私はちょうどコードの壁面、[ask]が要求するような[mcve]、他の情報を見ています。 – Olaf

+1

コードをコンパイルするべきではありません。 'around'メンバは' en_dirs'型ですが、 'en_rooms'を保持します。 –

+0

@DavidSchwartzそれを指摘してくれてありがとう。しかし残念ながら、これは 'en_rooms'に変更されたときにも同じ問題があります。 – Sato

答えて

2

不十分なバッファサイズ - 1

// Room rooms[NO_ROOM]; 
Room rooms[NO_ROOM + 1]; 

以上Item items[NO_ITEM];

そう他の問題と同じ

typedef enum { 
    KITCHEN, 
    PANTRY, 
    ... 
    NO_ROOM, 

    // Insure ROOM_N is 1 greater than all the others. 
    // Putting it last usually does this. 
    ROOM_N 
} en_rooms; 

Room rooms[ROOM_N]; 

によってオフ。

+0

それは、感謝をソートしました!他にもたくさんの問題があるはい:/ – Sato

2

我々はこれを持っている:

typedef enum{ 
    APPLE,  // 0 
    KEY,  // 1 
    NO_ITEM // 2 
} en_items; 

わかりましたので、NO_ITEMは2です。そして、我々はこれを持っている:

Item items[NO_ITEM]; 

わかりましたので、itemsは二つのアイテムの配列です。

strcpy(i[APPLE].name, "Apple"); 
strcpy(i[APPLE].desc, "A bright red apple."); 

strcpy(i[KEY].name, "Key"); 
strcpy(i[NO_ITEM].name, "A silver key."); 

strcpy(i[NO_ITEM].name, ""); 
strcpy(i[NO_ITEM].desc, ""); 

私たちは2つのアイテムの配列を持っており、3つすべてを初期化しようとしています。おっとっと。

関連する問題