Bueno, muchos por ahi no lo sepan pero me encanta programar y hoy vengo a traer el codigo para hacer nuestro propio Ta te ti en C, tambien puse los comentarios explicando paso por paso como se programa. Espero que sea de su agrado, vean mis otros post que hablan sobre C y C++ para ingenieros. Gracias por su tiempo

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define TRUE 1
#define FALSE 0
/**
* Para el tablero se escogió una representación un poco fuera de lo
* convencional, 2 enteros. La elección de ésta representación se debe
* pura y absolutamente a mi afán por querer aprender y ver la potencia
* que tiene el lenguaje c para el manejo de bajo nivel.
*
* Al ser números enteros, éstos guardan en dónde se encuentra la ficha
* en su representación binaria (a nivel de máquina).
* La razón de que sean 2 enteros es que con 1 sólo no alcanza para
* representar 3 estados (FICHA_USR, FICHA_PC o NADA) ya que sólo se
* puede mantener 2 representaciones (1 o 1). Entonces escogí usar 2
* enteros, 1 mantiene sólo las posiciones fichas que tiene el usuario y
* el otro las posiciones de las fichas de la pc.
* Para armar todo el tablero, es necesario ambos enteros y con un
* simple or a nivel de bit('|') se completa.
*
* A lo largo del código se ve el uso de los operadores a nivel de bit,
* por ejemplo para agregar una ficha al tablero se utiliza:
* tablero |= posicion
* para saber si una posición ya ha sido ocupada, se utiliza el &:
* (tablero_pc|tablero_usr)&posicion
*/
/* Primer fila */
#define F0C0 (0x1)
#define F0C1 (F0C0<<1)
#define F0C2 (F0C1<<1)
/* Segunda fila */
#define F1C0 (F0C2<<1)
#define F1C1 (F1C0<<1)
#define F1C2 (F1C1<<1)
/* Tercer fila */
#define F2C0 (F1C2<<1)
#define F2C1 (F2C0<<1)
#define F2C2 (F2C1<<1)
/* Dice si la posicion está ocupada en el tablero */
#define ocupada(pos, tablero) (pos&(tablero))
/* Cantidad de fichas que hay en el tablero */
#define cant_fichas(tablero)
((tablero)&F0C0?1:0)+((tablero)&F0C1?1:0)+((tablero)&F0C2?1:0)+
((tablero)&F1C0?1:0)+((tablero)&F1C1?1:0)+((tablero)&F1C2?1:0)+
((tablero&F2C0)?1:0)+((tablero)&F2C1?1:0)+((tablero)&F2C2?1:0)
/* Tablero vacío */
#define VACIO 0x00
/* Tablero con todas las fichas puestas */
#define COMPLETO (F0C0|F0C1|F0C2|F1C0|F1C1|F1C2|F2C0|F2C1|F2C2)
/* Dadas las coordenadas x e y, dice cuál es el número que lo representa
* en el tablero
*/
#define COORD2REPR(x,y) 0x1<<((x)*3 + (y))
#define foreach_celda(i) for(i = F0C0; i <= F2C2; i<<=1)
#define tateti_fila(tablero)
((tablero)&(F0C0|F0C1|F0C2))==(F0C0|F0C1|F0C2)||
((tablero)&(F1C0|F1C1|F1C2))==(F1C0|F1C1|F1C2)||
((tablero)&(F2C0|F2C1|F2C2))==(F2C0|F2C1|F2C2)
#define tateti_columna(tablero)
((tablero)&(F0C0|F1C0|F2C0))==(F0C0|F1C0|F2C0)||
((tablero)&(F0C1|F1C1|F2C1))==(F0C1|F1C1|F2C1)||
((tablero)&(F0C2|F1C2|F2C2))==(F0C2|F1C2|F2C2)
#define tateti_diagonal(tablero)
((tablero)&(F0C0|F1C1|F2C2))==(F0C0|F1C1|F2C2)||
((tablero)&(F0C2|F1C1|F2C0))==(F0C2|F1C1|F2C0)
#define tateti(tablero)
(tateti_fila((tablero)) ||
tateti_columna((tablero)) ||
tateti_diagonal((tablero)))
/***
* Macros útiles
*****************/
/* Vacía el buffer de entrada */
#define vaciar_buffer
int c;
do{
c = getc(stdin);
}while(c != 'n' && c != EOF)
#define print_bienvenida
printf("********************************************n"
" Bienvenido al juego de TATETI n"
"********************************************n";)
/*====================================================================*/
/* PROTOTIPOS DE FUNCIONES */
/*====================================================================*/
/** Funciones útilies **/
int get_int_input(char *msg);
int menu(int cant,char *title, char *opciones[]);
/** Interacción con usuario **/
int get_coordenadas();
/** IA **/
int seguro(int *tableros);
int donde_se_puede_tateti(int t1, int t2);
int get_coordenadas_ia(int tablero_user, int tablero_pc);
void jugar(int *tableros, short int quien_es_pc);
void print_tablero(int tablero_O, int tablero_X);
/*========================================================================*/
/**
* main:
********/
int main(int argc, char *argv[]){
int tablero[] = {VACIO, VACIO};
int opcion;
char *menu_principal[] = {"Comenzar nueva partida", "Salir"};
char *menu_patida_nueva[] =
{"Ceder turno", "Yo quiero empezar", "Volver al menu anterior"};
do{
print_bienvenida;
tablero[0] = tablero[1] = VACIO;
opcion = menu(2, "Principal", menu_principal);
switch(opcion){
case 1:
opcion = menu(3, "Nuevo Juego", menu_patida_nueva);
switch(opcion){
case 1:
jugar(tablero, 0);
break;
case 2:
jugar(tablero, 1);
break;
case 3:
break;
}
break;
case 2:
return 0;
}
}while(TRUE);
}
/*====================================================================*/
/* FUNCIONES ÚTILES */
/*====================================================================*/
/**
* get_int_input:
* Pide el ingreso de un entero
********************************/
int get_int_input(char *msg){
#define BUFF_LEN 6
#define LAST (BUFF_LEN - 1)
int i;
char opcion[BUFF_LEN];
int len;
char *aux;
int isNumber = FALSE;
/*****
* Iteramos hasta que ingrese un número válido
*/
do{
printf("%s: ", msg);
fgets(opcion, BUFF_LEN, stdin);
len = strlen(opcion);
if( len == (BUFF_LEN - 1) && opcion[LAST-1] != 'n'){
vaciar_buffer;
}
isNumber = TRUE; /* Asumimos que es un número */
for(aux = opcion; *aux; ++aux){
if(!isdigit(*aux) && *aux != '' && *aux != 'n'){
/* Si encontramos uno que no es número, terminamos el for */
isNumber = FALSE;
break;
}
}
if(isNumber){
i = atoi(opcion);
return i;
}
/* Borramos el último salto de linea (si lo tiene) para mejorar
* la forma de ver el mensaje */
opcion[len-1] = (opcion[len-1] == 'n')?'':opcion[len-1];
printf("%s no es una opción correcta, intenta de nuevo!n", opcion);
}while(TRUE); /* La única forma de salir del while es ingresando un número válido de opción */
}
/**
* menu:
* Imprime el menu y espera que el usuario ingrese una opción válida. Se
* queda dentro del bucle hasta que se ingrese una opción válida
* sus parámetros son:
* cant: la cantidad de opciones que se quiere mostrar, debe ser menor
* o igual al tamaño de arreglo de opciones.
* title: el título que se quiere mostrar para ese menú.
* opciones: un arreglo de strings que muestran la descripción de la
* opción.
***********************************************************************/
int menu(int cant,char *title, char *opciones[]){
int opcion;
int i;
printf("Menu %s:n", title);
/* Mostrar las opciones del menú */
for(i=0; i < cant; ++i){
printf("t%3d. %sn",(i+1), opciones[i]);
}
opcion = get_int_input("Tu opcion?";);
while(opcion <= 0 && opcion > cant){
/* Pedir el valor hasta que sea válido */
printf("%d no es una opcion válidan", opcion);
opcion = get_int_input("Tu opcion?";);
}
return opcion;
}
/*====================================================================*/
/* INTERACCION CON EL USUARIO */
/*====================================================================*/
/**
* get_coordenadas:
* Pide las coordenadas de dónde se quiere que se coloque la ficha
*/
int get_coordenadas(){
short int x, y;
do{
/* Pedir el valor de x hasta que se ingrese uno válido */
x = get_int_input("fila?";);
if(x < 3 && x >= 0){
break;
}
printf("Opcion incorrecta, intenta de nuevon";);
}while(TRUE);
do{
/* Pedir el valor de y hasta que se ingrese uno válido */
y = get_int_input("columna?";);
if(y < 3 && y >= 0){
break;
}
printf("Opcion incorrecta, intenta de nuevon";);
}while(TRUE);
return COORD2REPR(x,y);
}
/*====================================================================*/
/* INTELIGENCIA ARTIFICIA */
/*====================================================================*/
/**
* seguro:
* Devuelve verdadero si a partir de la disposición de los
* tableros pasados como parámetros, es posible llegar a un empate o que
* gane el jugador cuyo tablero es t2. En caso de que no sea factible
* retornará falso.
*/
int seguro(int *tableros){
short int i = 0;
int pos;
while((tableros[0]|tableros[1]) != COMPLETO){
/* Primero hay que ver si se puedo hacer tateti */
pos = donde_se_puede_tateti(tableros[i], tableros[1-i]);
if(pos != -1){
return i == 1; /* Seguro sólo si tablero 2
puedo hacer tateti */
}
/* Intentar parar el tateti del otro */
pos = donde_se_puede_tateti(tableros[1-i], tableros[i]);
if(pos == -1){
//return cant_fichas((t1|t2)) >= 6;
return cant_fichas((tableros[0]|tableros[1])) >= 6;
}
tableros[i] |= pos;
i = (i+1)%2;
}
return TRUE;
}
/**
* donde_se_puede_tateti:
* Devuelve dónde se puede hacer tateti...
* t1 es el tablero sobre el cual se quiere hacer tateti, y t2 sólo se
* usa para averiguar que esa posicion no esté ocupada por el jugador
* contrario
*/
int donde_se_puede_tateti(int t1, int t2){
int i;
foreach_celda(i){
if(!ocupada(i, t1|t2)){
if(tateti(t1|i)){
return i;
}
}
}
return -1;
}
/**
* get_coordenadas_ia:
* Pide las coordenadas para la pc
**********************************/
int get_coordenadas_ia(int tablero_user, int tablero_pc){
int pos;
print_tablero(tablero_user, tablero_pc);
if(tablero_pc == VACIO){
/* La pc aún no ha movido */
if(!ocupada(F1C1,tablero_pc|tablero_user)){
return F1C1; /* Ocupamos el centro si aún no se ha hecho */
}
/* El usuario si y ha ocupado la casilla del medio */
return F0C0;
}
/* Queremos saber si se puede hacer tateti en el tablero de la pc */
pos = donde_se_puede_tateti(tablero_pc, tablero_user);
if(pos != -1){
return pos;
}
/* Ahora si podemos detener al tateti del otro jugador */
pos = donde_se_puede_tateti(tablero_user, tablero_pc);
if(pos != -1){
return pos; /* Se ha encontrado una casilla en la cual el
* otro jugador puede llegar a hacer tatei */
}
int tableros[2];
foreach_celda(pos){
if(!ocupada(pos,tablero_pc|tablero_user)){
tableros[0] = tablero_user;
tableros[1] = tablero_pc | pos;
if(seguro(tableros)){
return pos; /* En éste posicion es seguro el
movimiento */
}
}
}
print_tablero(tableros[0], tableros[1]);
/* Nunca debería suceder ésto */
printf("***Fatal error!n"
"No se encuentra una jugada factible para que la PC gane, fin del juegon";);
exit(-1);
}
/*====================================================================*/
/* JUEGO */
/*====================================================================*/
/**
* jugar:
* Es el juego en si, se juega turnandose los jugadores de a 1 por vez,
* los parámetros son los tableros que manejan ambos jugadores y un
* parámetro adicional que indica cuál de los tableros pertenece a la PC
************************************************************************/
void jugar(int *tableros, short int quien_es_pc){
short int i=-1;
int casilla;
do{
i = (i + 1) % 2;
if(i != quien_es_pc){
/* Mostrar el tablero sólo cuando juega el usuario */
print_tablero(tableros[1-quien_es_pc], tableros[quien_es_pc]);
/* Pedimos las coordenadas de dónde quiere colocar su ficha */
casilla = get_coordenadas();
while(ocupada(casilla, tableros[0]|tableros[1])){
/* Hata que no ingrese una casilla desocupada no salimos */
printf("Has ingresado una casilla ocupadan";);
casilla = get_coordenadas();
}
}else{
/* Sólo vemos dónde pone la ficha la IA */
casilla = get_coordenadas_ia(tableros[1-quien_es_pc], tableros[quien_es_pc]);
if(ocupada(casilla, tableros[0]|tableros[1])){
/* Si el que puso la ficha en un lugar ocupado es la pc
* es un error fatal ya que siempre retornará el mismo
* valor y nunca se podrá seguir con el juego
*/
printf("***Fatal error!:n"
"la pc intenta ingresar en una casilla ya ocupadan";);
exit(-1);
}
}
tableros[i] |= casilla; /* Poner la ficha en la casilla */
}while(!tateti(tableros[i]) && (tableros[0]|tableros[1]) != COMPLETO);
/* Imprimimos el tablero final */
print_tablero(tableros[1-quien_es_pc], tableros[quien_es_pc]);
if(tateti(tableros[0]) || tateti(tableros[1])){
/* El ganador es el último que puso la ficha, es decir el valor
* de i */
printf("nn^^^^^^^^Ha ganado el jugador %s^^^^^^^^nn",
(quien_es_pc==i)?"PC":"HUMANO";);
}else{
printf("nn^^^^^^^^Ha ocurrido un EMPATE^^^^^^^^nn";);
}
}
/**
* Imprime el tablero en pantalla en una representación agradable para
* el usuario humano
*/
void print_tablero(int tablero_O, int tablero_X){
printf("nn*************n"
"* %c | %c | %c *n"
"*-----------*n"
"* %c | %c | %c *n"
"*-----------*n"
"* %c | %c | %c *n"
"*************n",
((tablero_O&F0C0)?'O':(tablero_X&F0C0)?'X':' '),
((tablero_O&F0C1)?'O':(tablero_X&F0C1)?'X':' '),
((tablero_O&F0C2)?'O':(tablero_X&F0C2)?'X':' '),
((tablero_O&F1C0)?'O':(tablero_X&F1C0)?'X':' '),
((tablero_O&F1C1)?'O':(tablero_X&F1C1)?'X':' '),
((tablero_O&F1C2)?'O':(tablero_X&F1C2)?'X':' '),
((tablero_O&F2C0)?'O':(tablero_X&F2C0)?'X':' '),
((tablero_O&F2C1)?'O':(tablero_X&F2C1)?'X':' '),
((tablero_O&F2C2)?'O':(tablero_X&F2C2)?'X':' ')
);
}[/i][/i][/i][/i][/i][/i]
