Merge remote-tracking (subtree) branch 'PracticingCurses/master'

This commit is contained in:
Dan Buch
2012-03-03 20:15:32 -05:00
69 changed files with 4237 additions and 0 deletions

View File

@@ -0,0 +1,28 @@
# Makefile for JustForFun Files
# A few variables
CC=gcc
LIBS=-lncurses
SRC_DIR=.
EXE_DIR=../demo/exe
EXES = \
${EXE_DIR}/hanoi \
${EXE_DIR}/life\
${EXE_DIR}/magic \
${EXE_DIR}/queens \
${EXE_DIR}/shuffle \
${EXE_DIR}/tt
${EXE_DIR}/%: %.o
${CC} -o $@ $< ${LIBS}
%.o: ${SRC_DIR}/%.c
${CC} -o $@ -c $<
all: ${EXES}
clean:
@rm -f ${EXES}

View File

@@ -0,0 +1,10 @@
Description of files
--------------------
JustForFun
|
|----> hanoi.c -- The Towers of Hanoi Solver
|----> life.c -- The Game of Life demo
|----> magic.c -- An Odd Order Magic Square builder
|----> queens.c -- The famous N-Queens Solver
|----> shuffle.c -- A fun game, if you have time to kill
|----> tt.c -- A very trivial typing tutor

View File

