billr@saab.CNA.TEK.COM (Bill Randle) (03/07/90)
Submitted-by: Eric Lechner <lechner@ucscb.ucsc.edu> Posting-number: Volume 9, Issue 33 Archive-name: tttt/Part01 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 1 (of 1)." # Contents: README Makefile tttt.6 tttt.c # Wrapped by billr@saab on Tue Mar 6 17:20:43 1990 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(482 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XThis is a 4 by 4 version of tic-tac-toe with "wraparound Xedges" (so you can have off-center diagonal wins). X XI've compiled it under 4.3 BSD Unix, but it should compile Xok just about everywhere that has a curses package. X XEdit the Makefile as necessary, then make. X XIf you improve the code, please let me know. I'd be interested Xin seeing any changes to it. X XThis program is public domain. X X-Eric Lechner, 6 March 1990 Xlechner@ucscb.ucsc.edu ...!ucbvax!ucscc!ucscb!lechner END_OF_FILE if test 482 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'Makefile' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'Makefile'\" else echo shar: Extracting \"'Makefile'\" \(566 characters\) sed "s/^X//" >'Makefile' <<'END_OF_FILE' X# makefile for tic-tac-toc-toe X# X# edit as necessary, then make X X# where the executable will go XBINDIR = /usr/games X X# where the formatted manpage will go XMANDIR = /usr/games/Doc X X# options for the c compiler (-g, -O, etc.) XCFLAGS = -O X X# compiler libraries (-ltermcap, etc.) XLIBS = -lcurses -ltermcap X Xtttt: tttt.c X cc $(CFLAGS) -o tttt tttt.c $(LIBS) X Xinstall: tttt tttt.man X cp tttt $(BINDIR)/tttt X chmod 711 $(BINDIR)/tttt X cp tttt.man $(MANDIR)/tttt.6 X chmod 644 $(MANDIR)/tttt.6 X Xtttt.man: tttt.6 X nroff -man tttt.6 > tttt.man X Xclean: X rm -f tttt *.o tttt.man END_OF_FILE if test 566 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'tttt.6' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tttt.6'\" else echo shar: Extracting \"'tttt.6'\" \(1013 characters\) sed "s/^X//" >'tttt.6' <<'END_OF_FILE' X.TH TTTT 6 "6 March 1990" X.SH NAME Xtttt X\- tic-tac-toc-toe with wraparound edges X.SH SYNOPSIS X.B /usr/games/tttt X.SH DESCRIPTION XTic-Tac-Toc-Toe is a 4 by 4 version of Tic-Tac-Toe Xwith wraparound edges. The goal of the game is to Xconnect 4 of your pieces in a row, either horizontally, Xvertically, or diagonally. Note that diagonal wins can Xbe off-center, due to the wraparound edges (and hence, there Xare no corners in the board). X.PP XTo play, simply press the letter and number corresponding Xto select the appropriate square, and the computer will then Xtake its turn. X.PP XThe first player to connect four squares in a row wins. If Xthe board becomes filled without a winner, it is a tie game. X.SH HISTORY XThis program was originally written for an Advanced Logic XDesign class, as a high level version of the program to Xlater be implemented in hardware. It was converted to run Xwith curses in an attempt to procrastinate working on the Xhardware implementation. X.SH AUTHOR XEric Lechner, lechner@ucscb.ucsc.edu END_OF_FILE if test 1013 -ne `wc -c <'tttt.6'`; then echo shar: \"'tttt.6'\" unpacked with wrong size! fi # end of 'tttt.6' fi if test -f 'tttt.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tttt.c'\" else echo shar: Extracting \"'tttt.c'\" \(6961 characters\) sed "s/^X//" >'tttt.c' <<'END_OF_FILE' X/* X Eric Lechner Feb. 27, 1990 X X revised for curses output: march 6, 1990 X X CE 126 Final Project Development X X a high level simulation of tic-tac-toc-toe, a 4x4 X version of tic-tac-toe with "wraparound edges" X X this takes user input for one player, and has a X computer player for the other. X*/ X X#include <stdio.h> X#include <curses.h> X X#define EMPTY 0 X#define X 1 X#define O 2 X X#define TIE -1 /* for ending when the board is full */ X#define QUIT -2 X X#define WIN 100 /* for position rank scoring */ X X#ifndef TRUE X#define TRUE 1 /* cause they aren't included elsewhere */ X#define FALSE 0 X#endif X Xchar board [4][4]; /* this is the playing board */ Xint pieces; X Xvoid initboard(), X printboard(); X Xint check_win(), X getrank(), X x_move(), /* "our" move */ X o_move(); /* the computer player's move */ X Xmain() X{ X int done = FALSE; X int xmove = TRUE; X X pieces = 0; X X initscr(); X savetty(); X cbreak(); X noecho(); X X initboard(); X X clear(); X printboard(); X while (!done) { X if (xmove) X done = x_move(); X else { X done = o_move(); X } X if ((++pieces == 16) && !done) done = TIE; X X xmove = !xmove; X } X X switch (done) { X case TIE : X move(17,23); X printw("The board is full, and nobody won.\n"); X break; X case QUIT : X move(17,23); X printw("Hope to beat you again someday!\n"); X break; X default : X move(17,33); X printw("Player `%c' Wins!\n",(done == X) ? 'X' : 'O'); X } X move(21,0); X refresh(); X sleep(2); X resetty(); X endwin(); X} X X/* X initialize the board to all empty X*/ Xvoid initboard() X{ X int i,j; X X for (i=0; i<4; i++) X for (j=0; j<4; j++) X board [i][j] = EMPTY; X} X X/* X print the current board X*/ Xvoid printboard() X{ X int i; X X move(2,24); X printw("Tic-Tac-Toc-Toe - by Eric Lechner"); X X move(5,30); X printw(" A B C D \n"); X move(6,30); X printw(" --- --- --- ---\n"); X for (i=0; i<4; i++) { X move(7 + (i * 2), 30); X printw("%d | %c | %c | %c | %c |\n", i, X (!board[i][0]) ? ' ' : (board[i][0] == X) ? 'X' : 'O', X (!board[i][1]) ? ' ' : (board[i][1] == X) ? 'X' : 'O', X (!board[i][2]) ? ' ' : (board[i][2] == X) ? 'X' : 'O', X (!board[i][3]) ? ' ' : (board[i][3] == X) ? 'X' : 'O'); X move(8 + (i * 2), 30); X printw(" --- --- --- ---\n"); X } X refresh(); X} X X/* X player "x", the human player X*/ Xint x_move() X{ X int row, col, tmp, mess = 0; XGetX: row = col = -1; X X move(15,33); X printw("Your move : "); X clrtoeol(); X refresh(); X while ((row == -1) || (col == -1)) { X tmp = getch(); X switch (tmp) { X case 'A' : X case 'a' : X case 'B' : X case 'b' : X case 'C' : X case 'c' : X case 'D' : X case 'd' : X move(15,45); X printw("%c ",tmp); X if ((tmp >= 'a') && (tmp <= 'd')) X col = tmp - 'a'; X else X col = tmp - 'A'; X break; X case '0' : X case '1' : X case '2' : X case '3' : X move(15,47); X printw("%c",tmp); X row = tmp - '0'; X break; X case 'q' : X case 'Q' : X return(QUIT); X break; X case 0x12 : X case 0x0c : X clear(); X printboard(); X goto GetX; X default: X break; X } X refresh(); X } X if (board[row][col] == EMPTY) board[row][col] = X; X else { X move(17,34); X printw("Illegal move!\n"); X mess = 1; /* whether an error message has been printed */ X refresh(); X goto GetX; X } X X if (mess) { /* if there was an error message, clear it */ X move(17,1); X clrtoeol(); X } X X move(7 + (row * 2), 34 + (col * 4)); /* print the move */ X printw("X"); X X refresh(); X X return (check_win (X,row,col)); X} X X/* X player "o", the computer player X*/ Xint o_move() X{ X int bestrank = 0, bestrow = 0, bestcol = 0, i, j, rank; X X for (i=0; i<4; i++) { X for (j=0; j<4; j++) { X rank = getrank(O,i,j); X if (rank > bestrank) { X bestrow = i; X bestcol = j; X bestrank = rank; X } X } X } X X board [bestrow][bestcol] = O; X X move(7 + (bestrow * 2), 34 + (bestcol * 4)); X printw("O"); X refresh(); X X return (check_win (O,bestrow,bestcol)); X} X X/* X this ranks a move location in order of "preference". X X the strategy is to not let the opponent get lots in a row. X ever. X X X rows, columns, and diagonals get treated independently, and X the "best" rank of them all is considered. X*/ Xint getrank(type,row,col) Xint type,row,col; X{ X int i, j, rank = 0, countx = 0, counto = 0; X X /* if already taken, this isn't a good spot */ X if (board[row][col]) return (rank); X X /* check across */ X countx = counto = 0; X for (i=0; i<4; i++) { X if (board[row][i] == X) countx++; X else if (board[row][i] == O) counto++; X } X if (type == X) { X if (countx >= 3) return (WIN); X if (!countx && (counto > rank)) rank = counto; X } else { X if (counto >= 3) return (WIN); X if (!counto && (countx > rank)) rank = countx; X } X X /* check vertically */ X countx = counto = 0; X for (i=0; i<4; i++) { X if (board[i][col] == X) countx++; X else if (board[i][col] == O) counto++; X } X if (type == X) { X if (countx >= 3) return (WIN); X if (!countx && (counto > rank)) rank = counto; X } else { X if (counto >= 3) return (WIN); X if (!counto && (countx > rank)) rank = countx; X } X X /* check \ diagonal */ X countx = counto = 0; X for (i=0; i<4; i++) { X if (board[(row + i) % 4][(col + i) % 4] == X) countx++; X else if (board[(row + i) % 4][(col + i) % 4] == O) counto++; X } X if (type == X) { X if (countx >= 3) return (WIN); X if (!countx && (counto > rank)) rank = counto; X } else { X if (counto >= 3) return (WIN); X if (!counto && (countx > rank)) rank = countx; X } X X /* check / diagonal */ X countx = counto = 0; X for (i=0; i<4; i++) { X if (board[(row + 4 - i) % 4][(col + i) % 4] == X) countx++; X else if (board[(row + 4 - i) % 4][(col + i) % 4] == O) counto++; X } X if (type == X) { X if (countx >= 3) return (WIN); X if (!countx && (counto > rank)) rank = counto; X } else { X if (counto >= 3) return (WIN); X if (!counto && (countx > rank)) rank = countx; X } X X /* add one, so that even no blocks still shows as a valid move */ X /* and return the rank for this move */ X return (++rank); X} X X/* X checks for a win at a specific location, and returns the X type of win, or 0, if there wasn't a win. X*/ Xint check_win(type,row,col) Xint type, row, col; X{ X int r[4],c[4], i; /* temp row, col, and counter vars */ X X /* check across */ X if ((board [row][0] == type) && (board [row][1] == type) && X (board [row][2] == type) && (board [row][3] == type)) X return (type); X X /* check vertically */ X if ((board [0][col] == type) && (board [1][col] == type) && X (board [2][col] == type) && (board [3][col] == type)) X return (type); X X /* check \ diagonal */ X for (i=0; i<4; i++) { X r[i] = (row + i) % 4; X c[i] = (col + i) % 4; X } X if ((board [r[0]][c[0]] == type) && (board [r[1]][c[1]] == type) && X (board [r[2]][c[2]] == type) && (board [r[3]][c[3]] == type)) X return (type); X X /* check / diagonal */ X for (i=0; i<4; i++) { X r[i] = (row + i) % 4; X c[i] = (col + (4 - i)) % 4; X } X if ((board [r[0]][c[0]] == type) && (board [r[1]][c[1]] == type) && X (board [r[2]][c[2]] == type) && (board [r[3]][c[3]] == type)) X return (type); X X /* if it got here, there aren't any wins at that spot */ X return (0); X} X END_OF_FILE if test 6961 -ne `wc -c <'tttt.c'`; then echo shar: \"'tttt.c'\" unpacked with wrong size! fi # end of 'tttt.c' fi echo shar: End of archive 1 \(of 1\). cp /dev/null ark1isdone MISSING="" for I in 1 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have the archive. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0