Site hosted by Angelfire.com: Build your free website today!
« October 2012 »
S M T W T F S
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31
Entries by Topic
All topics  «
Blog Tools
Edit your Blog
Build a Blog
RSS Feed
View Profile
You are not logged in. Log in
Curso de programación
Wednesday, 17 October 2012

|||||||||||||||||||||||||||||

|||||||||||||||||||||||||||||


CURSO DE PROGRAMACIÓN C++


|||||||||||||||||||||||||||||

|||||||||||||||||||||||||||||



PRESENTACIÓN


El siguiente texto es un curso de C++.


Este programa ha sido desde hace poco más de 15 años la herramienta de programación más poderosa desde la creación de la PC. Con ella se han escrito los más famosos e importantes programas.


En el medio de la programación se dice que gran parte del Windows (o todo el Windows) de 16 bits se escribió con C++. UNIX y LINUX son otros casos. NOI, CAE, SAE son otros programas que han sido escritos con él. La lista de programas construídos con C++ parece no tener fin.


El estilo de programación por clases, objetos, la herencia y el polimorfismo están llevando a producir programas realmente grandes (100000 líneas o más), con gran eficiencia y claridad.


Son temas fundamentales en programación que deben abordarse desde los cursos iniciales. Sin embargo por un motivo pedagógico aquí hemos preferido seguir la recomendación de aportar los elementos completos del lenguaje C antes de iniciar al estudiante con el C++. Sin embargo es tarea del profesor, la escuela o del autodidacta decidir cuándo comenzar con objetos y clases y otros temas propios del C++.


Aquí se aborda el tema de las clases a través de un programa que ya ha sido estudiado en secciones anteriores: el juego del gato. Se agrega una página inicial de instrucciones y ello da pié para estructurar dos entornos de los que nacen dos objetos cuyas clases se definen.


El objeto surge como una necesidad de regulación de los límites de los entornos proporcionando con ello una mejor administración de recursos de memoria. Sin embargo va más allá al proporcionar medios para la aparición del polimorfismo, proceso que también se conoce con la frase: "mismo nombre nuchos métodos", con lo que el lenguaje computacional puede crecer sin límites en el camino de la expresión no gramatical sino más bien expresiva (y esto último se acerca más bien a la poesía).


A todos los estudiantes que se acerquen a este curso les agradezco su atención y les pido que envíen cualquier duda o comentario al teléfono o al email que se indica. Asimismo, si existe algún error agradeceré que me lo hagan saber.


Jorge Manuel Paz Morelos. México D.F., mayo, 2003.

|||||||||||||||||||||||||||||


ÍNDICE C++


|||||||||||||||||||||||||||||



PRESENTACIÓN


ÍNDICE TEMÁTICO DEL DICCIONARIO

ÍNDICE ALFABÉTICO DEL DICCIONARIO

ÍNDICE DE EJEMPLOS

EJEMPLOS EN EL CURSO

SECCIÓN DE EJEMPLOS DIVERSOS

EJEMPLOS EN EL DICCIONARIO


PROGRAMACIÓN EN C++.

INTRODUCCIÓN.

C++ Y LA PROGRAMACIÓN POR OBJETOS

DIFERENCIAS ENTRE C Y C++

ELEMENTOS INICIALES

cin Y cout

COMENTARIOS CON //

LAS PALABRAS PROPIAS DEL C++

LAS CLASES

CONSTRUCTORES Y DESTRUCTORES

REPASO: VERSIÓN CLASE DEL JUEGO DE GATO

CÓDIGOS DEL JUEGO DE GATO

POLIMORFISMO

SOBRECARGAR UN NOMBRE

HERENCIA

EL JUEGO DEL GATO POLIMÓRFICO

CÓDIGOS DEL GATO POLIMÓRFICO

SOBRECARGA DE OPERADORES

DIFERENCIAS EN LA SOBRECARGA DE OPERADORES. PALABRA this

SUMA DE VECTORES EN 3 DIMENSIONES

CÓDIGOS DEL PROGRAMA DE SUMA DE VECTORES

SOBRECARGA DE UNARIO: REPETICIÓN DE UN PATRÓN

EN 3A. DIMENSIÓN

CÓDIGOS DEL PROGRAMA DE REPETICIÓN DE PATRÓN


Para consultar el índice temático o alfabético, abrir la sección correspondiente al curso de programación C, y Turbo C.

|||||||||||||||||||||||||||||


ÍNDICE DE EJEMPLOS


|||||||||||||||||||||||||||||



A continuación se presenta el índice de ejemplos.


En esta parte del curso, los ejemplos que tienen un ejecutable disponible están acompañados del nombre del archivo que puede verse en el directorio ejemclas.


Todos estos ejemplos pueden correrse haciendo click en "corr". Los ejemplos que por ser fragmentos de programa o que no tienen ejecutable disponible no pueden correrse.

Ò

EJEMPLOS EN EL CURSO


GATOCLAS.CPP El juego del gato

GATCLAS2.CPP El juego del gato polimórfico

OPERAT00.CPP Suma de vectores

OPERAT01.CPP Repetición de patrón de 3a. dimensión

|||||||||||||||||||||||||||||


PROGRAMACIÓN EN C++


|||||||||||||||||||||||||||||



INTRODUCCIÓN


El C++ fué creado a partir del C. Con el C ha sido desarrollado el software más importante y es la herramienta más poderosa de programación.


Después de varias revisiones Bjarne Stroustrup que trabajaba en los Laboratorios Bell desde 1980 desarrolló el C++. Bjarne Stroustrup, ha dicho que algunos razgos de la programación orientada a objetos fueron inspiradas por otro lenguaje, el Simula67. Otro lenguaje de programación que sirvió de modelo fué el ALGOL68.


El C++ representa la unión de cuatro métodos poderosos de programación: Las clases, los objetos, el polimorfismo y la herencia entre objetos.


Ahora iniciaremos el estudio del C++. Aunque no es una condición necesaria, sí es una recomendación conocer lenguajes de programación con cierta soltura para abordar el tema de la programación por objetos, las clases, la herencia y el polimorfismo.


En realidad estos cuatro conceptos son sencillos de entender. Simplificando los conceptos para verlos en conjunto puede decirse lo siguiente:


Los objetos permiten manejar el "scope" o campo de acción de los elementos del programa, las clases son un medio de que se vale el lenguaje para lograr lo anterior. La herencia permite "pasar" o "heredar" las propiedades entre objetos y el polimorfismo es una ampliación de la gramática del lenguaje que nos permite "redefinir" métodos y operaciones para que realicen acciones distintas a las que tenían originalmente.


El polimorfismo permite que varios métodos compartan el mismo nombre y las formas necesarias (explícitas o implícitas) para que el compilador reconozca cuál de los métodos es aplicable en cada caso.



C++ Y LA PROGRAMACIÓN POR OBJETOS


De dónde nace la programación por objetos?. La programación de clases y objetos nace de la necesidad de agrupar variables, tipos, funciones y estructuras en "tipos o clases" de tal forma que los recursos pueden manipularse de una manera integral. Lograremos entender estos conceptos a su tiempo comparando lo que hasta ahora hemos logrado con el lenguaje y lo puede hacerse con el lenguaje desde esta perspectiva.



DIFERENCIAS ENTRE C Y C++


Cualquier programa C es un programa C++. Salvo algunas pequeños ajustes es posible correr cualquier programa de C en C++. Las diferencias más importantes son las siguientes:


1. Declarar parámetros void es opcional en C++. Por ejemplo las siguientes declaraciones son equivalentes en C++ (en C no lo son pues en la primera aún podemos agregar parámetros posteriormente):


int func();

int func(void);


2. En C++ todas las funciones deben tener prototipo.



ELEMENTOS INICIALES


Empecemos con algunas instrucciones como cin y cout, un método eficiente de comentarios y las definiciones básicas.

Ò

cin Y cout


Las instrucciones cin y cout se utilizan para recibir datos y escribir. Aunque no reemplazan a scanf y printf que todavía se utilizan, son más flexibles que éstas.


Ejemplos:


cout << "Esto se escribe\n";

cout << "El valor de la variable func es " << func;


Cada vez que se desee utilizar estas instrucciones deberá incluirse el archivo iostream.h así:


#include <iostream.h>



COMENTARIOS CON //


Lo que sigue a los caracteres // es comentario hasta el final de la línea. No hace falta terminar la línea con punto y coma.


Ejemplo


cout << "Esto se escribe\n"; // AHORA EMPIEZA EL COMENTARIO



LAS PALABRAS PROPIAS DEL C++


Además de las palabras del C y del Turbo C, el C++ utiliza las siguientes:


asm Instrucción en lenguaje ensamblador

catch Atrapa excepción

class Declara la clase de un objeto

delete Libera memoria

friend Permite que un elemento no miembro tenga acceso a