@@ -0,0 +1,178 @@
#include <curses.h>
#define POSX 10
#define POSY 5
#define DISC_CHAR '*'
#define PEG_CHAR '#'
#define TIME_OUT 300
typedef struct _peg_struct {
int n_discs; /* Number of discs at present */
int bottomx, bottomy; /* bottom x, bottom y co-ord */
int *sizes; /* The disc sizes array */
}peg;
void init_pegs(peg *p_my_pegs, int n_discs);
void show_pegs(WINDOW *win, peg *p_my_pegs, int n_discs);
void free_pegs(peg *p_my_pegs, int n_discs);
void solve_hanoi(peg *p_my_pegs, int n, int src, int aux, int dst);
void move_disc(peg *p_my_pegs, int n_discs, int src, int dst);
void print_in_middle(int startx, int starty, int width, char *string, WINDOW *win);
void check_usr_response(peg *p_my_pegs, int n_discs);
int store_n_discs;
char *welcome_string = "Enter the number of discs you want to be solved: ";
int main(int argc, char *argv[])
{ int n_discs;
peg my_pegs[3];
initscr(); /* Start curses mode */
cbreak(); /* Line buffering disabled. Pass on every thing */
keypad(stdscr, TRUE);
curs_set(FALSE);
print_in_middle(0, LINES / 2, COLS, welcome_string, NULL);
scanw("%d", &n_discs);
timeout(TIME_OUT);
noecho();
store_n_discs = n_discs;
init_pegs(my_pegs, n_discs);
show_pegs(stdscr, my_pegs, n_discs);
solve_hanoi(my_pegs, n_discs, 0, 1, 2);
free_pegs(my_pegs, n_discs);
endwin(); /* End curses mode */
return 0;
}
void solve_hanoi(peg *p_my_pegs, int n_discs, int src, int aux, int dst)
{ if(n_discs == 0)
return;
solve_hanoi(p_my_pegs, n_discs - 1, src, dst, aux);
move_disc(p_my_pegs, store_n_discs, src, dst);
show_pegs(stdscr, p_my_pegs, store_n_discs);
check_usr_response(p_my_pegs, store_n_discs);
solve_hanoi(p_my_pegs, n_discs - 1, aux, src, dst);
}
void check_usr_response(peg *p_my_pegs, int n_discs)
{ int ch;
ch = getch(); /* Waits for TIME_OUT milliseconds */
if(ch == ERR)
return;
else
if(ch == KEY_F(1))
{ free_pegs(p_my_pegs, n_discs);
endwin();
exit(0);
}
}
void move_disc(peg *p_my_pegs, int n_discs, int src, int dst)
{ int temp, index;
--p_my_pegs[src].n_discs;
index = 0;
while(p_my_pegs[src].sizes[index] == 0 && index != n_discs)
++index;
temp = p_my_pegs[src].sizes[index];
p_my_pegs[src].sizes[index] = 0;
index = 0;
while(p_my_pegs[dst].sizes[index] == 0 && index != n_discs)
++index;
--index;
p_my_pegs[dst].sizes[index] = temp;
++p_my_pegs[dst].n_discs;
}
void init_pegs(peg *p_my_pegs, int n_discs)
{ int size, temp, i;
p_my_pegs[0].n_discs = n_discs;
/* Allocate memory for size array
* atmost the number of discs on a peg can be n_discs
*/
for(i = 0; i < n_discs; ++i)
p_my_pegs[i].sizes = (int *)calloc(n_discs, sizeof(int));
size = 3;
for(i = 0;i < n_discs; ++i, size += 2)
p_my_pegs[0].sizes[i] = size;
temp = (p_my_pegs[0].sizes[n_discs - 1] / 2);
p_my_pegs[0].bottomx = POSX + 1 + temp;
p_my_pegs[0].bottomy = POSY + 2 + n_discs;
p_my_pegs[1].bottomx = p_my_pegs[0].bottomx + 2 + 2 * temp;
p_my_pegs[1].bottomy = POSY + 2 + n_discs;
p_my_pegs[2].bottomx = p_my_pegs[1].bottomx + 2 + 2 * temp;
p_my_pegs[2].bottomy = POSY + 2 + n_discs;
}
void show_pegs(WINDOW *win, peg *p_my_pegs, int n_discs)
{ int i, j, k, x, y, size;
wclear(win);
attron(A_REVERSE);
mvprintw(24, 0, "Press F1 to Exit");
attroff(A_REVERSE);
for(i = 0;i < 3; ++i)
mvwprintw( win, p_my_pegs[i].bottomy - n_discs - 1,
p_my_pegs[i].bottomx, "%c", PEG_CHAR);
y = p_my_pegs[0].bottomy - n_discs;
for(i = 0; i < 3; ++i) /* For each peg */
{ for(j = 0; j < n_discs; ++ j) /* For each row */
{ if(p_my_pegs[i].sizes[j] != 0)
{ size = p_my_pegs[i].sizes[j];
x = p_my_pegs[i].bottomx - (size / 2);
for(k = 0; k < size; ++k)
mvwprintw(win, y, x + k, "%c", DISC_CHAR);
}
else
mvwprintw(win, y, p_my_pegs[i].bottomx, "%c", PEG_CHAR);
++y;
}
y = p_my_pegs[0].bottomy - n_discs;
}
wrefresh(win);
}
void free_pegs(peg *p_my_pegs, int n_discs)
{ int i;
for(i = 0;i < n_discs; ++i)
free(p_my_pegs[i].sizes);
}
/* -------------------------------------------------------------*
* startx = 0 means at present x *
* starty = 0 means at present y *
* win = NULL means take stdscr *
* -------------------------------------------------------------*/
void print_in_middle(int startx, int starty, int width, char *string, WINDOW *win)
{ int length, x, y;
float temp;
if(win == NULL)
win = stdscr;
getyx(win, y, x);
if(startx != 0)
x = startx;
if(starty != 0)
y = starty;
if(width == 0)
width = 80;
length = strlen(string);
temp = (width - length)/ 2;
x = startx + (int)temp;
mvwprintw(win, y, x, "%s", string);
refresh();
}

View File

