home *** CD-ROM | disk | FTP | other *** search
/ Fish 'n' More 2 / fishmore-publicdomainlibraryvol.ii1991xetec.iso / dirs / curses_391.lzh / Curses / examples / tttt / tttt.c < prev   
C/C++ Source or Header  |  1990-10-27  |  7KB  |  354 lines

  1. /*
  2.     Eric Lechner                Feb. 27, 1990
  3.  
  4.     revised for curses output: march 6, 1990
  5.  
  6.         CE 126 Final Project Development
  7.  
  8.     a high level simulation of tic-tac-toc-toe, a 4x4
  9.     version of tic-tac-toe with "wraparound edges"
  10.  
  11.     this takes user input for one player, and has a
  12.     computer player for the other.
  13. */
  14.  
  15. #include <stdio.h>
  16. #include <curses.h>
  17.  
  18. #define EMPTY    0
  19. #define X    1
  20. #define O    2
  21.  
  22. #define TIE    -1        /* for ending when the board is full */
  23. #define QUIT    -2
  24.  
  25. #define WIN    100        /* for position rank scoring */
  26.  
  27. #ifndef TRUE
  28. #define TRUE    1        /* cause they aren't included elsewhere */
  29. #define FALSE    0
  30. #endif
  31.  
  32. char board [4][4];        /* this is the playing board */
  33. int pieces;
  34.  
  35. void    initboard(),
  36.     printboard();
  37.  
  38. int    check_win(),
  39.     getrank(),
  40.     x_move(),        /* "our" move */
  41.     o_move();        /* the computer player's move */
  42.  
  43. main()
  44. {
  45.     int done = FALSE;
  46.     int xmove = TRUE;
  47.  
  48.     pieces = 0;
  49.  
  50.     initscr();
  51.     savetty();
  52.     cbreak();
  53.     noecho();
  54.  
  55.     initboard();
  56.  
  57.     clear();
  58.     printboard();
  59.     while (!done) {
  60.         if (xmove)
  61.             done = x_move();
  62.         else {
  63.             done = o_move();
  64.         }
  65.         if ((++pieces == 16) && !done) done = TIE;
  66.  
  67.         xmove = !xmove;
  68.     }
  69.  
  70.     switch (done) {
  71.         case TIE :
  72.             move(17,23);
  73.             printw("The board is full, and nobody won.\n");
  74.             break;
  75.         case QUIT :
  76.             move(17,23);
  77.             printw("Hope to beat you again someday!\n");
  78.             break;
  79.         default :
  80.             move(17,33);
  81.             printw("Player `%c' Wins!\n",(done == X) ? 'X' : 'O');
  82.     }
  83.     move(21,0);
  84.     refresh();
  85. #ifdef AMIGA
  86.     Delay(200);
  87. #else
  88.     sleep(2);
  89. #endif
  90.     resetty();
  91.     endwin();
  92. }
  93.  
  94. /*
  95.     initialize the board to all empty
  96. */
  97. void initboard()
  98. {
  99.     int i,j;
  100.  
  101.     for (i=0; i<4; i++)
  102.         for (j=0; j<4; j++)
  103.             board [i][j] = EMPTY;
  104. }
  105.  
  106. /*
  107.     print the current board
  108. */
  109. void printboard()
  110. {
  111.     int i;
  112.  
  113.     move(2,24);
  114.     printw("Tic-Tac-Toc-Toe - by Eric Lechner");
  115.  
  116.     move(5,30);
  117.     printw("    A   B   C   D \n");
  118.     move(6,30);
  119.     printw("   --- --- --- ---\n");
  120.     for (i=0; i<4; i++) {
  121.         move(7 + (i * 2), 30);
  122.         printw("%d | %c | %c | %c | %c |\n", i,
  123.             (!board[i][0]) ? ' ' : (board[i][0] == X) ? 'X' : 'O',
  124.             (!board[i][1]) ? ' ' : (board[i][1] == X) ? 'X' : 'O',
  125.             (!board[i][2]) ? ' ' : (board[i][2] == X) ? 'X' : 'O',
  126.             (!board[i][3]) ? ' ' : (board[i][3] == X) ? 'X' : 'O');
  127.         move(8 + (i * 2), 30);
  128.         printw("   --- --- --- ---\n");
  129.     }
  130.     refresh();
  131. }
  132.  
  133. /*
  134.     player "x", the human player
  135. */
  136. int x_move()
  137. {
  138.     int row, col, tmp, mess = 0;
  139. GetX:    row = col = -1;
  140.  
  141.     move(15,33);
  142.     printw("Your move : ");
  143.     clrtoeol();
  144.     refresh();
  145.     while ((row == -1) || (col == -1)) {
  146.         tmp = getch();
  147.         switch (tmp) {
  148.             case 'A' :
  149.             case 'a' :
  150.             case 'B' :
  151.             case 'b' :
  152.             case 'C' :
  153.             case 'c' :
  154.             case 'D' :
  155.             case 'd' :
  156.                 move(15,45);
  157.                 printw("%c ",tmp);
  158.                 if ((tmp >= 'a') && (tmp <= 'd'))
  159.                     col = tmp - 'a';
  160.                 else
  161.                     col = tmp - 'A';
  162.                 break;
  163.             case '0' :
  164.             case '1' :
  165.             case '2' :
  166.             case '3' :
  167.                 move(15,47);
  168.                 printw("%c",tmp);
  169.                 row = tmp - '0';
  170.                 break;
  171.             case 'q' :
  172.             case 'Q' :
  173.                 return(QUIT);
  174.                 break;
  175.             case 0x12 :
  176.             case 0x0c :
  177.                 clear();
  178.                 printboard();
  179.                 goto GetX;
  180.             default:
  181.                 break;
  182.         }
  183.         refresh();
  184.     }
  185.     if (board[row][col] == EMPTY) board[row][col] = X;
  186.     else {
  187.         move(17,34);
  188.         printw("Illegal move!\n");
  189.         mess = 1;    /* whether an error message has been printed */
  190.         refresh();
  191.         goto GetX;
  192.     }
  193.     
  194.     if (mess) {        /* if there was an error message, clear it */
  195.         move(17,1);
  196.         clrtoeol();
  197.     }
  198.  
  199.     move(7 + (row * 2), 34 + (col * 4));    /* print the move */
  200.     printw("X");
  201.  
  202.     refresh();
  203.  
  204.     return (check_win (X,row,col));
  205. }
  206.  
  207. /*
  208.     player "o", the computer player
  209. */
  210. int o_move()
  211. {
  212.     int bestrank = 0, bestrow = 0, bestcol = 0, i, j, rank;
  213.  
  214.     for (i=0; i<4; i++) {
  215.         for (j=0; j<4; j++) {
  216.             rank = getrank(O,i,j);
  217.             if (rank > bestrank) {
  218.                 bestrow = i;
  219.                 bestcol = j;
  220.                 bestrank = rank;
  221.             }
  222.         }
  223.     }
  224.  
  225.     board [bestrow][bestcol] = O;
  226.  
  227.     move(7 + (bestrow * 2), 34 + (bestcol * 4));
  228.     printw("O");
  229.     refresh();
  230.  
  231.     return (check_win (O,bestrow,bestcol));
  232. }
  233.  
  234. /*
  235.     this ranks a move location in order of "preference".
  236.  
  237.     the strategy is to not let the opponent get lots in a row.
  238.     ever.
  239.  
  240.  
  241.     rows, columns, and diagonals get treated independently, and
  242.     the "best" rank of them all is considered.
  243. */
  244. int getrank(type,row,col)
  245. int type,row,col;
  246. {
  247.     int i, rank = 0, countx = 0, counto = 0;
  248.  
  249.     /* if already taken, this isn't a good spot */
  250.     if (board[row][col]) return (rank);
  251.  
  252.     /* check across */
  253.     countx = counto = 0;
  254.     for (i=0; i<4; i++) {
  255.         if (board[row][i] == X) countx++;
  256.         else if (board[row][i] == O) counto++;
  257.     }
  258.     if (type == X) {
  259.         if (countx >= 3) return (WIN);
  260.         if (!countx && (counto > rank)) rank = counto;
  261.     } else {
  262.         if (counto >= 3) return (WIN);
  263.         if (!counto && (countx > rank)) rank = countx;
  264.     }
  265.  
  266.     /* check vertically */
  267.     countx = counto = 0;
  268.     for (i=0; i<4; i++) {
  269.         if (board[i][col] == X) countx++;
  270.         else if (board[i][col] == O) counto++;
  271.     }
  272.     if (type == X) {
  273.         if (countx >= 3) return (WIN);
  274.         if (!countx && (counto > rank)) rank = counto;
  275.     } else {
  276.         if (counto >= 3) return (WIN);
  277.         if (!counto && (countx > rank)) rank = countx;
  278.     }
  279.  
  280.     /* check \ diagonal */
  281.     countx = counto = 0;
  282.     for (i=0; i<4; i++) {
  283.         if (board[(row + i) % 4][(col + i) % 4] == X) countx++;
  284.         else if (board[(row + i) % 4][(col + i) % 4] == O) counto++;
  285.     }
  286.     if (type == X) {
  287.         if (countx >= 3) return (WIN);
  288.         if (!countx && (counto > rank)) rank = counto;
  289.     } else {
  290.         if (counto >= 3) return (WIN);
  291.         if (!counto && (countx > rank)) rank = countx;
  292.     }
  293.  
  294.     /* check / diagonal */
  295.     countx = counto = 0;
  296.     for (i=0; i<4; i++) {
  297.         if (board[(row + 4 - i) % 4][(col + i) % 4] == X) countx++;
  298.         else if (board[(row + 4 - i) % 4][(col + i) % 4] == O) counto++;
  299.     }
  300.     if (type == X) {
  301.         if (countx >= 3) return (WIN);
  302.         if (!countx && (counto > rank)) rank = counto;
  303.     } else {
  304.         if (counto >= 3) return (WIN);
  305.         if (!counto && (countx > rank)) rank = countx;
  306.     }
  307.  
  308.     /* add one, so that even no blocks still shows as a valid move    */
  309.     /* and return the rank for this move                */
  310.     return (++rank);
  311. }
  312.  
  313. /*
  314.     checks for a win at a specific location, and returns the
  315.     type of win, or 0, if there wasn't a win.
  316. */
  317. int check_win(type,row,col)
  318. int type, row, col;
  319. {
  320.     int r[4],c[4], i;    /* temp row, col, and counter vars */
  321.  
  322.     /* check across */
  323.     if ((board [row][0] == type) && (board [row][1] == type) &&
  324.         (board [row][2] == type) && (board [row][3] == type))
  325.         return (type);
  326.  
  327.     /* check vertically */
  328.     if ((board [0][col] == type) && (board [1][col] == type) &&
  329.         (board [2][col] == type) && (board [3][col] == type))
  330.         return (type);
  331.  
  332.     /* check \ diagonal */
  333.     for (i=0; i<4; i++) {
  334.         r[i] = (row + i) % 4;
  335.         c[i] = (col + i) % 4;
  336.     }
  337.     if ((board [r[0]][c[0]] == type) && (board [r[1]][c[1]] == type) &&
  338.         (board [r[2]][c[2]] == type) && (board [r[3]][c[3]] == type))
  339.         return (type);
  340.  
  341.     /* check / diagonal */
  342.     for (i=0; i<4; i++) {
  343.         r[i] = (row + i) % 4;
  344.         c[i] = (col + (4 - i)) % 4;
  345.     }
  346.     if ((board [r[0]][c[0]] == type) && (board [r[1]][c[1]] == type) &&
  347.         (board [r[2]][c[2]] == type) && (board [r[3]][c[3]] == type))
  348.         return (type);
  349.  
  350.     /* if it got here, there aren't any wins at that spot */
  351.     return (0);
  352. }
  353.  
  354.