curses编程初步--汉诺塔游戏

来源:互联网 发布:淘宝商品放到自己平台 编辑:程序博客网 时间:2024/05/16 04:25
/************************************************* *  run normally:       hanoi -n <steps>              * *  example:           hanoi -a <steps>              * *  help:           hanoi -h                     * *************************************************/#include <curses.h>#include <string.h>#include <unistd.h>#define EXIT_SUCCESS        0#define EXIT_FAILURE        1#define NPEGS           3#define MINTILES            3#define MAXTILES            6#define DEFAULTTILES        7#define TOPLINE         6#define BASELINE            16#define STATUSLINE      (LINES-3)#define LEFTPEG         19#define MIDPEG          39#define RIGHTPEG            59#define LENTOIND(x)     (((x)-1)/2)#define OTHER(a,b)      (3-((a)+(b)))struct Peg {    size_t Length[MAXTILES];    int Count;};static struct Peg Pegs[NPEGS];static int PegPos[] ={LEFTPEG, MIDPEG, RIGHTPEG};static int TileColour[] ={    COLOR_RED,    COLOR_GREEN,    COLOR_YELLOW,    COLOR_BLUE,    COLOR_MAGENTA,    COLOR_CYAN,};static int NMoves = 0;static void InitTiles(int NTiles);static void DisplayTiles(void);static void MakeMove(int From, int To);static void AutoMove(int From, int To, int Num);static void Usage(void);static int Solved(int NumTiles);static int GetMove(int *From, int *To);static int InvalidMove(int From, int To);intmain(int argc, char **argv){  int NTiles, FromCol, ToCol,opt;  unsigned char AutoFlag = 0;  if(argc<2 || argc>3){ Usage();exit(0);}  while( (opt=getopt(argc,argv,"a:n:h") )!=-1)    switch (opt)    {      case 'n':NTiles = atoi(optarg);if (NTiles > MAXTILES || NTiles < MINTILES){   fprintf(stderr, "steps must be assigned between %d and %d/n", MINTILES, MAXTILES);return EXIT_FAILURE;}AutoFlag = FALSE;break;      case 'a':NTiles = atoi(optarg);if (NTiles > MAXTILES || NTiles < MINTILES){       fprintf(stderr, "steps must be assigned between %d and %d/n", MINTILES, MAXTILES);return EXIT_FAILURE;}AutoFlag = TRUE;break;      case 'h':      case '?':      case ':':Usage();exit(0);    }  initscr();  if (has_colors())  {    int i;    int bg = COLOR_BLACK;    start_color();    if (use_default_colors() == OK)      bg = -1;    for (i = 0; i < sizeof(TileColour); i++)      init_pair(i + 1, bg, TileColour[i]);  }  cbreak();  /* LINES and COLS are local variables in curses.h,    * which are used to store the total lines and total columns of current terminal.   */  if (LINES < 24 || COLS < 80)          /* standard terminal is 24*80 */  {    endwin();    fprintf(stderr, "current terminal is less than 24x80 /n");    return EXIT_FAILURE;  }  if (AutoFlag)  {    curs_set(0);    leaveok(stdscr, TRUE);  }  InitTiles(NTiles);  DisplayTiles();  if (AutoFlag) {    do {      noecho();      AutoMove(0, 2, NTiles);    } while (!Solved(NTiles));    sleep(2);  }   else {    echo();    for (;;) {      if (GetMove(&FromCol, &ToCol))break;      if (InvalidMove(FromCol, ToCol)) {mvaddstr(STATUSLINE, 0, "Invalid move !!");refresh();beep();sleep(2);continue;      }      MakeMove(FromCol, ToCol);      if (Solved(NTiles)) {mvprintw(STATUSLINE, 0, "Congratulations: You Win! %d steps used.", NMoves);refresh();sleep(5);break;      }    }  }  endwin();  return EXIT_SUCCESS;}static intInvalidMove(int From, int To){    if (From >= NPEGS)    return TRUE;    if (From < 0)    return TRUE;    if (To >= NPEGS)    return TRUE;    if (To < 0)    return TRUE;    if (From == To)    return TRUE;    if (!Pegs[From].Count)    return TRUE;    if (Pegs[To].Count &&    Pegs[From].Length[Pegs[From].Count - 1] >    Pegs[To].Length[Pegs[To].Count - 1])    return TRUE;    return FALSE;}static voidInitTiles(int NTiles){    int Size, SlotNo;    for (Size = NTiles * 2 + 1, SlotNo = 0; Size >= 3; Size -= 2)    Pegs[0].Length[SlotNo++] = Size;    Pegs[0].Count = NTiles;    Pegs[1].Count = 0;    Pegs[2].Count = 0;}static voidDisplayTiles(void){    int Line, peg, SlotNo;    char TileBuf[BUFSIZ];    erase();    init_pair(20,COLOR_MAGENTA,COLOR_BLACK);    attrset(COLOR_PAIR(20)|A_BOLD);    mvaddstr(1, 25,"Hanoi games!");    attrset(A_NORMAL);    mvprintw(18, 30, "current steps : ");    init_pair(21,COLOR_RED,COLOR_BLACK);    attrset(COLOR_PAIR(21)|A_BOLD);    mvprintw(18,50,"%d",NMoves);    attrset(A_NORMAL);    attrset(A_REVERSE);    mvaddstr(BASELINE, 8,         "                                                               ");    for (Line = TOPLINE; Line < BASELINE; Line++) {    mvaddch(Line, LEFTPEG, ' ');    mvaddch(Line, MIDPEG, ' ');    mvaddch(Line, RIGHTPEG, ' ');    }    mvaddch(BASELINE, LEFTPEG, '1');    mvaddch(BASELINE, MIDPEG, '2');    mvaddch(BASELINE, RIGHTPEG, '3');    attrset(A_NORMAL);        for (peg = 0; peg < NPEGS; peg++) {    for (SlotNo = 0; SlotNo < Pegs[peg].Count; SlotNo++) {        memset(TileBuf, ' ', Pegs[peg].Length[SlotNo]);        TileBuf[Pegs[peg].Length[SlotNo]] = '/0';        if (has_colors())        attrset(COLOR_PAIR(LENTOIND(Pegs[peg].Length[SlotNo])));        else        attrset(A_REVERSE);        mvaddstr(BASELINE - (SlotNo + 1),             (int) (PegPos[peg] - Pegs[peg].Length[SlotNo] / 2),             TileBuf);    }    }    attrset(A_NORMAL);    refresh();}static intGetMove(int *From, int *To){    attrset(A_REVERSE);    mvaddstr(LINES-1, 20,"<Q>/<q> quit       <1>-<3> move");    attrset(A_NORMAL);    mvaddstr(STATUSLINE, 0, "Next step: from ");    clrtoeol();    refresh();    *From = getch();    if ((*From == 'q')||(*From == 'Q') )return TRUE;    *From -= ('0' + 1);    addstr(" to ");    clrtoeol();    refresh();    *To = getch();    if ((*To == 'q') || (*To == 'Q'))return TRUE;    *To -= ('0' + 1);    refresh();    napms(500);    move(STATUSLINE, 0);    clrtoeol();    refresh();    return FALSE;}static voidMakeMove(int From, int To){    Pegs[From].Count--;    Pegs[To].Length[Pegs[To].Count] = Pegs[From].Length[Pegs[From].Count];    Pegs[To].Count++;    NMoves++;    DisplayTiles();}static voidAutoMove(int From, int To, int Num){    if (Num == 1) {    MakeMove(From, To);    napms(500);    return;    }    AutoMove(From, OTHER(From, To), Num - 1);    MakeMove(From, To);    napms(500);    AutoMove(OTHER(From, To), To, Num - 1);}static intSolved(int NumTiles){    int i;    for (i = 1; i < NPEGS; i++)    if (Pegs[i].Count == NumTiles)        return TRUE;    return FALSE;}static voidUsage(){    fprintf(stderr, "/nhanoi/t[n]steps -- play games/n/    /t[a]steps -- examples/n/t[h] /t-- help /n");    printf("/e[0;33m Note: steps must be assigned between %d and %d./e[0m/n", MINTILES, MAXTILES);}/*----------------the end-----------------*/
原创粉丝点击