@@ -0,0 +1,107 @@
#include <curses.h>
int STARTX = 0;
int STARTY = 0;
int ENDX = 79;
int ENDY = 24;
#define CELL_CHAR '#'
#define TIME_OUT 300
typedef struct _state {
int oldstate;
int newstate;
}state;
void display(WINDOW *win, state **area, int startx, int starty, int endx, int endy);
void calc(state **area, int x, int y);
void update_state(state **area, int startx, int starty, int endx, int endy);
int main()
{ state **workarea;
int i, j;
initscr();
cbreak();
timeout(TIME_OUT);
keypad(stdscr, TRUE);
ENDX = COLS - 1;
ENDY = LINES - 1;
workarea = (state **)calloc(COLS, sizeof(state *));
for(i = 0;i < COLS; ++i)
workarea[i] = (state *)calloc(LINES, sizeof(state));
/* For inverted U */
workarea[39][15].newstate = TRUE;
workarea[40][15].newstate = TRUE;
workarea[41][15].newstate = TRUE;
workarea[39][16].newstate = TRUE;
workarea[39][17].newstate = TRUE;
workarea[41][16].newstate = TRUE;
workarea[41][17].newstate = TRUE;
update_state(workarea, STARTX, STARTY, ENDX, ENDY);
/* For block */
/*
workarea[37][13].newstate = TRUE;
workarea[37][14].newstate = TRUE;
workarea[38][13].newstate = TRUE;
workarea[38][14].newstate = TRUE;
update_state(workarea, STARTX, STARTY, ENDX, ENDY);
*/
display(stdscr, workarea, STARTX, STARTY, ENDX, ENDY);
while(getch() != KEY_F(1))
{ for(i = STARTX; i <= ENDX; ++i)
for(j = STARTY; j <= ENDY; ++j)
calc(workarea, i, j);
update_state(workarea, STARTX, STARTY, ENDX, ENDY);
display(stdscr, workarea, STARTX, STARTY, ENDX, ENDY);
}
endwin();
return 0;
}
void display(WINDOW *win, state **area, int startx, int starty, int endx, int endy)
{ int i, j;
wclear(win);
for(i = startx; i <= endx; ++i)
for(j = starty;j <= endy; ++j)
if(area[i][j].newstate == TRUE)
mvwaddch(win, j, i, CELL_CHAR);
wrefresh(win);
}
void calc(state **area, int i, int j)
{ int neighbours;
int newstate;
neighbours =
area[(i - 1 + COLS) % COLS][j].oldstate +
area[(i - 1 + COLS) % COLS][(j - 1 + LINES) % LINES].oldstate +
area[(i - 1 + COLS) % COLS][(j + 1) % LINES].oldstate +
area[(i + 1) % COLS][j].oldstate +
area[(i + 1) % COLS][(j - 1 + LINES) % LINES].oldstate +
area[(i + 1) % COLS][(j + 1) % LINES].oldstate +
area[i][(j - 1 + LINES) % LINES].oldstate +
area[i][(j + 1) % LINES].oldstate;
newstate = FALSE;
if(area[i][j].oldstate == TRUE && (neighbours == 2 || neighbours == 3))
newstate = TRUE;
else
if(area[i][j].oldstate == FALSE && neighbours == 3)
newstate = TRUE;
area[i][j].newstate = newstate;
}
void update_state(state **area, int startx, int starty, int endx, int endy)
{ int i, j;
for(i = startx; i <= endx; ++i)
for(j = starty; j <= endy; ++j)
area[i][j].oldstate = area[i][j].newstate;
}

View File

