CURSES Library Python Library for Screen Painting and


CURSES Library Python Library for Screen Painting and Keyboard Handling - 2

Random Number Generator import random for i in range(10): print( random. randint(1, 6) ) 3

Pause in Program Execution import random import time for i in range(10): print( random. randint(1, 6) ) time. sleep(2) 4

Screen Handling (run curses_3. py) 5

Definition of curses on Wikipedia curses is a terminal control library for Unixlike systems, enabling the construction of text user interface (TUI) applications. p The name is a pun on the term “cursor optimization”. It is a library of functions that manage an application's display on character-cell terminals (e. g. , VT 100) p 6

Basic Functions p move(y, x) n Move cursor to (y, x) in screen yth row, xth column p the upper-left corner is (0, 0) p p addstr(str) n p Add a string to screen by calling addch() refresh() n Update screen 7

Initialize and Terminate Curses p initscr() n p getmaxyx() n p Get the height and width of a window endwin() n n n p Initialize curses End curses. This function should be called when your program is finished. It will release the space allocated to screen handling in your program. Remember to import curses at the beginning of 8 your program.

curses_2. py import time import curses stdscr = curses. initscr() y, x = stdscr. getmaxyx() msg = "This window has {0} rows and {1} columns. " stdscr. addstr(10, 20, msg. format(y, x) ) x = 10 for y in range(15, 0, -1): stdscr. move(y, x) stdscr. addstr("Hello") stdscr. refresh() time. sleep(0. 5) 9 curses. endwin()

curses_3. py import random import time import curses stdscr = curses. initscr() a = [0] * 6 for i in range(6): stdscr. addstr( "{0} ( )n". format(i+1) ) for i in range(10): j = random. randint(0, 5) stdscr. move(10, i*2) stdscr. addstr( "{0: 2}". format(j+1) ) a[j] = a[j] + 1 stdscr. addstr(j, 3, "{0: 2}". format( a[j] ) ) stdscr. refresh() time. sleep(2) curses. endwin() 10

Homework: 8 Queens p Imagine there are 8 queens attending a race. On your computer screen each queen is represented by a character ‘Q’. On each row there is one queen. n p Use a random number generator to determine which queen will move forward. n p If you think a single character is monotonous, you may modify this program to handle 8 horses ~/-^ You may use the sleep() function to slow down the program. Suppose the length of each lane is 50. The first queen who arrives at the destination wins the race. 12

Colors p To start using color, you should call the function start_color() soon after calling initscr(). p Colors are always used in pairs. n n A color-pair consists of a foreground color and a background color. Initializes a color-pair with the routine init_pair(n, foreground, background). After it has been initialized, curses. color_pair(n) is used to represent 13 the color attribute.

Pre-defined Colors COLOR_BLACK p COLOR_RED p COLOR_GREEN p COLOR_YELLOW p COLOR_BLUE p COLOR_MAGENTA p COLOR_CYAN p COLOR_WHITE p = = = = 0 1 2 3 4 5 6 7 14

curses_7. py # Color import curses stdscr = curses. initscr() curses. start_color() curses. init_pair(1, curses. COLOR_RED, curses. COLOR_WHITE) curses. init_pair(2, curses. COLOR_WHITE, curses. COLOR_BLUE) stdscr. addstr( 9, 10, "Good afternoon") stdscr. addstr(10, "Good afternoon", curses. color_pair(1)) stdscr. addstr(11, 10, "Good afternoon", curses. color_pair(2)) stdscr. refresh() curses. endwin() The 0 color pair is wired to white on black and cannot be changed. 15

Getting Characters from the Terminal p getkey() n p Get a character from the terminal noecho() n Turn off automatic echoing of keys to the screen 20

curses_12. cpp import curses stdscr = curses. initscr() curses. noecho() x, y = 10, 10 s = 'Q' c = '' while c != 'q': if c == 'h': x = x - 1 elif c == 'l': x = x + 1 elif c == 'j': y = y + 1 elif c == 'k': y = y - 1 stdscr. move(y, x) stdscr. addstr( s ) c = stdscr. getkey() curses. echo() curses. endwin() Try to comment out noecho() and see the difference. # Left # Right # Down # Up 21

curs_set() alters the appearance of the text cursor. p curs_set(visibility); p n n n A value of 0 for visibility makes the cursor disappear; a value of 1 makes the cursor appear "normal" (usually an underline on some terminals) 2 makes the cursor "highly visible" (usually a block). 22