elementos privados

inline Produce código en línea (especie de macro en línea)

new Accesa memoria

operator Sobrecarga un nuevo uso para algún operador

(redefine un nuevo uso para el operador)

private Declara un elemento privado dentro de una clase

protected Declara un elemento protegido dentro de una clase

public Declara un elemento público dentro de una clase

this Apunta al objeto de la clase en la clase

virtual Evita que las funciones se repitan en las clases herederas

template Crea un molde (semejante a una "macro de expansión")



EL OPERADOR ::


Este operador nos sirve para para presentar el cuerpo de una función que pertenece a una clase.


En el siguiente ejemplo, se presenta el cuerpo de la función CHECA que pertenece a la clase jugar:


int jugar::CHECA(void){ ... }


En el siguiente ejemplo, se presenta el cuerpo del constructor de la clase jugar (se verá qué es un

constructor un poco después):


jugar::jugar(void){ ... }



LAS CLASES. public, private, friend, protected, virtual, this


Las clases son un método gramatical de crear accesos y herencias entre objetos. Los datos,

funciones y estructuras pueden ser declarados como privados, públicos, amigos o reservados y la

forma en que pueden ser accesados por otros objetos depende de dichas declaraciones.


Usamos la palabra class para declarar la clase. Usamos las palabras private, public, protected y friend para modificar los accesos y campos de acción de las variables.


Las modificaciones que realizan son las siguientes:


private Los elementos que siguen son privados dentro de una clase.

Su nombre solo puede ser utilizado por funciones miembro y

amigas de la clase en la que se declara.

public Los elementos que siguen son públicos dentro de una clase, es

decir pueden ser accesados desde cualquier parte del código.

Su nombre puede ser utilizado por cualquier función.

protected Los elementos que siguen podrán ser accesados por alguna

clase friend pero serán inaccesibles para otras clases, es

decir, serán tomados como private por el resto del código.

Su nombre sólo puede ser utilizado por funciones miembro y

amigas de la clase en la que se declara y por funciones

miembro y amigas de clases derivadas de esta clase.

friend Permite que un elemento no miembro de la clase tenga

acceso a elementos private y protected. Una función

friend de una clase es una función que no es miembro de

la clase pero que tiene permiso de utilizar los nombres de

miembros privados y protegidos de esa clase. El nombre

de una "amiga" no está dentro del alcance de la clase y no

es llamada con los operadores de acceso a miembros, a

menos que sea miembro de otra clase.


Otras palabras que se usan son las siguientes:


virtual Evita que la copia "offset" de funciones se repitan en las

clases derivadas. Cuando una clase se deriva de otra,

se realiza una copia de cada uno de sus elementos. Esta

palabra evita que dicha copia se realice.

this Usamos la palabra para referirnos al objeto de la clase dentro

de la misma clase. Es un puntero que apunta al objeto de la

clase en la clase.


Sintácticamente una clase es una estructura. Sin embargo en una estructura por omisión todos

los elementos son accesados sin restricción alguna, es decir son de uso público.


Por ejemplo en la siguiente estructura:


struct hierro {

int precio;

char proveedor[80];

private:

destino[120];

} ;


los elementos precio y proovedor son públicos y destino se hace privado.


En una clase es a la inversa. Por ejemplo:


class jugar {

unsigned int nivel;

int scoreJugador, scoreComputadora;

public:

int GANADOR(int jugador);

void CUADROS(void);

};


Los elementos son privados por omisión y se hace públicos mediante la palabra public.


Esto significa que dichos elementos solo pueden ser utilizados por miembros de la misma

clase. Esta restricción es muy útil pues nos permite "limitar" el campo de acción de los

elementos. En secciones anteriores del curso se dijo que las variables globales consumen mucha

memoria. Pues bien, la definición de objetos nos permite delimitar los campos de acción de los

miembros de bloques y así reservar memoria.



CONSTRUCTORES Y DESTRUCTORES


Los miembros de una clase pueden ser de diversos tipos. Una clase especial de miembros son los constructores y los destructores.


Los primeros inicializan a la clase. El uso que generalmente tienen es para inicializar los elementos de la clase pues en la declaración de clase no se permiten inicializaciones.


Los segundos cierran el objeto. Por lo general no hacen más que eso, pero en cada caso depende del programa.


Para nombrar constructores y destructores se utiliza el mismo nombre de la clase. Por ejemplo en la clase jugar del ejemplo que veremos el constructor y el destructor son declarados así:


clase jugar {

...

public:

...

jugar(void);

~jugar(void);

}


y el cuerpo de los mismos son de la siguiente forma:


jugar::jugar(void){ ... }

jugar::~jugar(void){ ... };



VERSIÓN CLASE DEL JUEGO DE GATO


Hemos visto el juego del gato en sus diversas facetas en una versión "sin clases ni objetos". Ahora estudiemos una versión con los elementos que hasta ahora han sido aportados.


Las palabras que veremos son clase y public. Utilizaremos además el concepto de inicialización a través del constructor y utilizaremos los operadores ::, . (punto) y ~ (tilde).


Utilizaremos el teclado numérico para realizar las jugadas. Vamos a utilizar una pantalla inicial que lleve a cabo estas instrucciones.


El problema con el que nos enfrentamos es el siguiente:


1. En primer lugar tenemos que crear una función que presente las instrucciones iniciales (que se ha de emplear el teclado numérico en este caso). Esta función no empleará ninguna de las variables del juego y será "similar en su uso" a la función CUADROS que ya conocemos.


2. Por otro lado tenemos una serie de funciones, y aunque cada una de ellas no utiliza todas las variables en todo momento, están entrelazadas entre sí pues se realizan llamados entre ellas. Dichas funciones son las siguientes:


int GANADOR(int jugador);

void CUADROS(void);

int JUEGO1(void);

int CHECA(void);


Las variables de uso común son las siguientes:


char lugar[9];

unsigned int partida;

int sil;

int scoreJugador, scoreComputadora;


Definiremos el campo de acción de estos dos "entornos" por medio de la creación de dos "objetos". Para ello empleamos la palabra class y ya que el primer entorno está relacionado con la idea del inicio y el segundo entorno con el juego mismo usaremos las siguientes instrucciones:


class inicio { ... }

class jugar { ... }


Las variables de uso común de la clase jugar serán para nuestra comodidad privadas de los miembros de esa clase.


Según el principio del polimorfismo que dice "mismo nombre diversos procedimientos", en la clase inicio crearemos una función que utilizará el mismo nombre de la función CUADROS de la clase jugar. En este caso debemos poner el "apellido" correcto.


Para llevar esto a cabo declararemos "EN EL ENTORNO DEL MAIN" el "apellido juego" del tipo de la clase jugar, y el "apellido iniciemos" del tipo de clase inicio. Lo anterior se encuentra en el main así:


