Wednesday, February 13, 2008

ZTIC_TAC_TOE (Juego en ABAP)


Ayer estaba aburrido en la oficina, esperando una orden de transporte y que una tabla me devolviera algunos resultados...Entonces, me puse a pensar acerca de mi nuevo blog...Como ya he escrito tantas cosas, me es un poco dificil crear algo nuevo y extraño -;) Felizmente me acordé que hace algún tiempo hice un Tic-Tac-Toe (Michi o Gato) en Ruby, así que pensé que hacerlo en ABAP no sería muy díficil...Y no lo fué -;) Me tomó solamente 20 minutos hacer esto...

El juego tiene una pobre y limitada Inteligencia Artificial...Debemos ingresar un número del 1 al 9 y presionar Play! para que la computadora haga su jugada debemos presionar Play! nuevamente...






Ahora, el código fuente...


*&-----------------------------------------------------------*
*& Report ZTIC_TAC_TOE *
*&-----------------------------------------------------------*

REPORT ZTIC_TAC_TOE NO STANDARD PAGE HEADING.

TYPES: BEGIN OF TY_PLAYS,
PLAY TYPE C,
END OF TY_PLAYS.

DATA: T_PLAYS TYPE STANDARD TABLE OF TY_PLAYS.

FIELD-SYMBOLS: <FS_PLAYS> LIKE LINE OF T_PLAYS.

DATA: RANDOM TYPE REF TO CL_ABAP_RANDOM.

DATA: SEED TYPE I,
WIN_FLAG TYPE C,
FLAG_OK TYPE C,
W_LINES TYPE I,
FLAG TYPE C,
PLAYER_ONE TYPE C,
PLAYER_TWO TYPE C,
ONE TYPE C,
TWO TYPE C,
THREE TYPE C,
FOUR TYPE C,
FIVE TYPE C,
SIX TYPE C,
SEVEN TYPE C,
EIGHT TYPE C,
NINE TYPE C.

*-----------------------------------------------------------*
* START-OF-SELECTION *
*-----------------------------------------------------------*
START-OF-SELECTION.
FLAG = '1'.
SET PF-STATUS 'BAR'.
PERFORM BOARD USING '' '' ''.
PERFORM PLAYER_ONE.

*-----------------------------------------------------------*
* FORM PLAYER_ONE *
*-----------------------------------------------------------*
FORM PLAYER_ONE.
IF WIN_FLAG EQ SPACE.
WRITE:/ 'Player one: '.
FORMAT INPUT ON.
WRITE: PLAYER_ONE.
FORMAT INPUT OFF.
ENDIF.
ENDFORM. "player_one

*-----------------------------------------------------------*
* FORM PLAYER_TWO *
*-----------------------------------------------------------*
FORM PLAYER_TWO.
IF WIN_FLAG EQ SPACE.
WRITE:/ 'Player two: '.
FORMAT INPUT ON.
WRITE: PLAYER_TWO.
FORMAT INPUT OFF.
ENDIF.
ENDFORM. "player_two

*-----------------------------------------------------------*
* FORM BOARD *
*-----------------------------------------------------------*
FORM BOARD USING P_PLAYER P_NUMBER FLAG_OK.

IF P_PLAYER NE SPACE AND P_NUMBER NE SPACE.
READ TABLE T_PLAYS WITH KEY PLAY = P_NUMBER
ASSIGNING <FS_PLAYS>.
IF NOT <FS_PLAYS> IS ASSIGNED OR SY-SUBRC NE 0.
APPEND INITIAL LINE TO T_PLAYS
ASSIGNING <FS_PLAYS>.
<FS_PLAYS>-PLAY = P_NUMBER.
UNASSIGN <FS_PLAYS>.
FLAG_OK = 'X'.
ELSE.
WRITE:/ 'Please select another number!'.
CLEAR: P_NUMBER,FLAG_OK.
ENDIF.
ENDIF.

CASE P_NUMBER.
WHEN '1'.
IF P_PLAYER EQ '1'.
ONE = 'X'.
ELSE.
ONE = 'O'.
ENDIF.
WHEN '2'.
IF P_PLAYER EQ '1'.
TWO = 'X'.
ELSE.
TWO = 'O'.
ENDIF.
WHEN '3'.
IF P_PLAYER EQ '1'.
THREE = 'X'.
ELSE.
THREE = 'O'.
ENDIF.
WHEN '4'.
IF P_PLAYER EQ '1'.
FOUR = 'X'.
ELSE.
FOUR = 'O'.
ENDIF.
WHEN '5'.
IF P_PLAYER EQ '1'.
FIVE = 'X'.
ELSE.
FIVE = 'O'.
ENDIF.
WHEN '6'.
IF P_PLAYER EQ '1'.
SIX = 'X'.
ELSE.
SIX = 'O'.
ENDIF.
WHEN '7'.
IF P_PLAYER EQ '1'.
SEVEN = 'X'.
ELSE.
SEVEN = 'O'.
ENDIF.
WHEN '8'.
IF P_PLAYER EQ '1'.
EIGHT = 'X'.
ELSE.
EIGHT = 'O'.
ENDIF.
WHEN '9'.
IF P_PLAYER EQ '1'.
NINE = 'X'.
ELSE.
NINE = 'O'.
ENDIF.
ENDCASE.