curses_12 a. py import curses stdscr = curses. initscr() curses. noecho() curses. curs_set(0) x, y = 10, 10 s = 'Q' c = '' while c != 'q': if c == 'h': x = x - 1 elif c == 'l': x = x + 1 elif c == 'j': y = y + 1 elif c == 'k': y = y - 1 stdscr. move(y, x) stdscr. addstr( s ) c = stdscr. getkey() curses. curs_set(2) curses. echo() curses. endwin() # Left # Right # Down # Up 23

Exercise: Changing Positions and Colors # Erase the previous position # before move to a new position import curses stdscr = curses. initscr() curses. noecho() curses. curs_set(0) x = y = 10 s = 'Q' empty_s = ' ' c = '' while c != 'q': stdscr. move(y, x) stdscr. addstr(empty_s) if c == 'h': # x = x - 1 elif c == 'l': # x = x + 1 elif c == 'j': # y = y + 1 elif c == 'k': # y = y - 1 stdscr. move(y, x) stdscr. addstr( s ) c = stdscr. getkey() Left Right Down Up curses. curs_set(2) curses. echo() curses. endwin() 24

Function Keys p Call keypad() to enable the handling of Function keys and arrow keys. n p stdscr. keypad(True) getch() returns an integer corresponding to the key pressed. n n If it is a normal character, the integer value will be equivalent to the ASCII code of the character. Otherwise it returns a number which may be larger than 256. p p For example if the user presses the LEFT arrow key, the integer returned is 260. getkey() returns a string corresponding to the key pressed. n KEY_LEFT, KEY_RIGHT, KEY_UP, KEY_DOWN, KEY_PPAGE, KEY_NPAGE, KEY_IC, KEY_DC 25

Exercise: Arrow Keys Modify curses_12. py so that users can use arrow keys and HJKL to control the movement of ‘Q’. p Moreover, try to allow users to use both uppercase ‘H’ and lowercase ‘h’ to do the same movement. p Users can also change the color of ‘Q’ by pressing ‘ 0’…’ 7’. p 26

HW: Tetris 27

int timeout(int delay) p The timeout() function affects the behaviour of getch() when reading a character from stdscr. n n If delay is a positive number, then getch() will wait for that many milliseconds before returning If no character was available, then ERR (-1) will be returned. 28

pdcurses_6. cpp #include <curses. h> switch(c) { case 'h': x--; break; case 'l': x++; break; } move(y, old_x); addch(' '); int main() { int x=10, old_x; int c; initscr(); noecho(); curs_set(0); // hide the cursor timeout(500); // getch() will only wait 0. 5 second for (int y=1; y<15; y++) { move(y, x); addch('Q'); old_x = x; c = getch(); } refresh(); endwin(); return 0; } 29

HW: Tetris Rotation Replay Falling Down 30