@@ -0,0 +1,161 @@
#include <curses.h>
#include <stdlib.h>
#define STARTX 9
#define STARTY 3
#define WIDTH 6
#define HEIGHT 4
#define TRACE_VALUE TRACE_MAXIMUM
void board( WINDOW *win, int starty, int startx, int lines, int cols,
int tile_width, int tile_height);
void magic(int **, int);
void print(int **, int);
void magic_board(int **a,int n);
int main(int argc, char *argv[])
{
int **a,n,i;
if(argc != 2)
{ printf("Usage: %s <magic sqaure order>\n", argv[0]);
exit(0);
}
n = atoi(argv[1]);
if(n % 2 == 0)
{ printf("Sorry !!! I don't know how to create magic square of even order\n");
printf("The order should be an odd number\n");
exit(0);
}
a = (int **) malloc(n * sizeof(int*));
for(i = 0;i < n;++i)
a[i] = (int *)malloc(n * sizeof(int));
magic(a,n);
initscr();
curs_set(0);
noecho();
magic_board(a,n);
getch();
endwin();
return;
}
void magic(int **a, int n)
{
int i,j,k;
int row,col;
for(i = 0;i < n;++i)
for(j = 0;j < n;++j)
a[i][j] = -1;
row = 0;
col = n / 2;
k = 1;
a[row][col] = k;
while(k != n * n)
{
if(row == 0 && col != n - 1)
{ row = n - 1;
col ++;
a[row][col] = ++k;
}
else if(row != 0 && col != n - 1)
{ if(a[row - 1][col + 1] == -1)
{ row --;
col ++;
a[row][col] = ++k;
}
else
{
row ++;
a[row][col] = ++k;
}
}
else if(row != 0 && col == n - 1)
{
row --;
col = 0;
a[row][col] = ++k;
}
else if(row == 0 && col == n - 1)
{ row ++;
a[row][col] = ++k;
}
}
return;
}
void print(int **a,int n)
{ int i,j;
int x,y;
x = STARTX;
y = STARTY;
mvprintw(1,30,"MAGIC SQUARE");
for(i = 0;i < n;++i)
{ for(j = 0;j < n;++j)
{ mvprintw(y,x,"%d",a[i][j]);
if(n > 9)
x += 4;
else
x += 6;
}
x = STARTX;
if(n > 7)
y += 2;
else
y += 3;
}
refresh();
}
void board(WINDOW *win, int starty, int startx, int lines, int cols,
int tile_width, int tile_height)
{ int endy, endx, i, j;
endy = starty + lines * tile_height;
endx = startx + cols * tile_width;
for(j = starty; j <= endy; j += tile_height)
for(i = startx; i <= endx; ++i)
mvwaddch(win, j, i, ACS_HLINE);
for(i = startx; i <= endx; i += tile_width)
for(j = starty; j <= endy; ++j)
mvwaddch(win, j, i, ACS_VLINE);
mvwaddch(win, starty, startx, ACS_ULCORNER);
mvwaddch(win, endy, startx, ACS_LLCORNER);
mvwaddch(win, starty, endx, ACS_URCORNER);
mvwaddch(win, endy, endx, ACS_LRCORNER);
for(j = starty + tile_height; j <= endy - tile_height; j += tile_height)
{ mvwaddch(win, j, startx, ACS_LTEE);
mvwaddch(win, j, endx, ACS_RTEE);
for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
mvwaddch(win, j, i, ACS_PLUS);
}
for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
{ mvwaddch(win, starty, i, ACS_TTEE);
mvwaddch(win, endy, i, ACS_BTEE);
}
wrefresh(win);
}
void magic_board(int **a,int n)
{ int i,j, deltax, deltay;
int startx, starty;
starty = (LINES - n * HEIGHT) / 2;
startx = (COLS - n * WIDTH) / 2;
board(stdscr, starty, startx, n, n, WIDTH, HEIGHT);
deltay = HEIGHT / 2;
deltax = WIDTH / 2;
for(i = 0;i < n; ++i)
for(j = 0; j < n; ++j)
mvprintw(starty + j * HEIGHT + deltay,
startx + i * WIDTH + deltax,
"%d", a[i][j]);
}

View File

@@ -0,0 +1,122 @@
#include <stdio.h>
#include <curses.h>
#define QUEEN_CHAR '*'
int *nqueens(int num);
int place(int current, int *position);
int print(int *positions, int num_queens);
void board(WINDOW *win, int starty, int startx, int lines, int cols,
int tile_width, int tile_height);
int main(int argc, char *argv[])
{
int num_queens, *positions, count;
if(argc != 2)
{ printf("Usage: %s <number of queens (chess board order)>\n", argv[0]);
exit(1);
}
num_queens = atoi(argv[1]);
initscr();
cbreak();
keypad(stdscr, TRUE);
positions = nqueens(num_queens);
free(positions);
endwin();
return 0;
}
int *nqueens(int num)
{
int current, *position, num_solutions = 0;
position = (int *) calloc(num + 1, sizeof(int));
position[1] = 0;
current = 1; /* current queen is being checked */
/* position[current] is the coloumn*/
while(current > 0){
position[current] += 1;
while(position[current] <= num && !place(current, position) )
position[current] += 1;
if(position[current] <= num){
if(current == num) {
++num_solutions;
print(position, num);
}
else {
current += 1;
position[current] = 0;
}
}
else current -= 1; /* backtrack */
}
printf("Total Number of Solutions : %d\n", num_solutions);
return(position);
}
int place(int current, int *position)
{
int i;
if(current == 1) return(1);
for(i = 1; i < current; ++i)
if(position[i] == position[current]) return(0);
else if(abs(position[i] - position[current]) ==
abs(i - current))
return(0);
return(1);
}
int print(int *positions, int num_queens)
{ int count;
int y = 2, x = 2, w = 4, h = 2;
static int solution = 1;
mvprintw(0, 0, "Solution No: %d", solution++);
board(stdscr, y, x, num_queens, num_queens, w, h);
for(count = 1; count <= num_queens; ++count)
{ int tempy = y + (count - 1) * h + h / 2;
int tempx = x + (positions[count] - 1) * w + w / 2;
mvaddch(tempy, tempx, QUEEN_CHAR);
}
refresh();
mvprintw(LINES - 2, 0, "Press Any Key to See next solution (F1 to Exit)");
if(getch() == KEY_F(1))
{ endwin();
exit(0);
}
clear();
}
void board(WINDOW *win, int starty, int startx, int lines, int cols,
int tile_width, int tile_height)
{ int endy, endx, i, j;
endy = starty + lines * tile_height;
endx = startx + cols * tile_width;
for(j = starty; j <= endy; j += tile_height)
for(i = startx; i <= endx; ++i)
mvwaddch(win, j, i, ACS_HLINE);
for(i = startx; i <= endx; i += tile_width)
for(j = starty; j <= endy; ++j)
mvwaddch(win, j, i, ACS_VLINE);
mvwaddch(win, starty, startx, ACS_ULCORNER);
mvwaddch(win, endy, startx, ACS_LLCORNER);
mvwaddch(win, starty, endx, ACS_URCORNER);
mvwaddch(win, endy, endx, ACS_LRCORNER);
for(j = starty + tile_height; j <= endy - tile_height; j += tile_height)
{ mvwaddch(win, j, startx, ACS_LTEE);
mvwaddch(win, j, endx, ACS_RTEE);
for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
mvwaddch(win, j, i, ACS_PLUS);
}
for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
{ mvwaddch(win, starty, i, ACS_TTEE);
mvwaddch(win, endy, i, ACS_BTEE);
}
wrefresh(win);
}