void main(void){

jugar juego;

inicio iniciemos;


Una vez heho esto podemos utilizar el "apellido" correspondiente para cada una de las funciones CUADROS que habremos definido:


...

iniciemos.CUADROS();

...

juego.CUADROS();

...


Veamos un poco acerca de la sintaxis de la declaración de clase jugar que contiene a los miembros involucrados con el juego. Por omisión los miembros de una clase son privados, así que los públicos tienen que declararse como tal con la palabra public.


En este caso privados son las variables y arreglo: nivel, lugar[], partida, sil, scoreJugador y scoreComputadora. Públicas son las funciones GANADOR, CUADROS, JUEGO1 y CHECA. Se agrega el constructor de jugar (jugar(void)) que en la práctica realiza la inicialización de las variables pues en la declaración de clase en C++ no se pueden inicializar variables; y se agrega también su destructor respectivo (~jugar(void)).


class jugar {

unsigned int nivel;

char lugar[9];

unsigned int partida;

int sil;

int scoreJugador, scoreComputadora;

public:

int GANADOR(int jugador);

void CUADROS(void);

int JUEGO1(void);

int CHECA(void);

jugar(void);

~jugar(void);

};


Veamos ahora la sintaxis de la clase inicio, que como quedó establecido tendrá como miembro una función con el nombre CUADROS y que no tiene elementos privados, pues no los necesita:


class inicio {

public:

void CUADROS(void);

};


Una vez hechas las declaraciones de clase pueden presentarse los cuerpos de las funciones que se han declarado miembros de alguna clase y otras funciones que tuvieran carácter de global (que en este ejemplo no existen). Para ello se utiliza el operador ::.


Los constructores y destructores siempre utilizan el mismo nombre de la clase. Generalmente los constructores se utilizan para inicializar miembros y los destructores (en cuya declaración simplemente se utiliza el caracter ~) solo destruyen. Observemos que la declaración de la variable r se realiza fuera del inicio del cuerpo (esto no es posible en C o en

Turbo C) El cuerpo del constructor de juego es el siguiente:


jugar::jugar(void){

nivel=0;

partida=1;

sil=0;

scoreJugador=0; scoreComputadora=0;

register int r;

for(r=0;r<9;r++) lugar[r]=' ';

};


El cuerpo del destructor es el siguiente:


jugar::~jugar(void){

cout << "bye bye jugar ...";

getch();

};


Los cuerpos de las demás funciones se presentan de la siguiente forma:


int jugar::CHECA(void){ ... }

int jugar::JUEGO1(void){ ... }

int jugar::GANADOR(int jugador){ ... }

void jugar::CUADROS(void){ ... }

void inicio::CUADROS(void){ ... }


Notemos la presencia de los dos cuerpos de funciones CUADROS, la primera de jugar y la segunda de inicio.



CÓDIGOS DEL JUEGO DE GATO


El código del programa se encuentra en el archivo GATOCLAS.CPP y es el siguiente:


/*====================================

CÓDIGO DEL JUEGO DEL GATO EN OBJETOS */


#include <iostream.h>

#include <conio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include "c:\cursoc\mouse.c"

#include "c:\sisc\sonido.c"


/*====================================

CLASES */


// DECLARACIONES DE jugar


class jugar {


// VARIABLES PRIVADAS DE LA CLASE jugar


unsigned int nivel;

char lugar[9];

unsigned int partida;

int sil;

int scoreJugador, scoreComputadora;


public:


// MIEMBROS DE LA CLASE jugar


int GANADOR(int jugador);

void CUADROS(void);

int JUEGO1(void);

int CHECA(void);

jugar(void);

~jugar(void);

};


class inicio {

public:

void CUADROS(void);

};


/*====================================

MIEMBROS */


// CONSTRUCTOR QUE INICIA VARIABLES DE jugar


jugar::jugar(void){

nivel=0;

partida=1;

sil=0;

scoreJugador=0; scoreComputadora=0;

register int r;

for(r=0;r<9;r++) lugar[r]=' ';

};


// DESTRUCTOR DE jugar.(LOS DESTRUCTORES GENERALMENTE SOLO DESTRUYEN)


jugar::~jugar(void){

cout << "bye bye jugar ...";

getch();

};


/*===================================================

MIEMBROS DE LA CLASE JUGAR:

REVISA GANADORES */


int jugar::CHECA(void){int ix, iy;


for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)


{


if(lugar[0+3*(iy+1)]==lugar[1+3*(iy+1)] &&

lugar[1+3*(iy+1)]==lugar[2+3*(iy+1)] &&

lugar[2+3*(iy+1)]=='x')

return(1);


if(lugar[ix+1+3*(0)]==lugar[ix+1+3*(1)] &&

lugar[ix+1+3*(1)]==lugar[ix+1+3*(2)] &&

lugar[ix+1+3*(2)]=='x')

return(1);


if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[2+3*(2)]=='x')

return(1);


if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(0)] &&

lugar[2+3*(0)]=='x')

return(1);


if(lugar[0+3*(iy+1)]==lugar[1+3*(iy+1)] &&

lugar[1+3*(iy+1)]==lugar[2+3*(iy+1)] &&

lugar[2+3*(iy+1)]=='o')

return(2);


if(lugar[ix+1+3*(0)]==lugar[ix+1+3*(1)] &&

lugar[ix+1+3*(1)]==lugar[ix+1+3*(2)] &&

lugar[ix+1+3*(2)]=='o')

return(2);


if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[2+3*(2)]=='o')

return(2);


if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(0)] &&

lugar[2+3*(0)]=='o')

return(2);


}


return(0);

}



/*===================================================

SUBRUTINA DEL JUEGO */


int jugar::JUEGO1(void){int j=0,r; char c=0;


inicioj:


for(r=0;r<9;r++) lugar[r]=' ';


do{int ix,iy,cx,cy;


otrotiro:


for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

{


if(kbhit()|| (j==0&&partida==2))


{

c=getch();

if(c==27) goto evaluar;

if(c=='7'){iy=-1;ix=-1;}

if(c=='8'){iy=-1;ix= 0;}

if(c=='9'){iy=-1;ix= 1;}

if(c=='4'){iy= 0;ix=-1;}

if(c=='5'){iy= 0;ix= 0;}

if(c=='6'){iy= 0;ix= 1;}

if(c=='1'){iy= 1;ix=-1;}

if(c=='2'){iy= 1;ix= 0;}

if(c=='3'){iy= 1;ix= 1;}


if(!sil) silbo(50);

if( (j>0 && partida==2) || partida==1 )


{


if(lugar[ix+1+3*(iy+1)]=='x' || lugar[ix+1+3*(iy+1)]=='o')

{ if(!sil) silbo(50); goto otrotiro; }


else

{lugar[ix+1+3*(iy+1)]='x'; j++;

setcolor(10);

settextstyle(DEFAULT_FONT,HORIZ_DIR,3);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2+50*ix,getmaxy()/2+50*iy,"x");


if(CHECA()) return(CHECA());


}


}


if(j<=8)


{int b,fx,fy,esq;


j++;


randomize();



/* si el nivel es 0 y es la primer jugada responde al centro */



if(j==1 && nivel==0)

{cx=0;cy=0;goto respuesta;}



/* responde al centro cuando primer jugada fué al extremo */


if(j==2 && lugar[4]==' ')

{cx=0;cy=0;goto respuesta;}



/* DOS IGUALES 'o' */


/*diag ab*/

if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[2+3*(2)]==' ' && lugar[1+3*(1)]=='o' )

{cx=1; cy=1;goto respuesta;}


if(lugar[0+3*(0)]==lugar[2+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[2+3*(2)]=='o' )

{cx=0; cy=0;goto respuesta;}


if(lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[0+3*(0)]==' ' && lugar[2+3*(2)]=='o' )

{cx=-1;cy=-1;goto respuesta;}


/*diag ar*/

if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[2+3*(0)]==' ' && lugar[1+3*(1)]=='o' )

{cx=1;cy=-1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[1+3*(1)] &&

lugar[0+3*(2)]==' ' && lugar[1+3*(1)]=='o' )

{cx=-1;cy=1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[0+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[0+3*(2)]=='o' )

{cx=0; cy=0;goto respuesta;}


/*horiz*/


for(fy=-1;fy<=1;fy++){

if(lugar[0+3*(fy+1)]==lugar[1+3*(fy+1)] &&

lugar[2+3*(fy+1)]==' ' && lugar[1+3*(fy+1)]=='o')

{cx=1; cy=fy;goto respuesta;}


if(lugar[1+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[0+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='o')

{cx=-1;cy=fy;goto respuesta;}


if(lugar[0+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[1+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='o')

{cx=0; cy=fy;goto respuesta;}

}


/*vert*/


for(fx=-1;fx<=1;fx++){

if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(1)] &&

lugar[fx+1+3*(2)]==' ' && lugar[fx+1+3*(1)]=='o')

{cx=fx;cy=1;goto respuesta;}


if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(1)]==' ' && lugar[fx+1+3*(2)]=='o')

{cx=fx;cy=0;goto respuesta;}


if(lugar[fx+1+3*(1)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(0)]==' ' && lugar[fx+1+3*(2)]=='o')

{cx=fx;cy=-1;goto respuesta;}

}



/* DOS IGUALES 'x' */


/*diag ab*/

if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[2+3*(2)]==' ' && lugar[1+3*(1)]=='x' )

{cx=1; cy=1;goto respuesta;}


if(lugar[0+3*(0)]==lugar[2+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[2+3*(2)]=='x' )

{cx=0; cy=0;goto respuesta;}


if(lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[0+3*(0)]==' ' && lugar[2+3*(2)]=='x' )

{cx=-1;cy=-1;goto respuesta;}


/*diag ar*/

if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[2+3*(0)]==' ' && lugar[1+3*(1)]=='x' )

{cx=1;cy=-1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[1+3*(1)] &&

lugar[0+3*(2)]==' ' && lugar[1+3*(1)]=='x' )

{cx=-1;cy=1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[0+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[0+3*(2)]=='x' )

{cx=0; cy=0;goto respuesta;}


/*horiz*/


for(fy=-1;fy<=1;fy++){

if(lugar[0+3*(fy+1)]==lugar[1+3*(fy+1)] &&

lugar[2+3*(fy+1)]==' ' && lugar[1+3*(fy+1)]=='x')

{cx=1; cy=fy;goto respuesta;}


if(lugar[1+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[0+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='x')

{cx=-1;cy=fy;goto respuesta;}


if(lugar[0+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[1+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='x')

{cx=0; cy=fy;goto respuesta;}

}


/*vert*/


for(fx=-1;fx<=1;fx++){

if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(1)] &&

lugar[fx+1+3*(2)]==' ' && lugar[fx+1+3*(1)]=='x')

{cx=fx;cy=1;goto respuesta;}


if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(1)]==' ' && lugar[fx+1+3*(2)]=='x')

{cx=fx;cy=0;goto respuesta;}


if(lugar[fx+1+3*(1)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(0)]==' ' && lugar[fx+1+3*(2)]=='x')

{cx=fx;cy=-1;goto respuesta;}

}


/* PRIORIDAD EN LAS ESQUINAS */


randomize();

do


{


cy=random(3)-1;cx=random(3)-1;}

while(lugar[cx+1+3*(cy+1)]=='o' ||

lugar[cx+1+3*(cy+1)]=='x' );


respuesta: lugar[cx+1+3*(cy+1)]='o';


setcolor(12);

settextstyle(DEFAULT_FONT,HORIZ_DIR,3);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2+50*cx,getmaxy()/2+50*cy,"o");


if(CHECA()) return(CHECA());


}


if(CHECA()) return(CHECA());


}


}