PERFORM CHECK_WHO_WINS.
DESCRIBE TABLE T_PLAYS LINES W_LINES.

IF WIN_FLAG EQ SPACE AND W_LINES EQ 9.
WIN_FLAG = 'X'.
WRITE: 'It''s a tie!'.
ENDIF.

WRITE:/ ONE,'|',TWO,'|',THREE.
WRITE:/ '--+---+---'.
WRITE:/ FOUR,'|',FIVE,'|',SIX.
WRITE:/ '--+---+---'.
WRITE:/ SEVEN,'|',EIGHT,'|',NINE.

IF P_PLAYER EQ '2'.
PERFORM PLAYER_ONE.
ELSEIF P_PLAYER EQ '1'.
PERFORM PLAYER_TWO.
ENDIF.
ENDFORM. "board

*-----------------------------------------------------------*
* FORM check_who_wins *
*-----------------------------------------------------------*
FORM CHECK_WHO_WINS.
IF ONE EQ TWO AND TWO EQ THREE.
IF THREE EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF THREE EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF FOUR EQ FIVE AND FIVE EQ SIX.
IF SIX EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF SIX EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF SEVEN EQ EIGHT AND EIGHT EQ NINE.
IF NINE EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF NINE EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF ONE EQ FOUR AND FOUR EQ SEVEN.
IF SEVEN EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF SEVEN EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF TWO EQ FIVE AND FIVE EQ EIGHT.
IF EIGHT EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF EIGHT EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF THREE EQ SIX AND SIX EQ NINE.
IF NINE EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF NINE EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF ONE EQ FIVE AND FIVE EQ NINE.
IF NINE EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF NINE EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF SEVEN EQ FIVE AND FIVE EQ THREE.
IF THREE EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF THREE EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
IF FOUR EQ FIVE AND FIVE EQ SIX.
IF SIX EQ 'X'.
WRITE:/ 'Player 1 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ELSEIF SIX EQ 'O'.
WRITE:/ 'Player 2 Wins!'.
WIN_FLAG = 'X'.
SKIP 2.
ENDIF.
ENDIF.
ENDFORM. "check_who_wins

*-----------------------------------------------------------*
* AT USER-COMMAND *
*-----------------------------------------------------------*
AT USER-COMMAND.

IF SY-UCOMM EQ 'BACK'.
SET SCREEN 0.
LEAVE PROGRAM.
ELSE.
IF WIN_FLAG EQ SPACE.
IF FLAG = '1'.
PLAYER_ONE = SY-LISEL+12(1).
PERFORM BOARD USING FLAG PLAYER_ONE FLAG_OK.
IF FLAG_OK = 'X'.
FLAG = '2'.
ENDIF.
ELSE.
SEED = CL_ABAP_RANDOM=>SEED( ).
RANDOM = CL_ABAP_RANDOM=>CREATE( SEED ).
PLAYER_TWO = RANDOM->INTINRANGE( LOW = 1 HIGH = 9 ).
PERFORM BOARD USING FLAG PLAYER_TWO FLAG_OK.
IF FLAG_OK = 'X'.
FLAG = '1'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.

Espero que les guste y si pueden, mejorenlo -:)

Saludos,

Blag.

6 comments:

Unknown said...

Ese Alvaro, todo un geek... quien se pone a programar un michi mientras espera su orden de transporte??? jaja solo tu compare, si que te gusta programar!

Alvaro "Blag" Tejada Galindo said...

Lennon:

-:) No puedo evitarlo...Llevo la programación en la sangre...Y eso que mis amigos del SDN programan el triple que yo -:O Soy calichín comparado con ellos -:P

Saludos,

Blag.

Carlos Agreda said...

Jeje, me paso algo similar pero por ausencia de proyectos :P, tb hice un Tres en raya relativamente pequeño (con respecto a código).
Estoy implementándole la heurística para que siempre gane.
Ojala lo puedan chekear.

Tb está en proyecto el SPACE INVADERS, ni bien lo termine, lo paso.

Carlos Agreda said...

Jaja, me olvide de dejar e link.
ahi va. http://carlosagreda.blogspot.com/2008/02/tres-en-raya-para-abap.html

Alvaro "Blag" Tejada Galindo said...

Carlos, acabo de comentar en tu blog...Realmente me ha sorprendido tu implementación...Es bastante creativa y concreta -:) Espero ver más trabajos tuyos.

Saludos,

Blag.

Carlos Agreda said...

Jeje, gracias Alvaro. Lo que puede hacer la falta de proyecto o la espera de un transporte no? jajaja.
Saludos.