Question

I'm making a Roguelike game in C, and I can't get my character to move in the way I want it to. I made a 2D char array with the character on it at point (x, y), drew the array, and changed the x and y values and redrew the array upon input of a direction in which to go (kind of like Zork but with graphics). But this isn't working out how I planned. The code will explain more than I can:

/* game.h (header file for globals) */

#define GAME_H

char character = '@';
//char monster = '&';

int x = 2;
int y = 2;

/* my beginning floor
(will not be implemented, just for testing movement) */
char floor[10][6] = { /* 219 = filled block, 32 = space */
        219, 219, 219, 219, 219, 219, 219, 219, 219, '\n',
        219,  32,  32,  32,  32,  32,  32,  32, 219, '\n',
        219,  32,  32,  32,  32,  32,  32,  32, 219, '\n',
        219,  32,  32,  32,  32,  32,  32,  32, 219, '\n',
        219, 219, 219, 219, 219, 219, 219, 219, 219, '\n'};



/* game.c (main file) */
#include <stdio.h>
#include "game.h"

int main(void){
        system("cls");
        floor[x][y] = character;
        printf("%s", floor);
        char move;

        redo:

        printf("\nTravel which way?\n");
        printf("a = left\ns = down\nd = up\nf = right\n\n>");
        scanf("%s", &move);

        /*
        array oftentimes gets desroyed because the newlines are
        being overwritten by the assignments.
        the if statements should have prevented this.
        why didn't they?
        */

        if (move == 'a'){ /* LEFT */
                if (x < 1){
                        x = 1;}
                x--;
                floor[x][y] = character;
                floor[x+1][y] = ' ';
                system("cls");
                printf("%s", floor);
                goto redo;

        } else if (move == 's'){ /* DOWN (works, but goes right. Sometimes clones itself) */
                if (y > 3){
                        y = 3;} /*bounds may be wrong*/
                y++;
                floor[x][y] = character;
                floor[x][y-1] = ' ';
                system("cls");
                printf("%s", floor);
                goto redo;

        } else if (move == 'd'){ /* UP */
                if (y < 1){
                        y = 1;}
                y--;
                floor[x][y] = character;
                floor[x][y+1] = ' ';
                system("cls");
                printf("%s", floor);
                goto redo;

        } else if (move == 'f'){ /* RIGHT */
                if (x > 7){
                        x = 7;}
                x++;
                floor[x][y] = character;
                floor[x-1][y] = ' ';
                system("cls");
                printf("%s", floor);
                goto redo;}
        else {
                goto done;
        }

        done:
        return 0;
}

Can anyone tell me what I'm doing wrong?

Note: This map setup is simply a draft. I'm going to be doing it completely differently once the mechanics are done, but I'll be planning to move the character along the array in much the same way, so I would rather have help with this specific setup rather than advice on how to do it better/differently. However, relevant answers and source code that show better implementation would still be useful and appreciated, since I myself may be doing it totally wrong in the first place, as this is my first Roguelike game.

Was it helpful?

Solution 2

Given this code:

char character = '@'; 
int x = 2;
int y = 2;

char floor[10][6] = { /* 219 = filled block, 32 = space */
        219, 219, 219, 219, 219, 219, 219, 219, 219, '\n',
        219,  32,  32,  32,  32,  32,  32,  32, 219, '\n',
        219,  32,  32,  32,  32,  32,  32,  32, 219, '\n',
        219,  32,  32,  32,  32,  32,  32,  32, 219, '\n',
        219, 219, 219, 219, 219, 219, 219, 219, 219, '\n'};


/* game.c (main file) */
#include <stdio.h>
#include "game.h"

int main(void){
        system("cls");
        floor[x][y] = character;
        printf("%s", floor); /* print the map and character */

There are several problems. First, your array is not null terminated; it is not safe to print it like that. There are only 5 * 10 = 50 characters in that array, so it is null terminated after all. I didn't notice the miscounting until later. If you had the sixth line of data, you'd have to use:

       printf("%.*s", (int)sizeof(floor), floor);

The other problem is that you've misunderstood the array; it is 10 rows of 6 characters, not 6 rows of 10 characters.

char floor[10][6] =
{ /* 219 = filled block, 32 = space */
        { 219,  219, 219,  219, 219,  219, },
        { 219,  219, 219, '\n', 219,   32, },
        {  32,   32,  32,   32,  32,   32, },
        { 219, '\n', 219,   32,  32,   32, },
        {  32,   32,  32,   32, 219, '\n', },
        { 219,   32,  32,   32,  32,   32, },
        {  32,   32, 219, '\n', 219,  219, },
        { 219,  219, 219,  219, 219,  219, },
        { 219, '\n' },
};

and, in fact, your data is short a few characters too. However, it will appear OK because of the way you print it, but if you did fully bracketed initialization, you'd find that you had problems if you put the brackets around each line in your original layout.

I'd be tempted to use names instead of numbers for the characters in the initializatio:

enum { WALL = 219, OPEN = 32, ENDL = '\n' };

These are uniformly 4 letters each, making for a more systematic layout in the initializer.

Note that when you place the character at 2,2, you are modifying the array like this:

char floor[10][6] =
{ /* 219 = filled block, 32 = space */
        { 219,  219, 219,  219, 219,  219, },
        { 219,  219, 219, '\n', 219,   32, },
        {  32,   32, '@',   32,  32,   32, },  // Change here!
        { 219, '\n', 219,   32,  32,   32, },
        {  32,   32,  32,   32, 219, '\n', },
        { 219,   32,  32,   32,  32,   32, },
        {  32,   32, 219, '\n', 219,  219, },
        { 219,  219, 219,  219, 219,  219, },
        { 219, '\n' },
};

OTHER TIPS

Your declaration of floor looks a bit weird to me try doing something like this:

//c arrays are generally array[rows][columns]
int rows = 6, cols = 10;
char floor[rows][cols] = {
    {219, 219, 219, 219, 219, 219, 219, 219, 219, '\n'},
    {219,  32,  32,  32,  32,  32,  32,  32, 219, '\n'},
    {219,  32,  32,  32,  32,  32,  32,  32, 219, '\n'},
    {219,  32,  32,  32,  32,  32,  32,  32, 219, '\n'},
    {219, 219, 219, 219, 219, 219, 219, 219, 219, '\n'}};

Example here http://ideone.com/O7UG8g . I changed 219->35 in that example because I don't think printing extended ascii works on that site.

Also I think the bound checks should be something like:

//move left (go one column left)
//if current position is array[curRow][curCol]
//assuming array[0][0] is top left of map
//check if left is a wall
if((curCol - 1) == charForAWall)
   return;
else
   curCol--;

Right would be +1 column, up -1 row, and down +1 row.

There's nothing wrong with the code that handles the moves, it looks like the problem is to do with the way you allocate your array. For starters, you only have 5 columns, not 6. I grouped the elements like this:

char floor[10][5] = {
    {219,219,219,219,219},
    {219,32,32,32,219},
    {219,32,32,32,219},
    {219,32,32,32,219},
    {219,32,32,32,219},
    {219,32,32,32,219},
    {219,32,32,32,219},
    {219,32,32,32,219},
    {219,219,219,219,219},
    {'\n','\n','\n','\n','\n'}
};

And then I wrote another function to print the array (to replace the printf statement, which will no longer work like this) like so:

int printArray() {
    int i, j;

    for(i=0; i<5; i++) {
        for(j=0; j<10; j++) {
            printf("%c", floor[j][i]);
        }
    }
}

The rest of the code then works fine.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top