evaluar:


if(c)

{ if(c==27) exit(0);

if(c==(int)'n') sil=1;

if(c==(int)'s') sil=0;

c=0;

}


} while(j<9);


return -1;


}




/*===================================================

GANADOR Y CONTINUACIÓN */


int jugar::GANADOR(int jugador)


{int ix;


setfillstyle(SOLID_FILL,3);

bar(getmaxx()/2-100,35,getmaxx()/2+100,60);


settextstyle(DEFAULT_FONT,HORIZ_DIR,3);

settextjustify(CENTER_TEXT,CENTER_TEXT);


switch(jugador){

case 1: outtextxy(getmaxx()/2,50,"GANASTE!");

partida=1; scoreJugador++; break;

case 2: outtextxy(getmaxx()/2,50,"GANÉ!");

partida=2; scoreComputadora++; break;

}


setfillstyle(SOLID_FILL,14);setcolor(14);

for(ix=-1;ix<=1;ix+=2)

{

if(!sil) silbo(50);

bar(getmaxx()/2+50*ix-40,getmaxy()*5/6-20,

getmaxx()/2+50*ix+80-40,getmaxy()*5/6+20);

}


setcolor(12);

settextstyle(DEFAULT_FONT,HORIZ_DIR,2);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2+50*(-1),getmaxy()*5/6,"Juego");

outtextxy(getmaxx()/2+50 ,getmaxy()*5/6,"Salir");


for(;;)

if(kbhit())

{getch(); goto sig;}

sig:


cleardevice();

return(0);

}



/*===================================================

CUADROS EN jugar */


void jugar::CUADROS(void)

{int ix,iy;

char ScoreGraf1[35], ScoreGraf2[35], buffer1[10], buffer2[10], *buf1, *buf2;

register int i;


setcolor(13);

settextstyle(DEFAULT_FONT,HORIZ_DIR,4);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2,getmaxy()/5,"JUEGO DEL GATO");


ScoreGraf1[0]='\0'; ScoreGraf2[0]='\0'; buffer1[0]='\0'; buffer2[0]='\0';


strcpy(ScoreGraf1,"JUGADOR ");

strcat(ScoreGraf1, itoa(scoreJugador,buffer1,10) );


strcat(ScoreGraf2,"COMPUTADORA ");

strcat(ScoreGraf2, itoa(scoreComputadora,buffer2,10) );


setcolor(11);

settextstyle(DEFAULT_FONT,HORIZ_DIR,2);

settextjustify(LEFT_TEXT,CENTER_TEXT);


outtextxy(15,getmaxy()-65,ScoreGraf1);

outtextxy(15,getmaxy()-45,ScoreGraf2);

setcolor(5);

outtextxy(15,getmaxy()-25,"para salir [esc]");

outtextxy(15,getmaxy()-10,"sonido [s], sin sonido [n]");


setfillstyle(SOLID_FILL,15);


for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

bar(getmaxx()/2+50*ix-25,getmaxy()/2+50*iy-25,

getmaxx()/2+50*ix+48-25,getmaxy()/2+48+50*iy-25);


}


/*===================================================

CUADROS EN inicio */


void inicio::CUADROS(void)

{

int ix,iy;


setcolor(13);

settextstyle(DEFAULT_FONT,HORIZ_DIR,4);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2,getmaxy()/5,"JUEGO DEL GATO");

settextstyle(DEFAULT_FONT,HORIZ_DIR,2);

setcolor(14);

outtextxy(getmaxx()/2,getmaxy()/5+30, "Usar el teclado numerico, una tecla...");


settextstyle(DEFAULT_FONT,HORIZ_DIR,4);

setcolor(5);

setfillstyle(SOLID_FILL,15);

for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

bar(getmaxx()/2+50*ix-25, getmaxy()/2+50*iy-25,

getmaxx()/2+50*ix+48-25, getmaxy()/2+48+50*iy-25);

for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

{

if(iy==-1 && ix==-1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"7");


if(iy==-1 && ix== 0)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"8");


if(iy==-1 && ix== 1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"9");


if(iy== 0 && ix==-1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"4");


if(iy== 0 && ix== 0)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"5");


if(iy== 0 && ix== 1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"6");


if(iy== 1 && ix==-1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"1");


if(iy== 1 && ix== 0)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"2");


if(iy== 1 && ix== 1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"3");

}

}


/*===================================================

PROGRAMA PRINCIPAL */


void main(void) {


jugar juego;

inicio iniciemos;

int resultado;


inigrafer(1,0,0,0);

iniciemos.CUADROS();getch();cleardevice();


for(;;)

{

juego.CUADROS();

randomize();

resultado=juego.JUEGO1();

if(resultado>=0) juego.GANADOR(resultado);

}


}



POLIMORFISMO


Uno de los resultados más importantes de la programación por objetos es el polimorfismo. El polimorfismo tiene dos ramas comprensivas: la primera es que muchos procedimientos pueden ser llamados con el mismo nombre. En este caso se dice que el nombre está "sobrecargado". La segundo es que la función de los operadores también puede "sobrecargarse". De manera que el mismo operador puede realizar varias tareas distintas, dependiendo del contexto.


Veamos el primer aspecto: sobrecargar un nombre.



SOBRECARGAR UN NOMBRE


Detro de una clase un nombre puede ser usado para nombrar dos o más procedimientos.


Estamos interesados en analizar qué tipo de funciones podemos por motivos prácticos englobar bajo un nombre común.


En programación nos encontramos a veces con funciones que cumplen propósitos parecidos pero que difieren en relación al tipo de argumentos que utilizan. Este caso es uno de los más comunes en que se utiliza el recurso de "sobrecargar nombres". Si los parámetros que utilizan las funciones no son distintos podríamos nosotros agregar un parámetro para "crear" la diferencia.


Por ejemplo: queremos que una función realice el cálculo de posición en pantalla y a veces enviamos el parámetro como entero y a veces como punto flotante para calcular la posición de acuerdo a una posición fija (incrementox, incrementoy). Necesitaríamos que dos funciones realicen el trabajo dependiendo de los datos que se envían. En este ejemplo se colocará un punto en una posición determinada.


class COLOCA {

int incrementox, incrementoy;

public:

punto(int x, int y, int color)

{setcolor(color); putpixel(x,y);}

punto(float x, float y, float color);

{setcolor(color);

putpixel((int)(x+incrementox),(int)(y+incrementoy));}

};


Estas dos funciones realizarán la tarea y para nosotros será muy sencillo simplemente escribir en el código que llame a la función simplemente así:


COLOCA.punto(15, 30, 13);

COLOCA.punto(15.035, 30.5, 13.2);


En el primer llamado, se posicionará un punto de acuerdo a la primer función que toma como parámetros números enteros. En el segundo llamado, se usará la función con parámetros flotantes. Si no usáramos el mismo nombre, en vez de usar la escritura anterior tendríamos que haber usado algo así como:


COLOCA.punto_entero(15, 30, 13);

COLOCA.punto_flotante(15.035, 30.5, 13.2);


...y de cualquier forma haber definido las dos funciones respectivas.


El polimorfismo aporta cierta comodidad y elegancia en la escritura de los programas.



HERENCIA


Otro aspecto de la programación por objetos es la herencia.


Los objetos pueden "heredar" propiedades y accesos a miembros de otros objetos.


Las palabras que tienen efecto sobre el tipo de herencia son: private,

public y protected.


Las siguientes reglas se aplican en la herencia:


1. Una clase que "hereda" a otra, es clase base.


2. Una clase que "recibe" la herencia de otra, es clase derivada.


3. Ninguna clase derivada tiene acceso a los miembros private

de ninguna clase base.


4. Los elementos protected de una clase base sí pueden ser

accesados por clases derivadas pero permanecen private

a cualquier otra clase (solo accesan los "herederos").


5. Al definir una clase derivada se establece el acceso que dicha

clase tendrá con respecto a los miembros de la clase base.


