本程式修正了因視窗大小調整而造成的映像無法顯示,主要用了signal 函數實現對進層的訊號控制...
本來想把輸贏結果用新的視窗重新顯示,但是後來發現不太好用,這樣寫還不如做個圖形介面的來的既方便又美觀,之所以當初考慮用curses庫做是因為主要想重點放在裡五子棋的核心部分AI, 以及一些網路socket功能和多線程部分,所以映像部分就比較省略了,預計完成大部分預想功能以後我會把這個遊戲用 C++重新移植到QT 或者GTK 上。
我的第一個版本是1.0,這是第二個版本:2.0。
/* This file is WuZiGame source code http://www.baidu.com application launcher, compatible with GNU/Linux and most other POSIX systems Copyright (C) 2013-2014 Sam Brown version 2.0 This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. Sam Brown E-mail: zzulion@gamil.com */ #include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <ctype.h>#include <signal.h>#include <ncurses.h>typedef struct stack{int y, x;}stack;struct {int top, left;int y, x;int board[15][15];int white_or_black;stack S[521];int s_top;int flag;}g;void draw_border( void );bool start( void );void draw_grid( void );void handle_signal( int signum );void handle_win( int signum );void show_cursor(void);void redraw_all( void );void move_step( void ); void draw_piece( void ); void regret( void );int win( int cal );void redraw_win( int flag );//WINDOW *create_newwin( int height, int width, int starty, int startx );//void destroy_win( WINDOW *local_win );void black_win( void );void white_win( void ); int main(){int key;again:if( !start() ){fprintf( stderr, "Error starting up ncurses!\n");return 1;}signal( SIGWINCH, (void (*)(int))handle_signal );memset( g.board, 0, sizeof(g.board) );g.y = 7; g.x = 7;g.white_or_black = 0;g.s_top = 0;redraw_all( );while( 1 ) { refresh(); key = getch(); switch( key ) { case KEY_LEFT: /* move left */ --g.x;if( g.x >= 0 && g.x <= 14 && g.y >= 0 && g.y <= 14 )move_step();else++g.x;break; case KEY_RIGHT: /* move right */ ++g.x;if( g.x >= 0 && g.x <= 14 && g.y >= 0 && g.y <= 14 )move_step();else--g.x; break; case KEY_UP: /* move up */ --g.y; if( g.x >= 0 && g.x <= 14 && g.y >= 0 && g.y <= 14 )move_step(); else++g.y; break; case KEY_DOWN: /* move down */ ++g.y;if( g.x >= 0 && g.x <= 14 && g.y >= 0 && g.y <= 14 )move_step(); else--g.y; break; case 32: /* draw the piece by press space */ if( g.x >= 0 && g.x <= 14 && g.y >= 0 && g.y <= 14 && !g.board[g.y][g.x] ) { g.flag = 0; draw_piece( ); g.flag = win( 0 ); } if( g.flag == 1 || g.flag == 2 ) {if( g.flag == 1 ){black_win();endwin();goto again;}if( g.flag == 2 ){white_win();endwin();goto again;} } break; case 'q': /* press q to quit */ endwin(); exit( 0 ); break; case 'n': /* new game, return to begin */ endwin(); goto again; case 'r': /* regret the piece you put */ regret( ); break; // case 't': // goto test; } }return 0;}void regret( void ){if( g.s_top == 0 )return ;else{g.y = g.S[(g.s_top)-1].y;g.x = g.S[(g.s_top)-1].x;move_step();g.board[g.y][g.x] = 0;printw( "." );move_step();}g.s_top--;}void draw_piece( void ){ char ch1 = 'X', ch2 = 'O'; if( (g.white_or_black++)%2 ) { g.S[g.s_top].y = g.y; g.S[g.s_top].x = g.x; g.s_top++; addch( ch1 ); move_step(); g.board[g.y][g.x] = 1; } else { g.S[g.s_top].y = g.y; g.S[g.s_top].x = g.x; g.s_top++; addch( ch2 ); move_step(); g.board[g.y][g.x] = 2; } }void move_step( void ) { show_cursor();} void redraw_all(){endwin();refresh();clear();draw_border();draw_grid();show_cursor();refresh();}void show_cursor(void){ // restore cursor's location move(g.top + g.y, g.left +2*(g.x) );}void draw_border( void ){int maxy, maxx, i;getmaxyx( stdscr, maxy, maxx );if( has_colors() )attron( COLOR_PAIR(1) );for( i = 0; i <= maxx; i++ ){mvaddstr( 0, i, " " );mvaddstr( maxy-1, i, " " );}mvaddstr( 0, maxx/2-10, "Five-in-a-row");mvaddstr( maxy-1, 1, "[N]ew Game [R]egert " );mvaddstr( maxy-1, maxx-13, "[Q]uit Game" ); attroff( COLOR_PAIR(1) );}void draw_grid( void ){int maxy, maxx, i, j, top, left;getmaxyx( stdscr, maxy, maxx );g.top = maxy/2 - 7;g.left = maxx/2 - 30;top = g.top;left = g.left;for( i = 0; i < 15; i++ ){for( j = 0; j < 15; j++ ){if( !g.board[i][j] )mvaddstr( top+i, left+2*j, ". ");if( g.board[i][j] == 1 )mvaddstr( top+i, left+2*j, "X ");if( g.board[i][j] == 2 )mvaddstr( top+i, left+2*j, "O ");}addstr( "\n" );}}void handle_signal( int signum ){if( signum == SIGWINCH )redraw_all();signal( signum, (void(*)(int))handle_signal );}bool start( void ){if( initscr() == NULL )return false;if( has_colors() == FALSE ){endwin();fprintf( stderr, "Your terminal does not support coloer\n");exit(0);}else{if( start_color() == ERR ){endwin();return false;}if( init_pair( 1, COLOR_RED, COLOR_YELLOW ) == ERR ){endwin();return false;}}if( noecho() == ERR ){endwin();return false;}if( raw() == ERR ){endwin();return false;}if( keypad(stdscr, true) == ERR ){endwin();return false;}//wait 1000 ms at a time for inputtimeout(1000);return true;}int win( int cal ) { int i, j, k; int s = 20; // col line for( i = g.y, j = 0; j < 4; j++ ) { if( g.board[++i][g.x] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 ) cal++; } else break; } for( i = g.y, j = 0; j < 4; j++ ) { if( g.board[--i][g.x] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 ) cal++; } else break; } if( cal+1 >= 5 ) return g.board[g.y][g.x]; cal = 0; //row line for( i = g.x, j = 0; j < 4; j++ ) { if( g.board[g.y][++i] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 ) cal++; } else break; } for( i = g.x, j = 0; j < 4; j++ ) { if( g.board[g.y][--i] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 ) cal++; } else break; } if( cal+1 >= 5 ) return g.board[g.y][g.x]; cal = 0; // oblique line one for( i = g.y, j = g.x, k = 0; k < 4; k++ ) { if( g.board[++i][--j] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 && j >= 0 && j <= 14 ) cal++; } else break; } for( i = g.y, j = g.x, k = 0; k < 4; k++ ) { if( g.board[--i][++j] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 && j >= 0 && j <= 14 ) cal++; } else break; } if( cal+1 >= 5 ) return g.board[g.y][g.x]; cal = 0; // oblique line two for( i = g.y, j = g.x, k = 0; k < 4; k++ ) { if( g.board[--i][--j] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 && j >= 0 && j <= 14 ) cal++; } else break; } for( i = g.y, j = g.x, k = 0; k < 4; k++ ) { if( g.board[++i][++j] == g.board[g.y][g.x] ) { if( i >= 0 && i <= 14 && j >= 0 && j <= 14 ) cal++; } else break; } if( cal+1 >= 5 ) return g.board[g.y][g.x]; cal = 0; return 0; } void black_win( void ){int maxy, maxx;/*WINDOW *my_win;int startx, starty, width, height;height = 3;width = 10;starty = (LINES-height)/2;startx = (COLS-width)/2;my_win = create_newwin( height, width, starty, startx );wprintw( my_win, "black win!" );getchar();getchar();destroy_win( my_win ); */clear();getmaxyx( stdscr, maxy, maxx );signal( SIGWINCH, (void (*)(int))handle_win );mvprintw( maxy/2, maxx/2-5, "black win!!" );mvprintw( maxy/2+1, maxx/2-11, "press any key to continue..." );refresh();getchar();}void white_win( void ){int maxx, maxy;/*WINDOW *my_win;int startx, starty, width, height;height = 3;width = 10;starty = (LINES-height)/2;startx = (COLS-width)/2;my_win = create_newwin( height, width, starty, startx );wprintw( my_win, "white win!" );getchar();getchar();destroy_win( my_win );*/clear();getmaxyx( stdscr, maxy, maxx );signal( SIGWINCH, (void (*)(int))handle_win );mvprintw( maxy/2, maxx/2-5, "white win!!" );mvprintw( maxy/2+1, maxx/2-11, "press any key to continue..." );refresh();getchar();}/*WINDOW *create_newwin( int height, int width, int starty, int startx ){WINDOW *local_win;local_win = newwin( height, width, starty, startx );wrefresh( local_win );return local_win;}void destroy_win( WINDOW *local_win ){wrefresh(local_win);delwin( local_win );}*/void redraw_win( int flag ){int maxy, maxx;clear();refresh();getmaxyx( stdscr, maxy, maxx );if( flag == 1 ){mvprintw( maxy/2, maxx/2-5, "black win!!" );mvprintw( maxy/2+1, maxx/2-11, "press any key to continue..." );}else{mvprintw( maxy/2, maxx/2-5, "white win!!" );mvprintw( maxy/2+1, maxx/2-11, "press any key to continue..." );}refresh();}void handle_win( int signum ){if( signum == SIGWINCH )redraw_win( g.flag );signal( signum, (void(*)(int))handle_win );}