Search code examples
cncurses

Why the board is deleted by a loop?


I'm working on the backgammon game with ncurses library. Currently, I'm dealing with setting pawns on the board. My idea is to pass two c style strings to print_pawns(): first one telling by who is the field occupied and second one telling how many pawns are on the field. I divide print_pawns() to quarters because of the bar. Now, the first two loops (13<=i<=24) work properly, but the other two delete everything beside first three lines of the board. It looks like I'm overwriting some part of the board, but I can't find it.

#include <ncurses.h>
#define BOARD_WIDTH 53
#define BOARD_HEIGHT 19
#define START_X 9
#define START_Y 6
#define CENTER (BOARD_WIDTH/2+START_X)
#define WHITE 'W'
#define RED 'R'
#define EMPTY ' '
#define PAWNS 30
#define FIELDS 24

typedef struct board{
    char pawn_color[FIELDS];
    int pawn_count[FIELDS];
}Board;

typedef struct player{
    char name[50];
    char color;
    int score;
}Player;

void frame(){
    int i;
    mvprintw(BOARD_HEIGHT/2+START_Y, CENTER-1, "BAR");
    for(i=0;i<BOARD_HEIGHT-1;i++){
        mvprintw(i+START_Y, START_X,"|");
        mvprintw(i+START_Y,BOARD_WIDTH+START_X-1,"|");
        mvprintw(i+START_Y,CENTER-2,"|");
        mvprintw(i+START_Y,CENTER+2,"|");
    }
    for(i=0;i<BOARD_WIDTH-1;i++){
        mvprintw(START_Y,i+START_X,"-");
        mvprintw(BOARD_HEIGHT+START_Y-1,i+START_X,"-");
    }
    mvprintw(START_Y,START_X,"+");
    mvprintw(START_Y,BOARD_WIDTH+START_X-1,"+");
    mvprintw(BOARD_HEIGHT+START_Y-1, START_X,"+");
    mvprintw(BOARD_HEIGHT+START_Y-1,BOARD_WIDTH+START_X-1,"+");
}

void lower_numbers(){
    for(int i=12, j=START_X+2; i>6; i--,j+=4){
        mvprintw(START_Y+BOARD_HEIGHT, j,"%d",i);
    }
    for(int i=6, j=CENTER+4; i>0; i--,j+=4){
        mvprintw(START_Y+BOARD_HEIGHT, j,"%d",i);
    }
    
}
void upper_numbers(){
    for(int i=13, j=START_X+2; i<19; i++,j+=4){
        mvprintw(START_Y-1, j,"%d",i);
    }
    for(int i=19, j=CENTER+4; i<25; i++, j+=4){
        mvprintw(START_Y-1, j,"%d", i);
    }
}
void board(){
    initscr();
    mvprintw(0,CENTER-4,"BACKGAMMON");
    mvprintw(2,START_X,"Author: Oskar Wisniewski 198058");
    mvprintw(3,START_X,"Score:  Player1: 0 Player2: 0");
    upper_numbers();
    frame();
    lower_numbers();
    refresh();
}
void print_pawns(Board *board){
    for(int i=13, j=START_X+2; i<=3*FIELDS/4; i++, j+=4){
       for(int k=START_Y+1; k<START_Y+1+board->pawn_count[i-1]; k++){
                mvprintw(k,j,"%c",board->pawn_color[i-1]);
            } 
    } 
    for(int i=19, j=CENTER+4; i<=FIELDS; i++, j+=4){
        for(int k=START_Y+1; k<START_Y+1+board->pawn_count[i-1]; k++){
                mvprintw(k,j,"%c",board->pawn_color[i-1]);
            }
    }
    for(int i=1, j=BOARD_WIDTH+START_X-3; i<=FIELDS/4; i++, j-=4){
            for(int k=BOARD_HEIGHT+START_Y-2; k>BOARD_HEIGHT+START_Y-2+board->pawn_count[i-1]; k--){
                mvprintw(k,j,"%c",board->pawn_color[i-1]);
            }
    }
    for(int i=7, j=CENTER-4; i<=FIELDS/2; i++, j-=4){
            for(int k=BOARD_HEIGHT+START_Y-2; k>BOARD_HEIGHT+START_Y-2+board->pawn_count[i-1]; k--){
                mvprintw(k,j,"%c",board->pawn_color[i-1]);
            }
    } 
    
}

int main(){
    board();
    Board board={
        .pawn_color={WHITE, EMPTY, EMPTY, EMPTY, EMPTY, RED, EMPTY, RED, EMPTY, EMPTY, EMPTY, WHITE, RED, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, WHITE, EMPTY, EMPTY,EMPTY, EMPTY, RED},
        .pawn_count={2,0,0,0,0,5,0,3,0,0,0,5,5,0,0,0,3,0,5,0,0,0,0,2}
    };
    print_pawns(&board);
    refresh();
    return 0;
}

I tried basic debugging - printing out the values of k and j, but the loops do not display it. I also rechecked values in loops several times and couldn't find the problem. I thought that maybe the order of printing out the loops is the problem, but reversing the iteration and changing order hasn't changed anything.

