篮球6s屏幕失控打字乱弹控制台怎么打字

使用linux curses开发控制台的打字游戏_linux教程-织梦者
当前位置:&>&&>& > 使用linux curses开发控制台的打字游戏
使用linux curses开发控制台的打字游戏
1. 关于linux curses库,不多说,google下便知道,就像当年的TC下的窗口程序库一样
2. 事情源于在chinaunix上看到了the4king在c/c++论坛上的帖子:
http://bbs.chinaunix.net/thread--3.html
代码的编译命令是:
# gcc file.c -lrt -lcurses
我的平台是Ubuntu10.04
3. 先阅读原代码,了解其思想。
该打字游戏的实现思想大致如下:
界面如下几部分组成,topwin(也就是显示字母下落动画效果的窗口),numwin(成绩框,记录输入字符数及命中数)
其它信号处理倒是简单,对应了'1'暂停,'2'退出等功能。
以字符串darwscr代表整个topwin的输出内容
  在最上面一行产生若干个字符(数量很少)。然后将新字符串重写回topwin,刷新显示
  调用changekey(),然后检查checkkey()在location[]记录的命中字符,并把当前命中位置置成'@',把上次命中位置置成' '
  将topwin自第二行开始向下移动一行///注意这个地方没有加锁,有线程同步问题