5.1. Si el acceso de una clase derivada es public,

los elementos protected y public de la clase base

serán protected y public en la clase derivada (la clase

derivada puede a su vez "heredar" accesos a otra).


5.2 Si el acceso de una clase derivada es private,

los elementos public y private de la clase base serán

private en la clase derivada (la clase derivada no puede

"heredar" dichos accesos a otra).


La forma general para declarar una base derivada es:


class nombre_derivada: acceso nombre_base { miembros... };


Por ejemplo, si queremos que la clase DERIVADA herede los accesos

protected y public de la base BASE, escribimos así:


class BASE {

int privado_base;

protected:

int protegido:

public:

int publico1;

int publico2;

};


class DERIVADA:private BASE { // NO HERèDA POR private

int derivada:

public:

void DERIVADA1(void);

void DERIVADA2(void);

};


En este ejemplo la clase DERIVADA tendrá acceso a protegido, publico1 y publico2 de BASE, pero no podrá heredar a nadie dichos accesos por su propio acceso private. Si quisiéramos que heredara dichos accesos tendríamos que escribir:


class DERIVADA:public BASE { // YA PUEDE HERèDAR POR public

...



EL JUEGO DEL GATO POLIMÓRFICO


Veamos ahora una versión nueva del programa que hemos venido estudiando.


Dijimos que requeríamos crear una clase distinta para una función que utilizaba el nombre CUADROS pues ya teníamos una con el mismo nombre en el entorno global del programa "sin clases". Así fue como creamos la clase inicio y la clase jugar, y después creamos los tipos iniciemos y juego para utilizar el nombre con "apellido" en el main. El resultado fué que en el entorno del main llamamos a las funciones CUADRO de las dos siguientes maneras:


iniciemos.CUADROS

juego.CUADROS


Pues bien, podemos observar que la función juego.CUADROS solo utiliza las variables scoreJugador y scoreComputadora del entorno jugar, mientras que iniciemos.CUADROS no utiliza ninguna. Aprovechemos este detalle para crear una clase que "herede" los accesos a dichas variables, pero que no "herede" los accesos privados de la clase jugar. Los demás elementos públicos de jugar siguen siendo públicos pues se utilizan en el entorno del main.


Asimismo la clase que crearemos no necesita heredar a ninguna otra clase, por lo que su propio acceso puede ser privado.


Ahora también utilizaremos el recurso de polimorfismo que aprendimos en la sección anterior y haremos que dos funciones compartan el mismo nombre. Tal como hemos creado las funciones CUADROS, ninguna requiere parámetros especiales, sin embargo ahora sí se requiere que los datos del score sean pasados como parámetros, pues cuando dichas variables son incrementadas en el entorno jugar de la función GANADOR, el incremento no tiene efecto en la copia que utiliza CUADROS.


Recordemos que la función GANADOR realiza el incremento y la función CUADROS imprime los resultados.


Así que ahora se requieren dos parámetros uno para el score del jugador y otro para el de la computadora. Aprovechemos esto y agreguemos una opción para cambio de color, con lo que resulta un tercer parámetro. El prototipo de la función queda como sigue:


void CUADROS(int SCOREJugador, int SCOREComputadora, int colorf);


La otra función CUADROS no utiliza parámetros y sigue igual:


void CUADROS(void);


Ya que una utiliza parámetros y la otra no utiliza ninguno esto será suficiente para distinguirlas en su uso.


Las declaraciones que han sido descritas son las siguientes:


class jugar {

unsigned int nivel;

char lugar[9];

unsigned int partida;

int sil;

public:

int scoreJugador, scoreComputadora;

int colortablero;

int GANADOR(int jugador);

int JUEGO1(void);

int CHECA(void);

jugar(void);

~jugar(void);

};


class dibuja:private jugar {

public:

void CUADROS(void);

void CUADROS(int SCOREJugador, int SCOREComputadora, int colorf);

};


Otros cambios necesarios son en los encabezados del cuerpo de ambas funciones. Ahora dichas funciones pertenecen a la clase dibuja así que los cuerpos son:


void dibuja::CUADROS(int SCOREJugador,

int SCOREComputadora, int colorf){...}


void dibuja::CUADROS(void) {...}


Ahora en el main podemos simplemente escribir:


dibujemos.CUADROS();


para una función y


dibujemos.CUADROS(juego.scoreJugador, juego.scoreComputadora,

juego.colortablero );


para la otra. En este caso juego.scoreJugador y juego.scoreComputadora son los valores que se utilizan durante el main.


También se han agregado las siguientes líneas a la función JUEGO1 que realizan la selección de color del tablero.


if(c=='b') {colortablero=15; return(-1);}

if(c=='a') {colortablero=14; return(-1);}


Las demás partes del programa son similares a las del programa GATOCLAS.CPP.


Si revisamos el tamaño del ejecutable que resulta se verá lo siguiente:


1. El tamaño de gato.exe (programa en Turbo C sin clases) es 66618.

2. El tamaño de gatoclas.exe (programa C++ con una clase) es 88345.

3. El tamaño de gatclas2.exe (programa C++ con clases y accesos restringidos) es 87666.


Ciertamente aún no hemos ganado en tamaño con respecto al programa en Turbo C. El programa es pequeño y el incremento debido a las clases es significativo. Pero si comparamos el tamaño del programa con accesos restringidos con el programa con una clase sin restricciones ya tiene ventaja sobre el . Las restricciones y el polimorfismo han liberado 680 K.



CÓDIGOS DEL GATO POLIMÓRFICO


Los códigos que se encuentran en el archivo GATCLAS2.CPP quedaron como sigue:


#include <iostream.h>

#include <conio.h>

#include <stdlib.h>

#include <string.h>

#include <time.h>

#include "c:\cursoc\mouse.c"

#include "c:\sisc\sonido.c"


/*====================================

CLASES */


// DECLARACIONES DE LA CLASE BASE jugar


class jugar {


// VARIABLES QUE NO REQUIEREN SER ACCESADAS


unsigned int nivel;

char lugar[9];

unsigned int partida;

int sil;


public:


// MIEMBROS DE LA CLASE jugar


int scoreJugador, scoreComputadora;

int colortablero;

int GANADOR(int jugador);

int JUEGO1(void);

int CHECA(void);

jugar(void);

~jugar(void);

};


/* CLASE dibuja QUE DERIVADA DE JUGAR

LOS ELEMENTOS PÚBLICOS Y PRIVADOS DE jugar

SON PÚBLICOS Y PRIVADOS DE dibuja */


class dibuja:private jugar {

public:

void CUADROS(void);

void CUADROS(int SCOREJugador, int SCOREComputadora, int colorf);

};


/*====================================

MIEMBROS */


// CONSTRUCTOR QUE INICIA VARIABLES DE jugar


jugar::jugar(void){

nivel=0;

partida=1;

sil=0;

scoreJugador=0; scoreComputadora=0;

register int r;

for(r=0;r<9;r++) lugar[r]=' ';

};


// DESTRUCTOR DE jugar.(LOS DESTRUCTORES GENERALMENTE SOLO DESTRUYEN)


jugar::~jugar(void){

cout << "bye bye jugar ...";

getch();

};


/*===================================================

MIEMBROS DE LA CLASE JUGAR:

REVISA GANADORES */


int jugar::CHECA(void){int ix, iy;


for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)


{


if(lugar[0+3*(iy+1)]==lugar[1+3*(iy+1)] &&

lugar[1+3*(iy+1)]==lugar[2+3*(iy+1)] &&

lugar[2+3*(iy+1)]=='x')

return(1);


if(lugar[ix+1+3*(0)]==lugar[ix+1+3*(1)] &&

lugar[ix+1+3*(1)]==lugar[ix+1+3*(2)] &&

lugar[ix+1+3*(2)]=='x')

return(1);


if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[2+3*(2)]=='x')

return(1);


if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(0)] &&

lugar[2+3*(0)]=='x')

return(1);


if(lugar[0+3*(iy+1)]==lugar[1+3*(iy+1)] &&

lugar[1+3*(iy+1)]==lugar[2+3*(iy+1)] &&

lugar[2+3*(iy+1)]=='o')

return(2);


if(lugar[ix+1+3*(0)]==lugar[ix+1+3*(1)] &&

lugar[ix+1+3*(1)]==lugar[ix+1+3*(2)] &&

lugar[ix+1+3*(2)]=='o')

return(2);


if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[2+3*(2)]=='o')

return(2);


if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[1+3*(1)]==lugar[2+3*(0)] &&

lugar[2+3*(0)]=='o')

return(2);


}


return(0);

}



/*===================================================

SUBRUTINA DEL JUEGO */


