Reputation: 21
I am using ncurses to make a little puzzle game that allows user to hit any arrow key to move a boxes containing each a number, all inside one big box, to arrange the numbers in ascending order. It is a 4x4 box and one sub-box is blank, so that other sub-boxes can move.
Now I have a problem in accessing an array of WINDOW (not pointers) I made in a function so that I can destroy all sub_boxes, change array of numbers, and recreate sub-boxes according to the array.
#include <stdio.h>
#include <ncurses.h>
#include <math.h>
#include <string.h>
#define HEIGHT 16
#define WIDTH 32
#define STARTY ((LINES - HEIGHT) / 2)
#define STARTX ((COLS - WIDTH) / 2)
#define QEXIT 81
#define qEXIT 113
WINDOW *create_win(int height, int width, int starty, int startx){
WINDOW *local_win;
local_win = newwin(height, width, starty, startx);
box(local_win, 0, 0);
wrefresh(local_win);
return local_win;
};
void destroy_win(WINDOW *local_win){
wborder(local_win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wrefresh(local_win);
delwin(local_win);
};
void draw_list(WINDOW *local_win, WINDOW *num_wins, int arr[][4], int length){
for(int i=0; i < length; i++){
for(int j=0; j < length; j++){
refresh();
WINDOW *sub_win;
int height = HEIGHT / length, width = WIDTH / length, starty = STARTY + i*height, startx = STARTX + j*width;
sub_win = create_win(height, width, starty, startx);
//wprintw(stdscr, "%d |", sizeof(*sub_win));
*(num_wins + i*4+j) = *sub_win;
//wprintw(stdscr, "%d - ", i*4+j);
//overwrite(sub_win, (num_wins + i*4+j));
//memcpy(num_wins + i*4+j, sub_win, sizeof(*sub_win));
int digity = height / 2, digitx = width / 2 - 1;
if(arr[i][j])
mvwprintw(sub_win, digity, digitx, "%d ", arr[i][j]);
else
mvwprintw(sub_win, digity, digitx, "X ");
wrefresh(sub_win);
};
};
};
void destroy_list(WINDOW *num_wins){
int length = 16;
for(int i=0; i < length; i++){
wprintw(stdscr, "%d ", i);
wborder((num_wins + i), ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wrefresh((num_wins + i));
delwin((num_wins + i));
};
};
void play(){
int arr[4][4] = {1,4,15,7,8,10,2,11,14,3,6,13,12,9,5,0};
int length = 4;
WINDOW *win;
int starty, startx;
//Placement
starty = STARTY;
startx = STARTX;
printw("Press Q or q to exit\n");
//printw("%d - %d\n%d - %d\n", LINES, COLS, HEIGHT, WIDTH);
printw("\n");
refresh();
// Create original window (Maybe it is useless)
win = create_win(HEIGHT, WIDTH, starty, startx);
// Create sub windows for numbers
WINDOW sub_wins[16];
draw_list(win, sub_wins, arr, length);
refresh();
getch();
destroy_win(&sub_wins[0]);
refresh();
//for(int i=0; i < 16; i++){
// wprintw(stdscr, "%d -", sizeof(sub_wins[i]));
//destroy_win(sub_wins + i);
//};
wrefresh(win);
int ch = getch();
while(ch != QEXIT && ch != qEXIT){
switch(ch){
case KEY_UP:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, --starty, startx);
//destroy_list(sub_wins);
break;
case KEY_RIGHT:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, starty, ++startx);
break;
case KEY_DOWN:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, ++starty, startx);
break;
case KEY_LEFT:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, starty, --startx);
break;
};
ch = getch();
};
};
int main(void){
//printList(arr, length);
printf("\n");
// Init ncurses
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
// Game mechanics
play();
endwin();
return 0;
};
I kind of threw multiple questions in my code and some parts that aren't entirely related to my main problem. Sorry. But I would like to primarily solve the problem regarding destroying sub-windows.
Thank you in advance.
Upvotes: 1
Views: 180
Reputation: 182753
You can't split a window into two windows. If you copy the window structure, you need to use one and only one instance to refer to the window.
*(num_wins + i*4+j) = *sub_win;
Here you copy a window. The window is now in two places, sub_win
and in the num_wins
array. You don't have two windows, you only have one. So you need to pick one of these.
if(arr[i][j])
mvwprintw(sub_win, digity, digitx, "%d ", arr[i][j]);
else
mvwprintw(sub_win, digity, digitx, "X ");
wrefresh(sub_win);
Okay, so you modify sub_win
. That means the copy you made is not the window. Remember, there's one and only one window. Since you modified sub_win
, it is the window. So what was the point of making a copy of the window before you modified it, that's not the window any more.
void destroy_list(WINDOW *num_wins){
int length = 16;
for(int i=0; i < length; i++){
wprintw(stdscr, "%d ", i);
wborder((num_wins + i), ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wrefresh((num_wins + i));
delwin((num_wins + i));
};
};
What are you doing here? You're manipulating a copy of what the window was before you modified it. But you modified it -- so that window no longer exists. This code makes no sense.
A window is one, and only one, thing. If you make a copy of the WINDOW
structure, you can use either copy to represent the window. But you can't use both -- there's only one window. Your code uses both. That is not valid.
In summary: You make a copy of the window, then you modify the window (NOT THE COPY). That means the copy is a copy of what the window was before you modified it, something that no longer exists because you modified the thing you copied. So attempting to access the copy is an error, because it's a copy of something that no longer exists.
It's kind of like doing this:
After you make a copy, you can treat either side as the original since they're identical at that point. But you can't mess with the other too or you will get awfully confused.
Upvotes: 2