View File

@@ -0,0 +1,205 @@
#include <curses.h>
#define STARTX 9
#define STARTY 3
#define WIDTH 6
#define HEIGHT 4
#define BLANK 0
typedef struct _tile {
int x;
int y;
}tile;
void init_board(int **board, int n, tile *blank);
void board(WINDOW *win, int starty, int startx, int lines, int cols,
int tile_width, int tile_height);
void shuffle_board(int **board, int n);
void move_blank(int direction, int **s_board, int n, tile *blank);
int check_win(int **s_board, int n, tile *blank);
enum { LEFT, RIGHT, UP, DOWN };
int main(int argc, char *argv[])
{ int **s_board;
int n, i, ch;
tile blank;
if(argc != 2)
{ printf("Usage: %s <shuffle board order>\n", argv[0]);
exit(1);
}
n = atoi(argv[1]);
s_board = (int **)calloc(n, sizeof(int *));
for(i = 0;i < n; ++i)
s_board[i] = (int *)calloc(n, sizeof(int));
init_board(s_board, n, &blank);
initscr();
keypad(stdscr, TRUE);
cbreak();
shuffle_board(s_board, n);
while((ch = getch()) != KEY_F(1))
{ switch(ch)
{ case KEY_LEFT:
move_blank(RIGHT, s_board, n, &blank);
break;
case KEY_RIGHT:
move_blank(LEFT, s_board, n, &blank);
break;
case KEY_UP:
move_blank(DOWN, s_board, n, &blank);
break;
case KEY_DOWN:
move_blank(UP, s_board, n, &blank);
break;
}
shuffle_board(s_board, n);
if(check_win(s_board, n, &blank) == TRUE)
{ mvprintw(24, 0, "You Win !!!\n");
refresh();
break;
}
}
endwin();
return 0;
}
void move_blank(int direction, int **s_board, int n, tile *blank)
{ int temp;
switch(direction)
{ case LEFT:
{ if(blank->x != 0)
{ --blank->x;
temp = s_board[blank->x][blank->y];
s_board[blank->x + 1][blank->y] = temp;
s_board[blank->x][blank->y] = BLANK;
}
}
break;
case RIGHT:
{ if(blank->x != n - 1)
{ ++blank->x;
temp = s_board[blank->x][blank->y];
s_board[blank->x - 1][blank->y] = temp;
s_board[blank->x][blank->y] = BLANK;
}
}
break;
case UP:
{ if(blank->y != 0)
{ --blank->y;
temp = s_board[blank->x][blank->y];
s_board[blank->x][blank->y + 1] = temp;
s_board[blank->x][blank->y] = BLANK;
}
}
break;
case DOWN:
{ if(blank->y != n - 1)
{ ++blank->y;
temp = s_board[blank->x][blank->y];
s_board[blank->x][blank->y - 1] = temp;
s_board[blank->x][blank->y] = BLANK;
}
}
break;
}
}
int check_win(int **s_board, int n, tile *blank)
{ int i, j;
s_board[blank->x][blank->y] = n * n;
for(i = 0;i < n; ++i)
for(j = 0;j < n; ++j)
if(s_board[i][j] != j * n + i + 1)
{ s_board[blank->x][blank->y] = BLANK;
return FALSE;
}
s_board[blank->x][blank->y] = BLANK;
return TRUE;
}
void init_board(int **s_board, int n, tile *blank)
{ int i, j, k;
int *temp_board;
temp_board = (int *)calloc(n * n, sizeof(int));
srand(time(NULL));
for(i = 0;i < n * n; ++i)
{
repeat :
k = rand() % (n * n);
for(j = 0;j <= i - 1; ++j)
if (k == temp_board[j])
goto repeat;
else
temp_board[i] = k;
}
k = 0;
for (i = 0;i < n;++i)
for(j = 0;j < n; ++j,++k)
{ if(temp_board[k] == 0)
{ blank->x = i;
blank->y = j;
}
s_board[i][j] = temp_board[k];
}
free(temp_board);
}
void board(WINDOW *win, int starty, int startx, int lines, int cols,
int tile_width, int tile_height)
{ int endy, endx, i, j;
endy = starty + lines * tile_height;
endx = startx + cols * tile_width;
for(j = starty; j <= endy; j += tile_height)
for(i = startx; i <= endx; ++i)
mvwaddch(win, j, i, ACS_HLINE);
for(i = startx; i <= endx; i += tile_width)
for(j = starty; j <= endy; ++j)
mvwaddch(win, j, i, ACS_VLINE);
mvwaddch(win, starty, startx, ACS_ULCORNER);
mvwaddch(win, endy, startx, ACS_LLCORNER);
mvwaddch(win, starty, endx, ACS_URCORNER);
mvwaddch(win, endy, endx, ACS_LRCORNER);
for(j = starty + tile_height; j <= endy - tile_height; j += tile_height)
{ mvwaddch(win, j, startx, ACS_LTEE);
mvwaddch(win, j, endx, ACS_RTEE);
for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
mvwaddch(win, j, i, ACS_PLUS);
}
for(i = startx + tile_width; i <= endx - tile_width; i += tile_width)
{ mvwaddch(win, starty, i, ACS_TTEE);
mvwaddch(win, endy, i, ACS_BTEE);
}
wrefresh(win);
}
void shuffle_board(int **s_board, int n)
{ int i,j, deltax, deltay;
int startx, starty;
starty = (LINES - n * HEIGHT) / 2;
startx = (COLS - n * WIDTH) / 2;
clear();
mvprintw(24, 0, "Press F1 to Exit");
board(stdscr, starty, startx, n, n, WIDTH, HEIGHT);
deltay = HEIGHT / 2;
deltax = WIDTH / 2;
for(j = 0; j < n; ++j)
for(i = 0;i < n; ++i)
if(s_board[i][j] != BLANK)
mvprintw(starty + j * HEIGHT + deltay,
startx + i * WIDTH + deltax,
"%-2d", s_board[i][j]);
refresh();
}