int jugar::JUEGO1(void){int j=0,r; char c=0;


inicioj:


for(r=0;r<9;r++) lugar[r]=' ';


do{int ix,iy,cx,cy;


otrotiro:


for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

{


if(kbhit()|| (j==0&&partida==2))


{

c=getch();

if(c==27) goto evaluar;

if(c=='7'){iy=-1;ix=-1;}

if(c=='8'){iy=-1;ix= 0;}

if(c=='9'){iy=-1;ix= 1;}

if(c=='4'){iy= 0;ix=-1;}

if(c=='5'){iy= 0;ix= 0;}

if(c=='6'){iy= 0;ix= 1;}

if(c=='1'){iy= 1;ix=-1;}

if(c=='2'){iy= 1;ix= 0;}

if(c=='3'){iy= 1;ix= 1;}

if(c=='b') {colortablero=15; return(-1);}

if(c=='a') {colortablero=14; return(-1);}



if(!sil) silbo(50);

if( (j>0 && partida==2) || partida==1 )


{


if(lugar[ix+1+3*(iy+1)]=='x' || lugar[ix+1+3*(iy+1)]=='o')

{ if(!sil) silbo(50); goto otrotiro; }


else

{lugar[ix+1+3*(iy+1)]='x'; j++;

setcolor(10);

settextstyle(DEFAULT_FONT,HORIZ_DIR,3);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2+50*ix,getmaxy()/2+50*iy,"x");


if(CHECA()) return(CHECA());


}


}


if(j<=8)


{int b,fx,fy,esq;


j++;


randomize();



/* si el nivel es 0 y es la primer jugada responde al centro */



if(j==1 && nivel==0)

{cx=0;cy=0;goto respuesta;}



/* responde al centro cuando primer jugada fué al extremo */


if(j==2 && lugar[4]==' ')

{cx=0;cy=0;goto respuesta;}



/* DOS IGUALES 'o' */


/*diag ab*/

if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[2+3*(2)]==' ' && lugar[1+3*(1)]=='o' )

{cx=1; cy=1;goto respuesta;}


if(lugar[0+3*(0)]==lugar[2+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[2+3*(2)]=='o' )

{cx=0; cy=0;goto respuesta;}


if(lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[0+3*(0)]==' ' && lugar[2+3*(2)]=='o' )

{cx=-1;cy=-1;goto respuesta;}


/*diag ar*/

if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[2+3*(0)]==' ' && lugar[1+3*(1)]=='o' )

{cx=1;cy=-1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[1+3*(1)] &&

lugar[0+3*(2)]==' ' && lugar[1+3*(1)]=='o' )

{cx=-1;cy=1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[0+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[0+3*(2)]=='o' )

{cx=0; cy=0;goto respuesta;}


/*horiz*/


for(fy=-1;fy<=1;fy++){

if(lugar[0+3*(fy+1)]==lugar[1+3*(fy+1)] &&

lugar[2+3*(fy+1)]==' ' && lugar[1+3*(fy+1)]=='o')

{cx=1; cy=fy;goto respuesta;}


if(lugar[1+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[0+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='o')

{cx=-1;cy=fy;goto respuesta;}


if(lugar[0+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[1+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='o')

{cx=0; cy=fy;goto respuesta;}

}


/*vert*/


for(fx=-1;fx<=1;fx++){

if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(1)] &&

lugar[fx+1+3*(2)]==' ' && lugar[fx+1+3*(1)]=='o')

{cx=fx;cy=1;goto respuesta;}


if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(1)]==' ' && lugar[fx+1+3*(2)]=='o')

{cx=fx;cy=0;goto respuesta;}


if(lugar[fx+1+3*(1)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(0)]==' ' && lugar[fx+1+3*(2)]=='o')

{cx=fx;cy=-1;goto respuesta;}

}



/* DOS IGUALES 'x' */


/*diag ab*/

if(lugar[0+3*(0)]==lugar[1+3*(1)] &&

lugar[2+3*(2)]==' ' && lugar[1+3*(1)]=='x' )

{cx=1; cy=1;goto respuesta;}


if(lugar[0+3*(0)]==lugar[2+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[2+3*(2)]=='x' )

{cx=0; cy=0;goto respuesta;}


if(lugar[1+3*(1)]==lugar[2+3*(2)] &&

lugar[0+3*(0)]==' ' && lugar[2+3*(2)]=='x' )

{cx=-1;cy=-1;goto respuesta;}


/*diag ar*/

if(lugar[0+3*(2)]==lugar[1+3*(1)] &&

lugar[2+3*(0)]==' ' && lugar[1+3*(1)]=='x' )

{cx=1;cy=-1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[1+3*(1)] &&

lugar[0+3*(2)]==' ' && lugar[1+3*(1)]=='x' )

{cx=-1;cy=1;goto respuesta;}


if(lugar[2+3*(0)]==lugar[0+3*(2)] &&

lugar[1+3*(1)]==' ' && lugar[0+3*(2)]=='x' )

{cx=0; cy=0;goto respuesta;}


/*horiz*/


for(fy=-1;fy<=1;fy++){

if(lugar[0+3*(fy+1)]==lugar[1+3*(fy+1)] &&

lugar[2+3*(fy+1)]==' ' && lugar[1+3*(fy+1)]=='x')

{cx=1; cy=fy;goto respuesta;}


if(lugar[1+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[0+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='x')

{cx=-1;cy=fy;goto respuesta;}


if(lugar[0+3*(fy+1)]==lugar[2+3*(fy+1)] &&

lugar[1+3*(fy+1)]==' ' && lugar[2+3*(fy+1)]=='x')

{cx=0; cy=fy;goto respuesta;}

}


/*vert*/


for(fx=-1;fx<=1;fx++){

if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(1)] &&

lugar[fx+1+3*(2)]==' ' && lugar[fx+1+3*(1)]=='x')

{cx=fx;cy=1;goto respuesta;}


if(lugar[fx+1+3*(0)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(1)]==' ' && lugar[fx+1+3*(2)]=='x')

{cx=fx;cy=0;goto respuesta;}


if(lugar[fx+1+3*(1)]==lugar[fx+1+3*(2)] &&

lugar[fx+1+3*(0)]==' ' && lugar[fx+1+3*(2)]=='x')

{cx=fx;cy=-1;goto respuesta;}

}


/* PRIORIDAD EN LAS ESQUINAS */


randomize();

do


{


cy=random(3)-1;cx=random(3)-1;}

while(lugar[cx+1+3*(cy+1)]=='o' ||

lugar[cx+1+3*(cy+1)]=='x' );


respuesta: lugar[cx+1+3*(cy+1)]='o';


setcolor(12);

settextstyle(DEFAULT_FONT,HORIZ_DIR,3);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2+50*cx,getmaxy()/2+50*cy,"o");


if(CHECA()) return(CHECA());


}


if(CHECA()) return(CHECA());


}


}


evaluar:


if(c)

{ if(c==27) exit(0);

if(c==(int)'n') sil=1;

if(c==(int)'s') sil=0;

c=0;

}


} while(j<9);


return -1;


}


/*===================================================

GANADOR Y CONTINUACIÓN */


int jugar::GANADOR(int jugador)


{int ix;


setfillstyle(SOLID_FILL,3);

bar(getmaxx()/2-100,35,getmaxx()/2+100,60);


settextstyle(DEFAULT_FONT,HORIZ_DIR,3);

settextjustify(CENTER_TEXT,CENTER_TEXT);


switch(jugador){

case 1: outtextxy(getmaxx()/2,50,"GANASTE!");

partida=1; scoreJugador++; break;

case 2: outtextxy(getmaxx()/2,50,"GANÉ!");

partida=2; scoreComputadora++; break;

}


setfillstyle(SOLID_FILL,14);setcolor(14);

for(ix=-1;ix<=1;ix+=2)

{

if(!sil) silbo(50);

bar(getmaxx()/2+50*ix-40,getmaxy()*5/6-20,

getmaxx()/2+50*ix+80-40,getmaxy()*5/6+20);

}


setcolor(12);

settextstyle(DEFAULT_FONT,HORIZ_DIR,2);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2+50*(-1),getmaxy()*5/6,"Juego");

outtextxy(getmaxx()/2+50 ,getmaxy()*5/6,"Salir");


for(;;)

if(kbhit())

{getch(); goto sig;}

sig:


cleardevice();

return(0);

}



/*===================================================

CUADROS EN jugar */


void dibuja::CUADROS(int SCOREJugador, int SCOREComputadora, int colorf)

{int ix,iy;

char ScoreGraf1[35], ScoreGraf2[35], buffer1[10], buffer2[10];

register int i;


setcolor(13);

settextstyle(DEFAULT_FONT,HORIZ_DIR,4);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2,getmaxy()/5,"JUEGO DEL GATO");


ScoreGraf1[0]='\0'; ScoreGraf2[0]='\0'; buffer1[0]='\0'; buffer2[0]='\0';


strcpy(ScoreGraf1,"JUGADOR ");