EDIT I moved this function and struct instance to board(). Now it displays the whole board, but doesn't print lower part at all. When I try to move the output of it, there are whitespaces instead of '-', so it prints out empty columns.


Solution

  • You had two signs wrong. In the last two for loops in print_pawn, you're supposed to subtract board->pawn_count. Here's the fixed code for completion:

    #include <ncurses.h>
    #include <unistd.h>
    #define BOARD_WIDTH 53
    #define BOARD_HEIGHT 19
    #define START_X 9
    #define START_Y 6
    #define CENTER (BOARD_WIDTH/2+START_X)
    #define WHITE 'W'
    #define RED 'R'
    #define EMPTY ' '
    #define PAWNS 30
    #define FIELDS 24
    
    typedef struct board{
        char pawn_color[FIELDS];
        int pawn_count[FIELDS];
    }Board;
    
    typedef struct player{
        char name[50];
        char color;
        int score;
    }Player;
    
    void frame(){
        int i;
        mvprintw(BOARD_HEIGHT/2+START_Y, CENTER-1, "BAR");
        for(i=0;i<BOARD_HEIGHT-1;i++){
            mvprintw(i+START_Y, START_X,"|");
            mvprintw(i+START_Y,BOARD_WIDTH+START_X-1,"|");
            mvprintw(i+START_Y,CENTER-2,"|");
            mvprintw(i+START_Y,CENTER+2,"|");
        }
        for(i=0;i<BOARD_WIDTH-1;i++){
            mvprintw(START_Y,i+START_X,"-");
            mvprintw(BOARD_HEIGHT+START_Y-1,i+START_X,"-");
        }
        mvprintw(START_Y,START_X,"+");
        mvprintw(START_Y,BOARD_WIDTH+START_X-1,"+");
        mvprintw(BOARD_HEIGHT+START_Y-1, START_X,"+");
        mvprintw(BOARD_HEIGHT+START_Y-1,BOARD_WIDTH+START_X-1,"+");
    }
    
    void lower_numbers(){
        for(int i=12, j=START_X+2; i>6; i--,j+=4){
            mvprintw(START_Y+BOARD_HEIGHT, j,"%d",i);
        }
        for(int i=6, j=CENTER+4; i>0; i--,j+=4){
            mvprintw(START_Y+BOARD_HEIGHT, j,"%d",i);
        }
        
    }
    void upper_numbers(){
        for(int i=13, j=START_X+2; i<19; i++,j+=4){
            mvprintw(START_Y-1, j,"%d",i);
        }
        for(int i=19, j=CENTER+4; i<25; i++, j+=4){
            mvprintw(START_Y-1, j,"%d", i);
        }
    }
    void board(){
        initscr();
        mvprintw(0,CENTER-4,"BACKGAMMON");
        mvprintw(2,START_X,"Author: Oskar Wisniewski 198058");
        mvprintw(3,START_X,"Score:  Player1: 0 Player2: 0");
        upper_numbers();
        frame();
        lower_numbers();
        refresh();
    }
    void print_pawns(Board *board){
        for(int i=13, j=START_X+2; i<=3*FIELDS/4; i++, j+=4){
           for(int k=START_Y+1; k<START_Y+1+board->pawn_count[i-1]; k++){
                    mvprintw(k,j,"%c",board->pawn_color[i-1]);
                } 
        } 
        for(int i=19, j=CENTER+4; i<=FIELDS; i++, j+=4){
            for(int k=START_Y+1; k<START_Y+1+board->pawn_count[i-1]; k++){
                    mvprintw(k,j,"%c",board->pawn_color[i-1]);
                }
        }
        for(int i=1, j=BOARD_WIDTH+START_X-3; i<=FIELDS/4; i++, j-=4){
                for(int k=BOARD_HEIGHT+START_Y-2; k>BOARD_HEIGHT+START_Y-2-board->pawn_count[i-1]; k--){
                    mvprintw(k,j,"%c",board->pawn_color[i-1]);
                }
        }
        for(int i=7, j=CENTER-4; i<=FIELDS/2; i++, j-=4){
                for(int k=BOARD_HEIGHT+START_Y-2; k>BOARD_HEIGHT+START_Y-2-board->pawn_count[i-1]; k--){
                    mvprintw(k,j,"%c",board->pawn_color[i-1]);
                }
        } 
    }
    
    int main(){
        board();
        Board board={
            .pawn_color={WHITE, EMPTY, EMPTY, EMPTY, EMPTY, RED, EMPTY, RED, EMPTY, EMPTY, EMPTY, WHITE, RED, EMPTY, EMPTY, EMPTY, WHITE, EMPTY, WHITE, EMPTY, EMPTY,EMPTY, EMPTY, RED},
            .pawn_count={2,0,0,0,0,5,0,3,0,0,0,5,5,0,0,0,3,0,5,0,0,0,0,2}
        };
        print_pawns(&board);
        refresh();
        sleep(1);
        return 0;
    }
    

    I've also added a sleep at the end so we can see the board fully.