View File

@@ -0,0 +1,223 @@
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define HSIZE 60
#define LENGTH 75
#define WIDTH 10
#define STARTX 1
#define STARTY 5
#define STATUSX 1
#define STATUSY 25
#define KEY_F1 265
int print_menu();
void print_byebye();
void create_test_string();
void print_time(time_t startt, time_t endt, int mistakes);
void print_in_middle(int startx, int starty, int width, char *string, WINDOW *win);
char *groups[] = { "`123456" ,
"7890-=" ,
"~!@#$%^" ,
"&*()_+" ,
"<>?" ,
",./\\" ,
"asdfg",
"jkl;'",
"qwer",
"uiop",
"tyur",
"zxcv",
"bnm",
};
int n_groups;
int main()
{ int choice, i;
char *test_array;
int ch = KEY_F1;
int mistakes;
int x, y;
time_t start_t, end_t;
WINDOW *typing_win;
char string[80];
string[0] = '\0';
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
intrflush(stdscr, FALSE);
srandom(time(NULL));
n_groups = sizeof(groups) / sizeof(char *);
test_array = (char *)calloc(HSIZE + 1, sizeof(char));
while(1)
{
if(ch == KEY_F1)
{ choice = print_menu();
choice -= 1;
if(choice == n_groups)
{ print_byebye();
free(test_array);
endwin();
exit(0);
}
}
clear();
strcpy(string, "Typing window");
print_in_middle(STARTX, STARTY - 2, LENGTH, string, NULL);
attron(A_REVERSE);
mvprintw(STATUSY, STATUSX, "Press F1 to Main Menu");
refresh();
attroff(A_REVERSE);
create_test_string(test_array, choice);
typing_win = newwin(WIDTH, LENGTH, STARTY, STARTX);
keypad(typing_win, TRUE);
intrflush(typing_win, FALSE);
box(typing_win, 0, 0);
x = 1;
y = 1;
mvwprintw(typing_win, y, x, "%s", test_array);
wrefresh(typing_win);
y += 1;
mistakes = 0;
i = 0;
time(&start_t);
wmove(typing_win, y, x);
wrefresh(typing_win);
ch = 0;
while(ch != KEY_F1 && i != HSIZE + 1)
{ ch = wgetch(typing_win);
mvwprintw(typing_win, y, x, "%c", ch);
wrefresh(typing_win);
++x;
if(ch == test_array[i])
{ ++i;
continue;
}
else
{ ++mistakes;
++i;
}
}
time(&end_t);
print_time(start_t, end_t, mistakes);
}
free(test_array);
endwin();
return 0;
}
int print_menu()
{ int choice, i;
choice = 0;
while(1)
{ clear();
printw("\n\n");
print_in_middle(1, 1, 0, "* * * Welcome to typing practice (Version 1.0) * * * ", NULL);
printw("\n\n\n");
for(i = 0;i <= n_groups - 1; ++i)
printw("\t%3d: \tPractice %s\n", i + 1, groups[i]);
printw("\t%3d: \tExit\n", i + 1);
printw("\n\n\tChoice: ");
refresh();
echo();
scanw("%d", &choice);
noecho();
if(choice >= 1 && choice <= n_groups + 1)
break;
else
{ attron(A_REVERSE);
mvprintw(STATUSY, STATUSX, "Wrong choice\tPress any key to continue");
attroff(A_REVERSE);
getch();
}
}
return choice;
}
void create_test_string(char *test_array, int choice)
{ int i, index, length;
length = strlen(groups[choice]);
for(i = 0;i <= HSIZE - 1; ++i)
{ if(i%5 == 0)
test_array[i] = ' ';
else
{ index = (int)(random() % length);
test_array[i] = groups[choice][index];
}
}
test_array[i] = '\0';
}
void print_byebye()
{ printw("\n");
print_in_middle(0,0,0,"Thank you for using my typing tutor\n", NULL);
print_in_middle(0,0,0,"Bye Bye ! ! !\n", NULL);
refresh();
}
void print_time(time_t start_t, time_t end_t, int mistakes)
{ long int diff;
int h,m,s;
float wpm;
diff = end_t - start_t;
wpm = ((HSIZE / 5)/(double)diff)*60;
h = (int)(diff / 3600);
diff -= h * 3600;
m = (int)(diff / 60);
diff -= m * 60;
s = (int)diff;
attron(A_REVERSE);
mvprintw(STATUSY, STATUSX, "Mistakes made : %d time taken: %d:%d:%d WPM : %.2f Press any Key to continue", mistakes, h, m, s, wpm);
attroff(A_REVERSE);
refresh();
getch();
}
/* ---------------------------------------------------------------- *
* startx = 0 means at present x *
* starty = 0 means at present y *
* win = NULL means take stdscr *
* ---------------------------------------------------------------- */
void print_in_middle(int startx, int starty, int width, char *string, WINDOW *win)
{ int length, x, y;
float temp;
if(win == NULL)
win = stdscr;
getyx(win, y, x);
if(startx != 0)
x = startx;
if(starty != 0)
y = starty;
if(width == 0)
width = 80;
length = strlen(string);
temp = (width - length)/ 2;
x = startx + (int)temp;
mvwprintw(win, y, x, "%s", string);
refresh();
}