strcat(ScoreGraf1, itoa(SCOREJugador,buffer1,10) );


strcat(ScoreGraf2,"COMPUTADORA ");

strcat(ScoreGraf2, itoa(SCOREComputadora,buffer2,10) );


setcolor(11);

settextstyle(DEFAULT_FONT,HORIZ_DIR,2);

settextjustify(LEFT_TEXT,CENTER_TEXT);


outtextxy(15,getmaxy()-65,ScoreGraf1);

outtextxy(15,getmaxy()-45,ScoreGraf2);

setcolor(5);

outtextxy(15,getmaxy()-25,"para salir [esc]");

outtextxy(15,getmaxy()-10,"sonido [s], sin sonido [n]");


setfillstyle(SOLID_FILL,15);


for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

bar(getmaxx()/2+50*ix-25,getmaxy()/2+50*iy-25,

getmaxx()/2+50*ix+48-25,getmaxy()/2+48+50*iy-25);


}


/*===================================================

CUADROS EN inicio */


void dibuja::CUADROS(void)

{

int ix,iy;


setcolor(13);

settextstyle(DEFAULT_FONT,HORIZ_DIR,4);

settextjustify(CENTER_TEXT,CENTER_TEXT);

outtextxy(getmaxx()/2,getmaxy()/5,"JUEGO DEL GATO");

settextstyle(DEFAULT_FONT,HORIZ_DIR,2);

setcolor(14);

outtextxy(getmaxx()/2,getmaxy()/5+30, "Usar el teclado numerico, una tecla...");


settextstyle(DEFAULT_FONT,HORIZ_DIR,4);

setcolor(5);

setfillstyle(SOLID_FILL,15);

for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

bar(getmaxx()/2+50*ix-25, getmaxy()/2+50*iy-25,

getmaxx()/2+50*ix+48-25, getmaxy()/2+48+50*iy-25);

for(iy=-1;iy<=1;iy++)

for(ix=-1;ix<=1;ix++)

{

if(iy==-1 && ix==-1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"7");


if(iy==-1 && ix== 0)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"8");


if(iy==-1 && ix== 1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"9");


if(iy== 0 && ix==-1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"4");


if(iy== 0 && ix== 0)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"5");


if(iy== 0 && ix== 1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"6");


if(iy== 1 && ix==-1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"1");


if(iy== 1 && ix== 0)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"2");


if(iy== 1 && ix== 1)

outtextxy(getmaxx()/2+50*ix+24-25, getmaxy()/2+50*iy+24-25,"3");

}

}


/*===================================================

PROGRAMA PRINCIPAL */


void main(void) {


jugar juego;

inicio iniciemos;

int resultado;


inigrafer(1,0,0,0);

dibujemos.CUADROS();getch();cleardevice();


for(;;)

{

dibujemos.CUADROS(juego.scoreJugador, juego.scoreComputadora, juego.colortablero );

randomize();

resultado=juego.JUEGO1();

if(resultado>=0) juego.GANADOR(resultado);

}


}



SOBRECARGA DE OPERADORES


Así como es posible asignar varias funciones a un mismo nombre, también es posible asignar varios usos a cualquiera de los operadores unarios y binarios. Los operadores ternarios no pueden sobrecargarse.


Ud. puede sobrecargar los operadores


new delete

+ - * / % ^ & | ~

! = < > += -= *= /= %=

^= &= != << >> >>= <<= == !=

<= >= && || ++ -- , ->* ->

() []


Es posible sobrecargar tanto unaria como binariamente


+ - * &


Y los operadores que no se pueden sobrecargar son:


. .* :: ?: sizeof


La sintaxis general para sobrecargar un operador es la siguiente:


tipo nombre_clase::operator#(argumentos) { operación... }


En general se recomienda que el uso que se da a un operador sobrecargado sea congruente con la operación que generalmente se asigna con dicho operador.


Por ejemplo en la suma de vectores o de números complejos es bastante natural reconocer que la notación:


c = a + b


