/* * 3D Tic Tac Toe. * * Original Author Unknown * * Compile command: cc ttt3d -fop */ #include #define EMPTY 0 #define PLAYER 1 #define BEAST 5 /* * This is a table of all winning combinations. * From Kilobaud, April 78. * You can look there to see how it is ordered. */ char w[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15, 0, 5, 10, 15, 3, 6, 9, 12, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 16, 20, 24, 28, 17, 21, 25, 29, 18, 22, 26, 30, 19, 23, 27, 31, 16, 21, 26, 31, 19, 22, 25, 28, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 32, 36, 40, 44, 33, 37, 41, 45, 34, 38, 42, 46, 35, 39, 43, 47, 32, 37, 42, 47, 35, 38, 41, 44, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 48, 52, 56, 60, 49, 53, 57, 61, 50, 54, 58, 62, 51, 55, 59, 63, 48, 53, 58, 63, 51, 54, 57, 60, 0, 16, 32, 48, 1, 17, 33, 49, 2, 18, 34, 50, 3, 19, 35, 51, 4, 20, 36, 52, 5, 21, 37, 53, 6, 22, 38, 54, 7, 23, 39, 55, 8, 24, 40, 56, 9, 25, 41, 57, 10, 26, 42, 58, 11, 27, 43, 59, 13, 29, 45, 61, 12, 28, 44, 60, 14, 30, 46, 62, 15, 31, 47, 63, 0, 21, 42, 63, 4, 21, 38, 55, 8, 25, 42, 59, 12, 25, 38, 51, 1, 21, 41, 61, 13, 25, 37, 49, 2, 22, 42, 62, 14, 26, 38, 50, 3, 22, 41, 60, 7, 22, 37, 52, 11, 26, 41, 56, 15, 26, 37, 48, 0, 20, 40, 60, 0, 17, 34, 51, 3, 18, 33, 48, 3, 23, 43, 63, 12, 24, 36, 48, 12, 29, 46, 63, 15, 30, 45, 60, 15, 27, 39, 51 }; /* * This is the board. * Starts off all empty. */ char b[64] = 0; char sep[] = " ----------- ----------- ----------- -----------\n"; /* * The mainline is just a driver. */ main() { char buf[20]; printf("Do you want the rules? "); fgets(buf, 20, stdin); if(buf[0]=='Y' || buf[0]=='y') rules(); printf("Do you want to go first? "); fgets(buf,20,stdin); if(buf[0]=='Y' || buf[0]=='y') user(); for(;;) { beast(); user(); } } /* * Print the rules of the game. */ rules() { printf("Three dimensional tic-tac-toe is played on a 4x4x4\n"); printf("board. To win you must get 4 in a row. Your moves\n"); printf("are specified as a 3 digit number; the first digit\n"); printf("is the level, the second the row and the third the\n"); printf("column. Levels and columns go from left to right\n"); printf("from 1 to 3. Rows go from top to bottom with 0 on\n"); printf("the top.\n"); } /* * Accept a user move. Exit if he wins. */ user() { register int i, j, t; char buf[20]; board(); for(;;) { printf("Your move (L/R/C)? "); if(!fgets(buf,20,stdin)) { printf("Chicken.\n"); exit(0); } i = 16*(buf[0]-'1') + (buf[1]-'1') + 4*(buf[2]-'1'); if(i>=0 && i<=63 && b[i]==EMPTY) break; printf("Eh?\n"); } b[i] = PLAYER; for(i=0; i<4*76; i+=4) { t = 0; for(j=0; j<4; ++j) t += b[w[i+j]]; if(t == 4*PLAYER) { printf("You win.\n"); exit(0); } } } /* * Display the board. (Not as easy as it sounds) */ board() { register int i, j; for(i=1; i < 5; ++i) printf(" %d ", i); printf("\n"); for(i=0; i<4; ++i) { printf(sep); printf("%d ", i+1); for(j=0; j<64; j+=4) { psq(i+j); if(j==12 || j==28 || j==44) printf(" "); else if(j >= 60) putc('\n', stdout); else putc('!', stdout); } } printf(sep); for(i=0; i < 4; ++i) { for(j=1; j < 5; ++j) printf(" %d", j); printf(" "); } printf("\n"); } /* * Format and put out square `s' of the board. */ psq(s) int s; { register int v; v = b[s]; if(v == PLAYER) printf("PP"); else if(v == BEAST) printf("CC"); else printf(" "); } /* * Move for the machine. Just exit on machine wins and draws. */ beast() { register int i, j, t; int s, bs, bt, v[76]; for(i=0; i<4*76; i+=4) { t = 0; for(j=0; j<4; ++j) t += b[w[i+j]]; v[i>>2] = t; if(t == 3*BEAST) break; } if(i < 4*76) { for(j=0; j<4; ++j) if(b[w[i+j]] == EMPTY) { b[w[i+j]] = BEAST; break; } board(); printf("I win.\n"); exit(0); } bt = 0; for(s=0; s<64; ++s) { if(b[s] != EMPTY) continue; t = 0; for(i=0; i<4*76; i+=4) { for(j=0; j<4; ++j) if(w[i+j] == s) break; if(j != 4) { if(v[i>>2] == 3*PLAYER) { b[s] = BEAST; return; } t += weight(v[i>>2]); } } if(t > bt) { bt = t; bs = s; } } if(bt != 0) b[bs] = BEAST; else { for(s=0; s<64; ++s) if(b[s] == EMPTY) break; if(s == 64) { printf("Draw.\n"); exit(0); } b[s] = BEAST; } } /* * Given a total along a winning combination, return the weight value. */ weight(at) int at; { register int t; t = at; if(t == PLAYER) return(1); if(t == 2*PLAYER) return(4); if(t == BEAST) return(1); if(t == 2*BEAST) return(2); return(0); }