checkkey()线程:
接收键盘输入
在当前darwscr里,找出命中位置,并记录到缓冲区中 //有线程同步问题
4. 观察其代码,发现一些不足之处
第一个地方,新增一个basewin,完全覆盖原始主窗口,因为发现在不同的终端下,默认原始主窗口的背景不一致,现在用basewin来统一一下,这样做有些移植性的意思哈。
首先,changekey()函数与函数之间用了不必要的信号量,完全可以用函数调用来代替
其次,每交topwin下移一行(产生动画效果)时,调用changekey()函数一次,实际上最多只能处理一个input字符,效果就是如果某一行的字符数大于topwin的高度LINES,
那么很悲剧,你无论键盘敲得多快,只能眼睁睁看着这一行落地而毫无办法。而且原代码里只用了一个变量去存储最近的命中字符,如果你输入很快,后面就会覆盖前面的。
解决办法很简单:
先建立输入缓冲区,这里用了一个循环队列,长度为1000,客观地讲应该不会溢出。
接着,就是改动changekey()的stop()时间,把节省下来的时间用于循环读缓冲区,争取在有限的时间里多处理几个命中的字符。
最后,完成上面这些改动之后,编译运行,缓冲区的效果是有了,可以在一次动画效果之间命中多个字符,但问题又来了,发现显示命中效果有问题,个别字符的命中效果产生了偏离,比如明明是第n行的第12个字符命中,却显示成了第n-行的第12个字符命中。检查了下代码,发现是多线程的问题。原代码在checkkey()里检查命中字符,并把其位置记录到缓冲区里,问题是,如果checkkey()恰好发生在一次动画效果之前,那么由于随后发生了动画效果,刚刚在checkkey()里记录的命中位置就不准确了,于是需要在动画效果的代码中检查缓冲区,并修正已有数据的偏移。同时,应该保证checkkey()修改缓冲区的代码与动画代码互斥。同一时刻只能有一个执行, 不然就混乱了!
可以通过增加信号量控制来改进这个问题
checkkey()线程:
循环接收键盘输入
信号量P操作,进入临界区
在当前darwscr里,找出命中位置,并记录到缓冲区中
信号量V操作,退出临界区
主线程,对应地改动:
sem_wait(&sem_location);
动画效果区代码
sem_post(&sem_location);
改动后的代码如下:
#include &unistd.h&
#include &stdlib.h&
#include &stdio.h&
#include &string.h&
#include &time.h&
#include &sys/time.h&
#include &curses.h&
#include &pthread.h&
#include &semaphore.h&
#include &signal.h&
静态窗口设置后可以关闭
动态窗口设置后不应该关闭,应该保持打开状态,使之长期有效
窗口创建后,如果没有主动调用refresh()是不会出现的,所以想让谁出现就调用对应的wrefresh(win)
void *checkkey (void *arg);
void *changekey (void *arg);
void *isover (void *arg);
WINDOW *a_win,*b_win,*c_
WINDOW *topwin,*bottomwin, *pausewin,*overwin,*numwin, *
pthread_t main_
sem_t sem_location, sem_
int n=400000,FLAG=1,hited_num=0,typed_num=0;
void releasewin()
free(darwscr);
free(basestr);
sem_destroy(&sem_location);
sem_destroy(&sem_lastlocation);
delwin(topwin);delwin(pausewin);delwin(numwin);
delwin(overwin);endwin();
void contin ()
touchwin(topwin);
wrefresh(topwin);
void paus ()
touchwin(pausewin);
wrefresh(pausewin);
void game_over ()
touchwin(overwin);wrefresh(overwin);
void stop (int usec)
tv.tv_sec=0;
tv.tv_usec=
select(0,NULL,NULL,NULL,&tv);
int main ()
int i,j,res,s=0;
struct sigaction to_pause,to_continue,to_
initscr();
noecho();cbreak();keypad(stdscr,TRUE);curs_set(0);
refresh();
darwscr = (char*) calloc((LINES-2)*(COLS-15),1);
basestr = (char*) calloc(LINES*COLS,1);
if(darwscr==NULL || basestr==NULL)
perror("Malloc Failure");endwin();exit(1);
basewin = newwin(LINES,COLS,0,0);
topwin=newwin(LINES-2,COLS-15,0,8);
bottomwin=newwin(1,30, LINES-1,(COLS-30)/2);
pausewin=newwin(1,COLS/2,LINES/2,COLS/4);
overwin=newwin(3,COLS/2,LINES/2+1,COLS/4);
numwin=newwin(1,9,LINES-1,COLS/2+18);
if(topwin==NULL || pausewin==NULL || overwin==NULL || numwin==NULL || bottomwin==NULL)
perror("Create window Failure");endwin();exit(1);
if(!has_colors())
perror("Devices not support colors");
delwin(topwin);delwin(pausewin);delwin(overwin);
delwin(numwin);endwin();exit(1);
if(start_color()!=OK)
perror("Initialize Colors Failure");
delwin(topwin);delwin(pausewin);delwin(overwin);
delwin(numwin);endwin();exit(1);
init_pair(1,COLOR_WHITE,COLOR_BLACK);
init_pair(2,COLOR_GREEN, COLOR_RED);
init_pair(3,COLOR_YELLOW, COLOR_BLUE);
init_pair(4,COLOR_YELLOW, COLOR_BLUE);
init_pair(5,COLOR_BLACK, COLOR_CYAN);
////////////
wattron(basewin, COLOR_PAIR(2));
for(i=0;i&LINES;i++)
for(j=0; j&COLS; j++)
if(j== 7 || j==COLS-7)
*(basestr+i*(COLS) + j) = '+';
*(basestr+i*(COLS) + j) = ' ';
mvwaddstr(basewin,0,0,basestr);
wrefresh(basewin);
wattron(topwin, COLOR_PAIR(5));
memset(darwscr,' ', (LINES-2)*(COLS-15));
mvwaddstr(topwin,0,0, darwscr);
wrefresh(topwin);
wattron(bottomwin,COLOR_PAIR(2));
mvwprintw(bottomwin,0,0,"%s","Press '1' to PAUSE,'2' to QUIT");
wrefresh(bottomwin);
wattroff(bottomwin,COLOR_PAIR(2));
wattron(numwin,COLOR_PAIR(2));
mvwprintw(numwin,0,0,"[%3d/%-3d]",hited_num,typed_num);
wrefresh(numwin);
wattron(pausewin,COLOR_PAIR(2));
mvwprintw(pausewin,0,2,"%s","Press 'CTRL-C' to Continue.");
wattroff(pausewin,COLOR_PAIR(2));
wattron(overwin,COLOR_PAIR(3));
for(i=0;i&3;i++)
for(j=0;j&COLS/2;j++) mvwaddch(overwin,i,j,' ');
wattroff(overwin,COLOR_PAIR(3));
wattron(overwin,COLOR_PAIR(4));
mvwprintw(overwin,1,COLS/4-4,"%s","GAME OVER");
mvwprintw(overwin,2,COLS/4-8,"%s","'CTRL-C' to QUIT");
wattroff(overwin,COLOR_PAIR(4));
to_pause.sa_handler=
sigemptyset(&to_pause.sa_mask);
to_pause.sa_flags=0;
sigaction(SIGUSR1,&to_pause,0);
to_continue.sa_handler=
sigemptyset(&to_continue.sa_mask);
to_continue.sa_flags=0;
sigaction(SIGINT,&to_continue,0);
to_over.sa_handler=game_
sigemptyset(&to_over.sa_mask);
to_over.sa_flags=0;
sigaction(SIGUSR2,&to_over,0);
/////////////////////////
main_tid=pthread_self();
pthread_t new_
if(pthread_create(&new_one,NULL,checkkey,(void *)darwscr))
perror("Thread Create Failure");
releasewin();exit(1);
if(sem_init(&sem_location,0,1)||sem_init(&sem_lastlocation,0,0))
perror("Semaphore Initialize Failure");
releasewin();exit(1);
s=(int)time(NULL);
while(FLAG)
s+=n/1000;
for(i=0;i&COLS-15;i++)
//1000的区间,0-994都是空,994-999打印字母
double tmp = rand();
int zone = abs((int)(tmp/(double)RAND_MAX*1000));
if(zone & 994)
*(darwscr+i)=' ';
zone = abs(tmp)%('z'-'a') + 'a';
*(darwscr+i) = (char)
mvwaddstr(topwin,0,0,darwscr);
wrefresh(topwin);
changekey(darwscr);
////下移一行,sem_location用于与checkkey()
sem_wait(&sem_location);
memmove(darwscr+COLS-15,darwscr,(LINES-3)*(COLS-15));
tuneLocation();
sem_post(&sem_location);
mvwprintw(numwin,0,0,"[%3d/%-3d]",hited_num,typed_num);
wrefresh(numwin);
releasewin();
循环队列:location[1000], 1000的长度客观上讲不会出现循环队列满的现象
checkkey 只进行入队操作 影响tail
changekey 只进行出队操作 影响head
head == tail 为空
#define QUEUE_LEN 1000
int location[1000], last_location[QUEUE_LEN], times=0;
volatile int head = 0;
volatile int tail = 0;
void tuneLocation(){
for(i= i!= i=(i+1)%QUEUE_LEN)
location[i] += COLS-15;
void *checkkey (void *arg)
char *p=(char *)
key=getch();
if(key=='1') pthread_kill(main_tid,SIGUSR1);
else if(key=='2') FLAG=0;
else if(key&='a' && key&='z')
sem_wait(&sem_location);
for(i=(LINES-2)*(COLS-15)-1;i&=0;i--)
if(*(p+i)==key)
location[(tail++)%QUEUE_LEN] =
sem_post(&sem_location);
void *changekey (void *arg)
const char space=' ';
const char over='@';
char *p=(char *)
int i,j,k,l,tmp_
if(times&30) n=400000;
else if(times&=30 && times &60) n=350000;
else if(times&=60 && times&100) n=300000;
else if(times&=100 && times&150) n=250000;
else if(times&=150 && times &220) n=200000;
else n=150000;
//stop(n/2) + stop(n/10)*8
stop(n/2);
/////清除上次命中的字符&@&
for(l=0; last_location[l]!=0; l++)
*(p+last_location[l]) =
last_location[l] = 0;
while(j&8)
tmp_tail =
while(head != tmp_tail)
*(p + location[head]) =
last_location[i++] = location[head] + COLS - 15;
head = (head+1)%QUEUE_LEN;
stop(n/10);
for(m=(LINES-2)*(COLS-15)-1; m&=(LINES-3)*(COLS-15); m--)
if(*(p+m)&='a' && *(p+m)&='z')
pthread_kill(main_tid,SIGUSR2);
在完成原打字游戏的改进后,我想再增加功能,把打字游戏变成单词练习游戏,就像一些打字练习的软件一样
  基本思路是,生成一系列的小窗口,窗口有两行,一行是单词,随机产生,一行空等待用户输入
  动画效果还是主线程实现,定时循环。
  当用户输入的单词完全匹配小窗口上的单词时,窗口消失(不要delwin(),应该回收到一个pool中,以重复使用)
  代码如下:
#include &unistd.h&
#include &stdlib.h&
#include &stdio.h&
#include &string.h&
#include &time.h&
#include &sys/time.h&
#include &curses.h&
#include &pthread.h&
#include &semaphore.h&
#include &signal.h&
#include &assert.h&
这个版本准备做一个单词击打游戏
////////////////////////////////宏定义区/////////////////////
#define MAX_WORDS 10
#define TOP_WIDTH
#define TOP_HEIGHT (LINES-2)
#define MOVE_WIDTH
#define MOVE_HEIGHT
#define OFFSET_MW 3
#define QUEUE_LEN 1000
////////////////////////////////全局变量/////////////////////
WINDOW *a_win, *b_win, *c_
WINDOW *topwin, *bottomwin, *pausewin,*overwin,*numwin, *basewin, *
pthread_t main_
sem_t sem_keybuffer, sem_movequeue, sem_
int FLAG=1, hited_num=0, typed_num=0;
int keybuffer[QUEUE_LEN];//键盘输入循环队列
volatile int head = 0;
volatile int tail = 0;
int n=400000, times=0; //速度调节参数
///////////////////////////////////////////////////////////
void *receivekey (void *arg);
void *checkMatch (void* one);
void *isover (void *arg);
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
typedef struct
int match_
char word[100];
//待匹配字符位置 0 ~~ (length-1)
typedef struct
MOVWIN* array[MAX_WORDS];
//最早的窗口
}MOVWINQUEUE;
MOVWINQUEUE moveQueue =
.length = MAX_WORDS,
.cursize = 0,
.index = 0
typedef struct
MOVWIN* array[MAX_WORDS+10];
}MOVWINPOOL;
MOVWINPOOL movePool =
.index = 0,
.length = MAX_WORDS
void addToQueue(MOVWINQUEUE* pool, MOVWIN* mw)
assert(mw);
assert(mw-&win);
for(i=0; i&pool-& i++)
if(pool-&array[i]==NULL)
pool-&array[i] =
pool-&cursize ++;
//remove mw from
void removeFromQueue(MOVWINQUEUE* pool, MOVWIN* mw)
{//TODO:::未检察溢出,本程序不会出现
assert(mw);
for(i=0; i&pool-& i++)
if(pool-&array[i] == mw)
pool-&array[i] = NULL;
pool-&cursize --;
void getFromPool(MOVWINPOOL* pool, MOVWIN** mw)
*mw = NULL;
for(i=0; i&pool-& i++)
if(pool-&array[i]!=NULL)
*mw = pool-&array[i];
pool-&array[i] = NULL;
void addToPool(MOVWINPOOL* pool, MOVWIN* mw)
assert(mw);
assert(mw-&win);
for(i=0; i&pool-& i++)
if(pool-&array[i]==NULL)
pool-&array[i] =
void fillMoveWin(MOVWIN* mw, const char* word, int y, int x)
strcpy(mw-&word, word);
mw-&length = strlen(mw-&word);
mw-&index = 0;
void initMoveWin(MOVWIN* mw)
wattron(mw-&win, A_REVERSE);
mvwaddnstr(mw-&win, 0, 0, movestr,MOVE_HEIGHT*MOVE_WIDTH);
mw-&startx = 0;
//子窗口内部光标位置
mw-&starty = 0;
getbegyx(mw-&win, mw-&y, mw-&x);
mw-&x += i*15;
//子窗口在父窗口的坐标
mw-&index = 0;
mw-&finish = 0;
mw-&match_flag = 1;
void initPoolAndQueue(MOVWINPOOL* pool, MOVWINQUEUE* queue)
for(i=0; i&pool-& i++)
pool-&array[i] = NULL;
for(i=0; i&queue-& i++)
queue-&array[i] = NULL;
for(i=0; i&pool-& i++)
mw = (MOVWIN*) malloc(sizeof(MOVWIN));
assert(mw);
//TODO::check
mw-&win = newwin(MOVE_HEIGHT, MOVE_WIDTH, 0, 30);
assert(mw-&win);
initMoveWin(mw);
addToPool(pool, mw);
void releasewin()
free(topstr);
free(basestr);
sem_destroy(&sem_keybuffer);
sem_destroy(&sem_movequeue);
delwin(topwin);delwin(pausewin);delwin(numwin);
delwin(overwin);endwin();delwin(movewin);
void contin ()
touchwin(topwin);
wrefresh(topwin);
void paus ()
touchwin(pausewin);
wrefresh(pausewin);
void game_over ()
touchwin(topwin);wrefresh(topwin);
touchwin(overwin);wrefresh(overwin);
void stop (int usec)
tv.tv_sec=0;
tv.tv_usec=
select(0,NULL,NULL,NULL,&tv);
void speedTune()
if(times&30) n=400000;
else if(times&=30 && times &60) n=350000;
else if(times&=60 && times&100) n=300000;
else if(times&=100 && times&150) n=250000;
else if(times&=150 && times &220) n=200000;
else n=150000;
stop(n*1.5);
int main ()
int i,j,res,s=0;
struct sigaction to_pause,to_continue,to_
initscr();
noecho();cbreak();keypad(stdscr,TRUE);curs_set(0);
refresh();
basestr = (char*) calloc(LINES*COLS,1);
topstr = (char*) calloc((LINES-2)*(COLS-15),1);
memset(topstr,' ', (LINES-2)*(COLS-15));
movestr = (char*) calloc(2*10,1);
memset(movestr,' ', MOVE_WIDTH*MOVE_HEIGHT);
if(topstr==NULL || basestr==NULL)
perror("Malloc Failure");endwin();exit(1);
basewin = newwin(LINES,COLS,0,0);
topwin = newwin(TOP_HEIGHT,TOP_WIDTH,0,8);
bottomwin = newwin(1,30, LINES-1,(COLS-30)/2);
pausewin = newwin(1,COLS/2,LINES/2,COLS/4);
overwin = newwin(3,COLS/2,LINES/2+1,COLS/4);
numwin = newwin(1,11,LINES-1,COLS/2+18);
movewin = newwin(MOVE_HEIGHT, MOVE_WIDTH,0,15);
if(topwin==NULL || pausewin==NULL || overwin==NULL || numwin==NULL || bottomwin==NULL || movewin==NULL)
perror("Create window Failure");endwin();exit(1);
if(!has_colors())
perror("Devices not support colors");
delwin(topwin);delwin(pausewin);delwin(overwin);
delwin(numwin);endwin();exit(1);
if(start_color()!=OK)
perror("Initialize Colors Failure");
delwin(topwin);delwin(pausewin);delwin(overwin);
delwin(numwin);endwin();exit(1);
init_pair(1,COLOR_WHITE,COLOR_BLACK);
init_pair(2,COLOR_GREEN, COLOR_RED);
init_pair(3,COLOR_YELLOW, COLOR_BLUE);
init_pair(4,COLOR_YELLOW, COLOR_BLUE);
init_pair(5,COLOR_BLACK, COLOR_CYAN);
////////////
wattron(basewin, COLOR_PAIR(2));
for(i=0;i&LINES;i++)
for(j=0; j&COLS; j++)
if(j== 7 || j==COLS-7)
*(basestr+i*(COLS) + j) = '+';
*(basestr+i*(COLS) + j) = ' ';
mvwaddstr(basewin,0,0,basestr);
wrefresh(basewin);
wattron(topwin, COLOR_PAIR(5));
mvwaddstr(topwin,0,0, topstr);
wrefresh(topwin);
wattron(bottomwin,COLOR_PAIR(2));
mvwprintw(bottomwin,0,0,"%s","Press '1' to PAUSE,'2' to QUIT");
wrefresh(bottomwin);
wattroff(bottomwin,COLOR_PAIR(2));
wattron(numwin,COLOR_PAIR(2));
mvwprintw(numwin,0,0,"[Score:%-3d]",hited_num);
wrefresh(numwin);
wattron(pausewin,COLOR_PAIR(2));
mvwprintw(pausewin,0,2,"%s","Press 'CTRL-C' to Continue.");
wattroff(pausewin,COLOR_PAIR(2));
wattron(overwin,COLOR_PAIR(3));
for(i=0;i&3;i++)
for(j=0;j&COLS/2;j++) mvwaddch(overwin,i,j,' ');
wattroff(overwin,COLOR_PAIR(3));
wattron(overwin,COLOR_PAIR(4));
mvwprintw(overwin,1,COLS/4-4,"%s","GAME OVER");
mvwprintw(overwin,2,COLS/4-8,"%s","'CTRL-C' to QUIT");
wattroff(overwin,COLOR_PAIR(4));
to_pause.sa_handler=
sigemptyset(&to_pause.sa_mask);
to_pause.sa_flags=0;
sigaction(SIGUSR1,&to_pause,0);
to_continue.sa_handler=
sigemptyset(&to_continue.sa_mask);
to_continue.sa_flags=0;
sigaction(SIGINT,&to_continue,0);
to_over.sa_handler=game_
sigemptyset(&to_over.sa_mask);
to_over.sa_flags=0;
sigaction(SIGUSR2,&to_over,0);
/////////////////////////
main_tid=pthread_self();
if(sem_init(&sem_keybuffer,0,1)||sem_init(&sem_movequeue,0,1) || sem_init(&sem_first,0,0))
perror("Semaphore Initialize Failure");
releasewin();exit(1);
s=(int)time(NULL);
int y=0,x=20;
mvwin(movewin,y,x);
MOVWIN one =
.startx = 0,
.starty = 0,
.length = 5,
.word = "hello",
.index = 0,
.finish = 0,
.match_flag = 1,
.win = movewin
mvwaddnstr(one.win, one.starty, one.startx, one.word, one.length);
wrefresh(one.win);
initPoolAndQueue(&movePool, &moveQueue);
pthread_t new_one, new_
MOVWIN* tmp = NULL;
int rand_x, rand_y;
char* rand_word[9] = {"hello","world","linux","","google","baidu","redhat","sun","oracel"};
int wi = 0; //rand_word的索引
int lasty = OFFSET_MW;//小窗口间距
int isfirst = 1;
while(FLAG)
rand_y = 0;
rand_x = abs(rand()%(COLS-30)) + 10;
//是否需要添加新窗口到queue
sem_wait(&sem_movequeue);
if(moveQueue.cursize & MAX_WORDS && lasty &= OFFSET_MW )
getFromPool(&movePool, &tmp);
mvwaddnstr(tmp-&win, 0, 0, movestr, MOVE_HEIGHT*MOVE_WIDTH);
fillMoveWin(tmp, rand_word[wi], 0, rand_x);
wi = (wi+1)%9;
mvwaddnstr(tmp-&win, tmp-&starty, tmp-&startx, tmp-&word, tmp-&length);
mvwin(tmp-&win, tmp-&y, tmp-&x);
wrefresh(tmp-&win);
addToQueue(&moveQueue, tmp);
lasty = 0;
sem_post(&sem_movequeue);
if(isfirst)
if(pthread_create(&new_one,NULL,receivekey,(void *)topstr) || pthread_create(&new_two,NULL,checkMatch, NULL))
perror("Thread Create Failure");
releasewin();exit(1);
sem_post(&sem_first);
isfirst = 0;
speedTune();
///集体动画效果
refresh();
mvwaddnstr(topwin, 0, 0, topstr, (LINES-2)*(COLS-15));
wnoutrefresh(topwin);
sem_wait(&sem_movequeue);
for(j=0; j&moveQueue. j++)
tmp = NULL;
if(moveQueue.array[j] != NULL)
tmp = moveQueue.array[j];
//判断落地单词
if(tmp-&y == TOP_HEIGHT-MOVE_HEIGHT)
pthread_kill(main_tid, SIGUSR2);
//完成的消失(可以不匹配)
if(tmp-&finish == 1)
tmp-&finish = 0;
mvwin(tmp-&win, tmp-&y+5, tmp-&x+5);
removeFromQueue(&moveQueue, tmp);
addToPool(&movePool, tmp);
tmp == NULL;
++ //速度调节相关
else//动画效果
tmp-&y = tmp-&y + 1;
mvwin(tmp-&win, tmp-&y, tmp-&x);
wnoutrefresh(tmp-&win);
sem_post(&sem_movequeue);
doupdate();
///刷新成绩
mvwprintw(numwin,0,0,"[Score:%-3d]",hited_num);
wrefresh(numwin);
wattroff(topwin, COLOR_PAIR(5));
releasewin();
循环队列:location[1000], 1000的长度客观上讲不会出现循环队列满的现象
checkMatch 只进行入队操作 影响tail
changekey 只进行出队操作 影响head
head == tail 为空
void *receivekey (void *arg)
char *p=(char *)
key=getch();
if(key=='1') pthread_kill(main_tid,SIGUSR1);
else if(key=='2') FLAG=0;
keybuffer[tail] =
tail = (tail+1)%QUEUE_LEN;
INCRIMENT(one)
if(one-&index & one-&length) one-&index++;
DECRIMENT(one)
if(one-&index & 0) one-&index--;
DO_BACKSPACE(one)
mvwaddch(one-&win, one-&starty+1, one-&startx + one-&index, ' '); /
DECRIMENT(one);
wrefresh(one-&win);
CHECK_FINISH(one)
if(one-&index&=one-&length && one-&match_flag)
one-&finish = 1;
mvwin(one-&win, 0, 60);
DO_MATCH(one, ch) do{
wattron(one-&win, A_UNDERLINE);
mvwaddch(one-&win, one-&starty+1, one-&startx+one-&index, ch);
one-&index ++;
wrefresh(one-&win);
wattroff(one-&win, A_UNDERLINE);
DO_MISMATCH(one, ch) {
wattron(one-&win, A_BOLD);
mvwaddch(one-&win, one-&starty+1, one-&startx+one-&index, ch);
one-&match_flag = 0;
one-&index ++;
wrefresh(one-&win);
wattroff(one-&win, A_BOLD);
IS_MATCH_KEY(ch)
((ch)&='a'&&(ch)&='z')
IS_CONTROL_KEY(ch)
((ch)==27 || (ch) == KEY_BACKSPACE )
checkMatch (void* arg)
int i,j,k,l;
int buffer[100];
int buf_size=0;
sem_wait(&sem_first);
MOVWIN* mw = NULL;
//获得尽可能大的buffer
buf_size = 0;
int tmptail=
while(head != tmptail)
buffer[buf_size++] = keybuffer[head];
head = (head+1)%QUEUE_LEN;
//遍历buffer
for(i=0; i&buf_ i++)
int ch = buffer[i];
if(IS_MATCH_KEY(ch) || IS_CONTROL_KEY(ch))
//匹配窗口为空?
if(NULL == mw)
{///遍历moveQueue,找出合适的窗口
sem_wait(&sem_movequeue);
for(j=0; j&moveQueue. j++)
if(moveQueue.array[j] && moveQueue.array[j]-&word[0]== ch && moveQueue.array[j]-&finish==0)
mw = moveQueue.array[j];
sem_post(&sem_movequeue);
//有匹配窗口?
if(IS_MATCH_KEY(ch))
//超过index就不再进行
if(mw-&index & mw-&length)
if(ch == mw-&word[mw-&index])
DO_MATCH(mw, ch);
//检查是否完成
if(mw-&index &= mw-&length)
mw-&finish = 1;
mw = NULL;
DO_MISMATCH(mw, ch);
DO_BACKSPACE(mw);
  这个单词练习游戏还有很多地方没有完善,比如单词库随机功能,计数功能有问题(懒得改了),或者还有bug,但跑起来还像那么回事,如下图:
6. 需要说明的是refresh()函数的功能,在这上面犯了不少错误:
refresh()就是刷新主屏幕(默认的屏幕)
a)程序初始化阶段,清除主屏幕,否则有时候程序启动后,窗口上很多乱码和不知名的符号!
b) 如果程序里生成了好几个窗口,并频繁操作它们的位置,那么也需要定时地刷新主屏幕,否则同样是窗口上显示混乱!
以上就是使用linux curses开发控制台的打字游戏的全文介绍,希望对您学习和使用Linux有所帮助.
这些内容可能对你也有帮助
更多可查看linux教程列表页。
猜您也会喜欢这些文章

我要回帖

更多关于 控制台屏幕缓冲区 的文章

 

随机推荐