los símbolos c, a y b no son números enteros o irracionales simples, sino que se trata de agrupaciones de números definidas para los vectores como {v | v=(v1, v2, v3) y para los complejos {c | c=(parte_real + parte_imaginaria*i) }.


Tales operaciones suelen sobrecargarse por medio del procedimiento que aquí se describe pudiendo haber más de una operación definida para el mismo operador. El compilador reconoce cuál función sobrecargada aplica en cada caso dependiendo de los argumentos que tome cada función.



DIFERENCIAS EN LA SOBRECARGA DE OPERADORES. PALABRA this


Al sobrecargar operadores existen diferencias si el operador es unario o binario. También existen diferencias si alguno de los operandos se pasa a la función en forma de argumento o si dicho operando es forma parte de los miembros de la clase. En este último caso, ya que no existe otra forma de devolver el puntero de la clase se introduce la palabra this, que es el puntero que apunta al objeto de la clase.



SUMA DE VECTORES EN 3 DIMENSIONES


Efectuemos un ejemplo de suma de vectores en 3 dimensiones. Cuando sumamos los vectores a + b y asignamos este valor a c, estamos realizando la operación:


c1 = a1 + b1

c2 = a2 + b2

c3 = a3 + b3


Ya que el primer paso consiste en sumar los dos valores de a y b, y el siguiente paso consiste en asignar dicho valor al respectivo valor de c, podemos sobrecargar el operador + y el operador =.


El cuerpo de la función que sobrecarga al primer operador puede ser:


vectores3 vectores3::operator+(vectores3 t)

{

vectores3 temporal;

temporal.v1 = v1 + t.v1;

temporal.v2 = v2 + t.v2;

temporal.v3 = v3 + t.v3;

return temporal;

}


Obsérvese que hemos tenido que declarar un objeto de clase vectores3 para poder realizar la operación interna de la función, y devolvemos dicho objeto.


En el caso del segundo operador =, la operación se efectúa sobre las variables privadas de la clase, es decir sobre v1, v2 y v3, de manera que tenemos que devolver el puntero propio de la clase. Hasta ahora no hemos utilizado este recurso. Para referirnos a dicho puntero, utilizamos la palabra this. El cuerpo de la función es el siguiente:


vectores3 vectores3::operator=(vectores3 t)

{

v1 = t.v1;

v2 = t.v2;

v3 = t.v3;

return *this;

}


En el main simplemente podemos ahora escribir c = a + b; para realizar la operación. Así:


void main (void)

{

...

vectores3 a, b, c;

...

c = a + b;

...

}



CÓDIGOS DEL PROGRAMA DE SUMA DE VECTORES


El programa completo se encuentra en el archivo OPERAT00.CPP y es el siguiente:


#include<iostream.h>

#include<conio.h>


class vectores3{

float v1,v2,v3;

public:

void muestra(void);

void asigna(float asig1, float asig2, float asig3);

vectores3 operator+(vectores3);

vectores3 operator=(vectores3);

};


vectores3 vectores3::operator+(vectores3 t)

{

vectores3 temporal;

temporal.v1 = v1 + t.v1;

temporal.v2 = v2 + t.v2;

temporal.v3 = v3 + t.v3;

return temporal;

}


vectores3 vectores3::operator=(vectores3 t)

{

v1 = t.v1;

v2 = t.v2;

v3 = t.v3;

return *this;

}


void vectores3::muestra(void)

{

cout << "( ";

cout << v1 << ", ";

cout << v2 << ", ";

cout << v3 << " )\n";

}


void vectores3::asigna(float asig1, float asig2, float asig3)

{

v1=asig1;

v2=asig2;

v3=asig3;

}


void main (void)

{

clrscr();

vectores3 a, b, c;

a.asigna(5,5,5);

b.asigna(1.5,2,.5);

cout <<"El primer vector es a = "; a.muestra();

cout <<"El segundo vector es b = "; b.muestra();

c = a + b;

cout <<"La suma de ambos vectores es c = "; c.muestra();

getch();

}



SOBRECARGA DE UNARIO. REPETICIÓN DE UN PATRÓN EN 3A. DIMENSIÓN


A continuación se presenta un programa en que hemos sobrecargado el operador ++ para que se efectúe una operación de incremento de valores en un patrón de tercera dimensión.


Se declaran dos clases: clase3d y clase3d_ops. La primera clase contiene elementos para el dibujo en 3a. dimensión (para informes sobre temas de 3a. dimensión favor de consultar y pedir informes en las direcciones que se anotan en la sección correspondiente). La segunda clase es derivada de la primera y hereda todos los miembros pues son públicos.


La segunda clase, contiene los elementos propios del operador sobrecargado que queremos definir.


El operador se declara miembro de la clase:


clase3d_ops operator++(void);


El cuerpo del miembro realiza una operación de incremento de coordenadas:


clase3d_ops clase3d_ops::operator++(void)

{

x+=incrx_op;

y+=incry_op;

z+=incrz_op;

return *this;

}


Las variables de incremento y otras se inicializan mediante el constructor de la clase:


clase3d_ops::clase3d_ops(void)

{

incrx_op=.25;

incry_op=.25;

incrz_op=-.25;

x=-50;

y=-3;

z=3;

incrpatrx=.25;

}


la función redefine, miembro de la clase, se utiliza para reposicionar el elemento cada vez que el ciclo termina.


void clase3d_ops::redefine(int cual)

{

y=-3;

z= 3;

x=x+incrpatrx;

}


En el programa main puede observarse que se ha declarado un objeto clase clase3d_ops de nombre a, inigrafer() se utiliza para inicializar los gráficos, la operación de reposicionamiento se lleva a cabo con el operador ++, la función dibuja_esquina() dibuja el patrón y la función redefine() reposiciona el elemento.


void main(void) { clase3d_ops a;


inigrafer(1,0,0,0);

register int i,j;

for(j=1;j<23;j++)

{

for(i=0;i<9;i++)

{

a.dibuja_esquina();

a++;

}

a.redefine(j);

} getch();

}



CÓDIGOS DEL PROGRAMA DE REPETICIÓN DE PATRÓN


El programa completo se encuentra en el archivo OPERAT01.CPP y es el siguiente:


#include <iostream.h>

#include "c:\sisc\mouse.cpp"

#include <stdio.h>

#include <math.h>

#include <graphics.h>

#include <conio.h>


class clase3d {

public:

double distpan; /* DISTANCIA DE LOS OJOS A LA PANTALLA (mts.)*/

double distejpanx1; /* DISTANCIA DE LOS OJOS AL ORIGEN

HORIZONTAL (mts.) */


double distejpanz1; /* DESVIACIÓN VERTICAL DE LA PANTALLA AL

ORIGEN (mts.) */

double distejpany1; /* DESVIACIÓN HORIZONTAL DE LA PANTALLA

AL ORIGEN (mts.) */


double dimpany; /* DIMENSIÓN VERTICAL DE LA PANTALLA

(mts. VGA)*/

double dimpanx; /* DIMENSIÓN HORIZONTAL DE LA PANTALLA

(mts. VGA)*/


double angejex; /* ÁNGULO DEL PLANO XY' CON RESPECTO

AL PLANO XY EN RADIANES

(pi/2=1.570796327) */


double punx ; /* CENTRO X DE LA PANTALLA = getmaxx() / 2; */

double puny ; /* CENTRO Y DE LA PANTALLA = getmaxy() / 2; */


double x,y,z; /* COORDENADAS GLOBALES */

double distx,disty,distz; /* VARIABLES PARA CÁLCULO

DE POSICIÓN DE PIXELES */

double xpan,ypan; /* COORDENADAS FINALES x Y

y EN PANTALLA (POSICIÓN DE PÍXELES) */


double ojpan; /* (.185 / 5 ) ALTURA DESCENDENTE DE LOS OJOS

CON RESPECTO AL TOPE DE LA

PANTALLA */


double centrox; /* VARIABLE QUE SE MULTIPLICA POR EL

TOTAL PÍXELES

HORIZONTALES PARA DEFINIR EL

CENTRO x RELATIVO DEL EJE VISUAL */


double ojpanpix; /* ojpan * 350 / .185; ALTURA DESCENDENTE DE LOS

OJOS CON RESPECTO AL TOPE DE

LA PANTALLA EN PÍXELES */

double X1,Y1,Z1,X2,Y2,Z2;

double incrx,incry,incrz;

int cd;


double cpan(double X,double Y,double Z,int i);

void linea(double xpar1,double ypar1,double zpar1,

double xpar2,double ypar2,double zpar2,int c);

void ejes(int c);

clase3d(void);

};


clase3d::clase3d(void){

distpan = .45; /* DISTANCIA DE LOS OJOS A LA PANTALLA (mts.)*/

distejpanx1 = 20; /* DISTANCIA DE LOS OJOS AL ORIGEN HORIZONTAL (mts.) */

distejpanz1 = 5.0; /* DESVIACIÓN VERTICAL DE LA PANTALLA AL ORIGEN (mts.) */

distejpany1 = 0; /* DESVIACIÓN HORIZONTAL DE LA PANTALLA AL ORIGEN (mts.) */

dimpany = .18; /* DIMENSIÓN VERTICAL DE LA PANTALLA (mts. VGA)*/

dimpanx = .24; /* DIMENSIÓN HORIZONTAL DE LA PANTALLA (mts. VGA)*/

angejex = .30; /* ÁNGULO DEL PLANO XY' CON RESPECTO AL PLANO XY

EN RADIANES (pi/2=1.570796327) */

ojpan = .037; /* (.185 / 5 ) ALTURA DESCENDENTE DE LOS OJOS

CON RESPECTO AL TOPE DE LA PANTALLA */

centrox = .5; /* VARIABLE QUE SE MULTIPLICA POR EL TOTAL PÍXELES

HORIZONTALES PARA DEFINIR EL CENTRO

x RELATIVO DEL EJE VISUAL */

ojpanpix = 70; /* ojpan * 350 / .185; ALTURA DESCENDENTE DE LOS

OJOS CON RESPECTO AL TOPE DE LA

PANTALLA EN PÍXELES */

incrx=0;

incry=0;

incrz=0;

}


/*-------- DEVUELVE LAS COORDENADAS X o Y EN PANTALLA ---------------*/


double clase3d::cpan(double X,double Y,double Z,int i)

{

if(X==0) X = .00001;

if(Y==0) Y = .00001;

if( X< 0 ) {distx = distejpanx1 + cos(atan(Y / X) - angejex) *

sqrt(pow(X,2) + pow(Y,2));

disty = distejpany1 + sin(atan(Y / X) - angejex) *

sqrt(pow(X,2) + pow(Y,2));

}


if( X> 0) {distx = distejpanx1 - cos(atan(Y / X) - angejex) *

sqrt(pow(X,2) + pow(Y,2));

disty = distejpany1 - sin(atan(Y / X) - angejex) *

sqrt(pow(X,2) + pow(Y,2));

}


distz = distejpanz1 - Z;


if (kbhit()) exit(0);


if(distx==0) distx=.00001;


switch(i){

case 0:

return ((getmaxx() * centrox) + (disty * distpan / distx) *

getmaxx() / dimpanx);

case 1:

return (ojpanpix + (distz * distpan / distx) * getmaxy() /

dimpany);

}

return 0;

}


/*------------------------ LÍNEA ---------------------------------*/


void clase3d::linea(double xpar1,double ypar1,double zpar1,

double xpar2,double ypar2,double zpar2,int c){


X1=xpar1+incrx; Y1=ypar1+incry; Z1=zpar1+incrz;

X2=xpar2+incrx; Y2=ypar2+incry; Z2=zpar2+incrz;


setcolor (c);

line(cpan(X1,Y1,Z1,0),cpan(X1,Y1,Z1,1),cpan(X2,Y2,Z2,0),cpan(X2,Y2,Z2,1));

}


/*------------------------ EJES ----------------------------*/


void clase3d::ejes(int c){


linea(0,0,0,1,0,0,c);

linea(0,0,0,0,1,0,c);

linea(0,0,0,0,0,1,c);


}


/*-----------------------------------------------------

LA CLASE CON OPERADOR SOBRECARGADO */


class clase3d_ops:clase3d {

public:

double incrpatrx;

double incrpatry;

double incrpatrz;

double incrx_op;

double incry_op;

double incrz_op;

void dibuja_esquina(void);

void redefine(int cual);

clase3d_ops operator++(void);

clase3d_ops(void);

};


clase3d_ops::clase3d_ops(void)

{

incrx_op=.25;

incry_op=.25;

incrz_op=-.25;

x=-50;

y=-3;

z=3;

incrpatrx=.25;

}


void clase3d_ops::redefine(int cual)

{

y=-3;

z= 3;

x=x+incrpatrx;

}


void clase3d_ops::dibuja_esquina(void)

{

linea(x,y,z,x+.5,y,z,14);

linea(x,y,z,x,y+.5,z,14);

linea(x,y,z,x,y,z+.5,14);

}


clase3d_ops clase3d_ops::operator++(void)

{

x+=incrx_op;

y+=incry_op;

z+=incrz_op;

return *this;

}


/*==================================================

PROGRAMA PRINCIPAL

====================================================*/


void main(void){


clase3d_ops a;

inigrafer(1,0,0,0);


register int i,j;

for(j=1;j<23;j++)

{

for(i=0;i<9;i++)

{

a.dibuja_esquina();

a++;

}

a.redefine(j);

}

getch();


}


Posted by jorge-paz at 9:48 PM EDT
Updated: Wednesday, 17 October 2012 10:44 PM EDT
Post Comment | Permalink | Share This Post

Newer | Latest | Older