Rotate with respect to a fixed point (x+1, (x+2, y-1) (x, y) (x+1, y) x y 31

Relative Coordinates (1, -1) (0, 0) (2, -1) (1, 0) x y 32

Rotate 90 Degrees (-1, -2) (-1, -1) (0, 0) x y 33

Rotate 180 Degrees (-1, 0) (-2, 1) (0, 0) (-1, 1) x y 34

Rotate 270 Degrees (0, 0) (0, 1) (1, 2) x y 35

Observe the x and y ( y, - x) (- x, - y) (0, 0) x ( x, y) (- y, x) y 36

switch(rotate) p case 0: n n n p x = x 0 + x; y = y 0 + y; break; case 2: n n n p x = x 0 - x; y = y 0 - y; break; case 1: n n n p x = x 0 + y; y = y 0 - x; break; case 3: n n n x = x 0 - y; y = y 0 + x; break; 37

Seven Shapes 38
![Represent these objects with struct Shape { Cell c[4]; }; struct Cell { int Represent these objects with struct Shape { Cell c[4]; }; struct Cell { int](http://slidetodoc.com/presentation_image_h2/5d268b23fa76cc6fcb5638f39690e1b8/image-34.jpg)
Represent these objects with struct Shape { Cell c[4]; }; struct Cell { int dx; int dy; } 39

Choose a reference point (0, -1) (-1, 0) (1, -1) (0, 0) 40
![Shape s[7]; void init_shape() { int i, j, x, y; FILE* fp; fp = Shape s[7]; void init_shape() { int i, j, x, y; FILE* fp; fp =](http://slidetodoc.com/presentation_image_h2/5d268b23fa76cc6fcb5638f39690e1b8/image-36.jpg)
Shape s[7]; void init_shape() { int i, j, x, y; FILE* fp; fp = fopen("X: \WWW\Course\CS 101\shape_xy. txt", "r"); for (i=0; i<7; i++) { 0 0 0 1 -1 0 -1 1 for (j=0; j<4; j++) 0 0 1 0 2 0 -1 0 { 0 0 0 1 -1 0 -1 -1 fscanf(fp, "%d %d", &y, &x); 0 0 0 1 0 -1 -1 0 s[i]. c[j]. dx = x; 0 0 0 1 0 2 -1 0 s[i]. c[j]. dy = y; 0 0 0 -1 -1 0 -1 1 } 0 0 0 -1 0 -2 -1 0 } fclose(fp); // Initialize the bottom line for (i=0; i<12; i++) occupy[11][i] = true; } 41

plot_shape(shape_id, y 0, x 0, rotate, character) for (j=0; j<4; j++) { x = x 0 + s[id]. c[j]. dx; y = y 0 + s[id]. c[j]. dy; move(y, x); addch(character); } 42

Consider Rotations 43

test_rotate() KEY_LEFT p KEY_RIGHT p KEY_UP p p tetris-1. cpp 44

history. txt p shape, y, x, r 1 1 1 6 6 6 6 6 110 210 320 430 531 10 3 1 120 220 330 440 551 662 773 880 10 8 0 y=1 implies a new object 45

replay() fopen() while ( fscanf( ) != EOF ) { if not a new object erase the old position plot at the new position } fclose() 46

Falling down Q: When should an object stop falling down? p A: When there get supported by some cells beneath it. p 47
![bool occupy[][] p We need an array to allow the program checking which cells bool occupy[][] p We need an array to allow the program checking which cells](http://slidetodoc.com/presentation_image_h2/5d268b23fa76cc6fcb5638f39690e1b8/image-43.jpg)
bool occupy[][] p We need an array to allow the program checking which cells (at the bottom) are occupied by previous objects. while ( ! beneath( ) ) { erase y = y + 1 plot } update_occupy(); 48

Define Your Own Color p start_color() n n initializes eight basic colors (black, red, green, yellow, blue, magenta, cyan, and white) Two global variables: COLORS: maximum number of colors p COLOR_PAIRS: maximum number of color-pairs p p bool has_colors(void); n if the terminal can manipulate colors. NCURSES Programming HOWTO p Public Domain Curses Library and its User's Guide p 49

has_colors() #include <curses. h> int main() { initscr(); start_color(); keypad(stdscr, TRUE); noecho(); move(0, 40); printw("There are %d colors and %d pairs", COLORS, COLOR_PAIRS); move(1, 0); printw("This terminal has %scolor; ", has_colors()? "": "no "); printw("can %schange colors. ", can_change_color()? "": "not "); getch(); endwin(); 50 return 0; }

pdcurses_2. cpp #include <curses. h> int main() { initscr(); start_color(); init_pair( 1, COLOR_WHITE, COLOR_RED ); attron( COLOR_PAIR(1) ); printw("Background red"); attroff( COLOR_PAIR(1) ); refresh(); getch(); endwin(); return 0; } 51

Pre-defined Colors in curses. h # define COLOR_BLUE 1 # define COLOR_GREEN 2 # define COLOR_RED 4 #define COLOR_CYAN (COLOR_BLUE | COLOR_GREEN) #define COLOR_MAGENTA (COLOR_RED | COLOR_BLUE) #define COLOR_YELLOW (COLOR_RED | COLOR_GREEN) #define COLOR_WHITE 7 52

color_content() p int color_content(short color, short *red, short *green, short *blue); n p int pair_content(short pair, short *fg, short *bg); n p Find the intensity of the red, green, and blue (RGB) components in a color. Find out how a given color-pair is currently defined. Note that the pointer is passed to the function so that the value of the arguments can be modified. 53

Global Variable: COLORS #include <curses. h> int main() { initscr(); start_color(); short color, red, green, blue; for (color=0; color < COLORS; color++) { color_content(color, &red, &green, &blue); printw("%d -t%dt%dn", color, red, green, blue); } refresh(); getch(); endwin(); return 0; } 54

pair_content() #include <curses. h> int main() { initscr(); start_color(); short pair; short fg, bg; for (pair=0; pair < 16; pair++) { pair_content(pair, &fg, &bg); printw("%d -t%dn", pair, fg, bg); } refresh(); getch(); endwin(); return 0; } 55
![Highlighted Color #include <curses. h> int main() { char* name[] = { "Black", "Blue", Highlighted Color #include <curses. h> int main() { char* name[] = { "Black", "Blue",](http://slidetodoc.com/presentation_image_h2/5d268b23fa76cc6fcb5638f39690e1b8/image-51.jpg)
Highlighted Color #include <curses. h> int main() { char* name[] = { "Black", "Blue", "Green", "Cyan", "Red", "Magenta", "Yellow", "White", "Grey", "BLUE", "GREEN", "CYAN", "RED", "MAGENTA", "YELLOW", "WHITE" }; initscr(); start_color(); short c; for (c=0; c < 8; c++) { init_pair( c, COLOR_WHITE, c ); attron( COLOR_PAIR(c) ); move(c, 10); printw("%10 s", name[c]); attroff( COLOR_PAIR(c) ); } for (c=8; c < 16; c++) { init_pair( c, COLOR_WHITE, c ); attron( COLOR_PAIR(c) ); move(c-8, 20); printw("%10 s", name[c]); attroff( COLOR_PAIR(c) ); } refresh(); getch(); endwin(); return 0; } 56

init_color() p int init_color(short color, short red, short green, short blue); n n n p Change the RGB values for the colors defined by curses initially. The RGB content is scaled from 0 to 1000. Initially COLOR_RED is defined with content 1000(r), 0(g), 0(b). However, the color did not change, after I run the init_color(). Maybe you can try. n Perhaps the dumb terminal only supports 16 colors. 57

Executable File (. EXE) Under your ProjectdemoDebug directory, there is a “demo. exe”. p After setting “PATH=%PATH%; L: PDCurses”, you can run the file “demo” directly (just like a command as “DIR”, “VOL”, “DATE”) from the Command Window. p 58

NCURSES Library - Functions for Screen Handling Visual C++ 2010 (P. 3 -P. 61) - G++ on Free. BSD (P. 62) 59

Ncurses Library on Free. BSD p New Cursor Control library p man ncurses p Ncurses Library Tutorial n http: //www. writeka. com/ed/ncurses_library. html 60

Moving a Star Towards the Left Suppose we want to have a program, which display a star on the screen. p With a fixed interval, the star will move towards the left, step by step. p n ncurses-1. exe 61

#include <iostream> #include <unistd. h> using std: : cout; using std: : endl; int main() { int i; int j; for (i=20; i>=0; i--) { for (j=0; j<i; j++) cout << ' '; cout << '*' ; for (j=0; j<23; j++) cout << endl; usleep(300000); // Pause for 0. 3 sec } return 0; } ncurse 1. cpp What if the window is shrunk to fewer rows? 62

If the moving pattern is complex … p ncurses-2. exe p Your program will become very complex, if you try to implement as done in the previous program. p It would be great if we can move the cursor to wherever we want. 63

Definition of curses on Wikipedia curses is a terminal control library for Unixlike systems, enabling the construction of text user interface (TUI) applications. p The name is a pun on the term “cursor optimization”. It is a library of functions that manage an application's display on character-cell terminals (e. g. , VT 100) p 64

Basic Functions p move(y, x) n n p addch(ch) n n p Add a string to screen by calling addch() printw(fmt, arg 1, arg 2, …) n p Add a character to screen. X coordinate will be incremented addstr(str) n p Move cursor to (y, x) in screen The coordinates are zero-based. Formatted print to screen by calling addstr() refresh() n Update screen 65

Initialize and Terminate Curses p initscr() n p endwin() n n n p Initialize curses End curses. This function should be called when your program is finished. It will release the space allocated to screen handling in your program. Remember to #include <curses. h> at the beginning of your program. 66

#include <curses. h> ncurses 3. cpp int main() { initscr(); addch('='); addstr("Hellon"); printw("%dt%dn", LINES, COLS); move(3, 3); addch('A'); move(2, 2); addch('B'); refresh(); endwin(); } p Compile your program and link with the curses library n g++ ncurses-3. cpp -lcurses -o ncurses-3. exe 67

Exercise: A Moving Star p Use the “curses” library to write a program, which shows a star moving towards the left 68

Homework: Move Around p Since you learned how to move a star, extend the exercise to move the star around a rectangle. n p You may need 4 loops to do that. Run “ncurses-2. exe” again to show students what they must achieve. 69

Getting Input from the Terminal p getch() n p getstr(str) n p Get a character from the terminal Get a string from the terminal scanw(fmt, arg 1, arg 2, …) n Formatted input from the terminal like scanf(). 70
![ncurses-4. cpp: getstr() vs. scanw() #include <curses. h> int main() { char text[10]; int ncurses-4. cpp: getstr() vs. scanw() #include <curses. h> int main() { char text[10]; int](http://slidetodoc.com/presentation_image_h2/5d268b23fa76cc6fcb5638f39690e1b8/image-66.jpg)
ncurses-4. cpp: getstr() vs. scanw() #include <curses. h> int main() { char text[10]; int i, j, c; initscr(); getstr(text); // input the string "1, 2" addstr(text); addch('n'); scanw("%d, %d", &i, &j); printw("%dt%dn", i, j); // input the string "1, 2" again c = getch(); endwin(); return 0; } 71

#include <curses. h> int main() { int i; char c; initscr(); for (i=0; i<5; i++) { c = getch(); switch (c) { case 'h': addstr("Left"); break; case 'l': addstr("Right"); break; } refresh(); } endwin(); return 0; } ncurses 5. cpp 72

#include <curses. h> int main() { int i; char c; initscr(); noecho(); for (i=0; i<5; i++) { c = getch(); switch (c) { case 'h': addstr("Left"); break; case 'l': addstr("Right"); break; } refresh(); } endwin(); return 0; ncurses 5 a. cpp 73

Exercise: h, j, k, l for Left, Down, Up, Right 74

ncurses-6. cpp // ncurses-6. cpp #include <curses. h> int main() { int y=10, x=10; char c; initscr(); noecho(); do { move(y, x); addch('Q'); refresh(); c = getch(); move(y, x); addch(' '); switch (c) { case 'h': x--; break; case 'l': x++; break; case 'j': y++; break; case 'k': y--; break; } } while (c != 'q'); endwin(); return 0; } 75

curs_set() alters the appearance of the text cursor. p int curs_set(int visibility); p n n n A value of 0 for visibility makes the cursor disappear; A value of 1 makes the cursor appear "normal" (usually an underline) 2 makes the cursor "highly visible" (usually a block). 76

ncurses-6 a. cpp // ncurses-6 a. cpp #include <curses. h> int main() { int y=10, x=10; char c; initscr(); noecho(); curs_set(0); // no cursor do { move(y, x); addch('Q'); c = getch(); move(y, x); addch(' '); switch (c) { case 'h': x--; break; case 'l': x++; break; case 'j': y++; break; case 'k': y--; break; } } while (c != 'q'); endwin(); return 0; } 77

Game of Tanks p With these skills, you can actually design a game similar to World of Tanks (although less fancy). p ncurses-7. exe n n h, j, k, l for Left, Backward, Foreward, Right Spacebar to cannon. 78

Keypad Keys p Call keypad() to enable the handling of keypad keys and arrow keys. n n p int keypad(WINDOW *win, bool bf); keypad(stdscr, TRUE); getch() returns an integer corresponding to the key pressed. n n If it is a normal character, the integer value will be equivalent to the ASCII code of the character. Otherwise it returns a number which can be matched with the constants defined in curses. h. p For example if the user presses KEY_DOWN, the integer returned is 258. 79

Keypad Keys (cont. ) p With keypad() enabled, you can check the returned value of getch() with the constants defined in curses. h n n n KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT KEY_IC (Insert character) KEY_DC (Delete character) KEY_NPAGE (next page, i. e. , Page Down) KEY_PPAGE (previous page, i. e. , Page Up) KEY_F 6 ~ KEY_F 12 80

Key Definitions p p p p #define KEY_DOWN KEY_UP KEY_LEFT KEY_RIGHT 0402 0403 0404 0405 /* /* down-arrow key */ up-arrow key */ left-arrow key */ right-arrow key */ #define KEY_IC mode (Insert) */ #define KEY_DC */ #define KEY_PPAGE #define KEY_NPAGE 0513 /* insert char or enter ins 0512 /* delete character (Delete) 0523 0522 /* previous page (Page. Up) */ /* next page (Page. Down) */ You may check /usr/include/curses. h to see more definitions. 81

#include <curses. h> 8. cpp int main() { int c; initscr(); noecho(); keypad(stdscr, TRUE); do { move(9, 10); printw("Press a key ('q' to quit): "); c = getch(); move(10, 10); printw("%04 o %cn", c, c); refresh(); } while (c != 'q'); endwin(); return 0; } 82

Colors p To start using color, you should first call the function start_color(). n p To find out whether a terminal has color capabilities or not, you can use has_colors() function, which returns FALSE if the terminal does not support color. Colors are always used in pairs. n n A color-pair consists of a foreground color and a background color. Initializes a color-pair with the routine init_pair(). After it has been initialized, COLOR_PAIR(n) is used to represent the color 83 attribute.

ncurses-9. cpp #include <curses. h> int main() { initscr(); start_color(); init_pair( 1, COLOR_WHITE, COLOR_RED ); attron( COLOR_PAIR(1) ); printw("Background red"); attroff( COLOR_PAIR(1) ); refresh(); getch(); endwin(); return 0; } 84

Pre-defined Colors on Unix COLOR_BLACK p COLOR_RED p COLOR_GREEN p COLOR_YELLOW p COLOR_BLUE p COLOR_MAGENTA p COLOR_CYAN p COLOR_WHITE p = = = = 0 1 2 3 4 5 6 7 85

#include <curses. h> 9 d. cpp int main() { int j; initscr(); start_color(); init_pair( 1, COLOR_WHITE, COLOR_RED ); init_pair( 2, COLOR_WHITE, COLOR_GREEN ); init_pair( 3, COLOR_WHITE, COLOR_BLUE ); for (int i = 0; i < 36; i++) { j = i % 3 + 1; attron( COLOR_PAIR(j) ); printw("%2 d", i); if (i % 6 == 5) printw("n"); attroff( COLOR_PAIR(j) ); } refresh(); getch(); endwin(); return 0; } 86

// ncurses-9 c. cpp #include <curses. h> Change background color for the whole screen int main() { initscr(); start_color(); init_pair(1, COLOR_YELLOW, COLOR_BLUE); init_pair(2, COLOR_BLUE, COLOR_YELLOW); init_pair(3, COLOR_BLUE, COLOR_WHITE); // box(stdscr, '*', '-'); border('|', '-', '+', '+'); move(1, 5); printw("Hello, World. "); for (int i=1; i<=3; i++) { bkgd(COLOR_PAIR(i)); refresh(); getch(); } endwin(); } 87

Create ncurses borders p int border(chtype ls, chtype rs, chtype ts, chtype bs, chtype tl, chtype tr, chtype bl, chtype br); n n p p p ls - left side, ts - top side, tl - top left-hand corner, bl - bottom left-hand corner, rs - right side, bs - bottom side, tr - top right-hand corner, br - bottom right-hand corner. FAQ: Can I draw a box around a small rectangle, instead of the whole screen? FAQ: Can I change the color for only a small area, instead of the whole screen? Ans: Of course. In that case, you are working with a “window” instead of stdscr. n See the manpages of subwin(), delwin(). 88

Exercise: Arrow Keys Modify ncurses-6. cpp so that users can use arrow keys and HJKL to control the movement of ‘Q’. p Moreover, try to allow users to use both uppercase ‘H’ and lowercase ‘h’ to do the same movement. p Users can also change the color of ‘Q’ by pressing ‘ 0’…’ 7’. p 89

int timeout(int delay) p The timeout() function affects the behaviour of getch() when reading a character from stdscr. n n If delay is a positive number, then getch() will wait for that many milliseconds before returning If no character was available, then ERR (-1) will be returned. 90

ncurses-10. cpp #include <curses. h> switch(c) { case 'h': x--; break; case 'l': x++; break; } move(y, old_x); addch(' '); int main() { int x=10, old_x; int c; initscr(); move(15, 15); addch('T'); noecho(); curs_set(0); // hide the cursor timeout(500); // getch() will only wait 0. 5 second for (int y=1; y<15; y++) { move(y, x); addch('Q'); refresh(); old_x = x; c = getch(); } refresh(); endwin(); return 0; } 91

HW: Tetris 92
- Slides: 87