Juego de los barquitos
*&=====================================================================*
*& Developed by ROMAN LOPEZ NAVARRO *
*& http://personales.com/espana/madrid/abap/ *
*& http://www.geocities.com/romlopabap/ *
*&=====================================================================*
REPORT ZBARCOS NO STANDARD PAGE HEADING.
DATA:
* Variable para imprimir la pantalla
POS TYPE I,
POSINI TYPE I VALUE 4,
FILAS TYPE I VALUE 10,
LONGITUD TYPE I,
CABLET(255),
NUMFILA(2),
* Variables para las funciones RANDOM
INTEGER2 LIKE DATATYPE-INTEGER2,
CHAR0128 LIKE DATATYPE-CHAR0128,
* Atributos de celda
NUMERO LIKE DATATYPE-INTEGER2, " Numero de la casilla actual
LETRA TYPE C, " Letra de la casilla actual
NUMLETRA TYPE I, " Letra convertida a numero
CELL_NAME(25), " Nombre de la celda
* Limites de la celda seleccionada
CELLS_EAST TYPE I, " Casillas libres a la derecha
CELLS_WEST TYPE I, " Casillas libres a la izquierda
CELLS_NORTH TYPE I, " Casillas libres arriba
CELLS_SOUTH TYPE I, " Casillas libres abajo
* Variables para contar los aciertos
CONTA_P1 TYPE I,
CONTA_C1 TYPE I,
CONTA_D1 TYPE I,
CONTA_D2 TYPE I,
CONTA_S1 TYPE I,
CONTA_S2 TYPE I,
CONTA_TOTAL(3) TYPE N,
* Variables varias
NOREPEAT_OBTAINCELL,
COPY_SYINDEX LIKE SY-INDEX,
ALPHABET(26) VALUE 'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
INT_TMP TYPE I,
CHAR1_TMP,
CHAR2_TMP(2),
STR_TMP(255),
PLACED_SHIP,
SHIPNAME(2),
LENSHIP TYPE I.
* Estructuras con todas las celdas
DATA:
BEGIN OF ITAB_LET,
A(3), B(3), C(3), D(3), E(3), F(3), G(3), H(3), I(3), J(3),
END OF ITAB_LET,
BEGIN OF ITAB_NUM,
1 LIKE ITAB_LET, 2 LIKE ITAB_LET, 3 LIKE ITAB_LET,
4 LIKE ITAB_LET, 5 LIKE ITAB_LET, 6 LIKE ITAB_LET,
7 LIKE ITAB_LET, 8 LIKE ITAB_LET, 9 LIKE ITAB_LET,
10 LIKE ITAB_LET,
END OF ITAB_NUM,
BIS_ITAB_NUM LIKE ITAB_NUM.
FIELD-SYMBOLS: , , , .
************************************************************************
* START-OF-SELECTION *
************************************************************************
START-OF-SELECTION.
PERFORM WRITE_TABLA.
PERFORM PLACE_SHIPS.
WRITE SPACE." Linea 26 donde se mostraran los mensajes (por ahora vacia)
SKIP 1.
WRITE ' Turno: 000' INTENSIFIED OFF." Linea 27
************************************************************************
* AT LINE-SELECTION *
************************************************************************
AT LINE-SELECTION.
GET CURSOR FIELD STR_TMP.
ASSIGN (STR_TMP) TO .
SUBTRACT 1 FROM SY-LSIND.
SET CURSOR 1 1." Para que el cursor no moleste la vision de la celda
* Comprobacion de que la celda no ha sido seleccionada anteriormente
CONCATENATE 'BIS_' STR_TMP INTO STR_TMP.
ASSIGN (STR_TMP) TO .
CHECK IS INITIAL.
MOVE 'X' TO .
ADD 1 TO CONTA_TOTAL.
CONCATENATE ' Turno:' CONTA_TOTAL INTO STR_TMP SEPARATED BY SPACE.
MODIFY LINE 27 LINE VALUE FROM STR_TMP LINE FORMAT INTENSIFIED OFF.
*------------------------------------------------------------------ Agua
IF IS INITIAL.
MODIFY LINE SY-LILLI FIELD VALUE FROM ' X'
FIELD FORMAT COLOR COL_POSITIVE.
STR_TMP = ' Agua'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
*--------------------------------------------------------------- Tocado!
ELSE.
STR_TMP = ' Tocado!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
*------------------------------------------------------------ Hundido!!!
CASE .
WHEN 'P1'. ADD 1 TO CONTA_P1.
IF CONTA_P1 = 5. STR_TMP = ' Hundido!!!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
ENDIF.
WHEN 'C1'. ADD 1 TO CONTA_C1.
IF CONTA_C1 = 4. STR_TMP = ' Hundido!!!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
ENDIF.
WHEN 'D1'. ADD 1 TO CONTA_D1.
IF CONTA_D1 = 3. STR_TMP = ' Hundido!!!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
ENDIF.
WHEN 'D2'. ADD 1 TO CONTA_D2.
IF CONTA_D2 = 3. STR_TMP = ' Hundido!!!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
ENDIF.
WHEN 'S1'. ADD 1 TO CONTA_S1.
IF CONTA_S1 = 2. STR_TMP = ' Hundido!!!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
ENDIF.
WHEN 'S2'. ADD 1 TO CONTA_S2.
IF CONTA_S2 = 2. STR_TMP = ' Hundido!!!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
ENDIF.
ENDCASE.
MODIFY LINE SY-LILLI FIELD VALUE FROM ' X'
FIELD FORMAT COLOR COL_NEGATIVE.
ENDIF.
*--------------------------------------------------------- Fin del juego
IF CONTA_P1 = 5 AND CONTA_C1 = 4 AND CONTA_D1 = 3 AND CONTA_D2 = 3 AND
CONTA_S1 = 2 AND CONTA_S2 = 2.
STR_TMP = ' Hundiste la flota enemiga!'.
MODIFY LINE 26 LINE VALUE FROM STR_TMP.
ENDIF.
*&---------------------------------------------------------------------*
*& Form PLACE_SHIPS
*&---------------------------------------------------------------------*
* Coloca todos los barcos en la tabla interna
*----------------------------------------------------------------------*
FORM PLACE_SHIPS.
*---------------------------------------------------------- Portaaviones
CLEAR PLACED_SHIP.
WHILE PLACED_SHIP IS INITIAL.
LENSHIP = 5. SHIPNAME = 'P1'. PERFORM PLACE_SHIP.
ENDWHILE.
*--------------------------------------------------------------- Crucero
CLEAR PLACED_SHIP.
WHILE PLACED_SHIP IS INITIAL.
LENSHIP = 4. SHIPNAME = 'C1'. PERFORM PLACE_SHIP.
ENDWHILE.
*---------------------------------------------------------- Destructor 1
CLEAR PLACED_SHIP.
WHILE PLACED_SHIP IS INITIAL.
LENSHIP = 3. SHIPNAME = 'D1'. PERFORM PLACE_SHIP.
ENDWHILE.
*---------------------------------------------------------- Destructor 2
CLEAR PLACED_SHIP.
WHILE PLACED_SHIP IS INITIAL.
LENSHIP = 3. SHIPNAME = 'D2'. PERFORM PLACE_SHIP.
ENDWHILE.
*----------------------------------------------------------- Submarino 1
CLEAR PLACED_SHIP.
WHILE PLACED_SHIP IS INITIAL.
LENSHIP = 2. SHIPNAME = 'S1'. PERFORM PLACE_SHIP.
ENDWHILE.
*----------------------------------------------------------- Submarino 2
CLEAR PLACED_SHIP.
WHILE PLACED_SHIP IS INITIAL.
LENSHIP = 2. SHIPNAME = 'S2'. PERFORM PLACE_SHIP.
ENDWHILE.
ENDFORM. " PLACE_SHIPS
*&---------------------------------------------------------------------*
*& Form PLACE_SHIP
*&---------------------------------------------------------------------*
* Coloca el barco actual en proceso
*----------------------------------------------------------------------*
FORM PLACE_SHIP.
* Obtencion de una celda vacia (NOREPEAT_OBTAINCELL es un flag que sir-
* ve para saber si la celda no esta vacia en cuyo caso hay que repetir
* la llamada al form OBTAIN_CELL) y de sus limites.
CLEAR NOREPEAT_OBTAINCELL.
WHILE NOREPEAT_OBTAINCELL IS INITIAL.
PERFORM OBTAIN_CELL.
ENDWHILE.
PERFORM OBTAIN_LIMITS.
* Valor aleatorio (1-4) para decidir la secuencia de orientaciones.
CLEAR INTEGER2.
CALL FUNCTION 'RANDOM_I2'
EXPORTING RND_MIN = 1 RND_MAX = 4
IMPORTING RND_VALUE = INTEGER2.
* Colocacion del barco siguiendo la secuencia de orientaciones. Se
* empieza con la primera; si no es posible se prueba con la segunda,
* sino con la tercera y por ultimo con la cuarta.
CLEAR PLACED_SHIP.
CASE INTEGER2.
WHEN 1. " Norte-Sur-Este-Oeste
PERFORM ADJUST_NORTH. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_SOUTH. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_EAST. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_WEST. CHECK PLACED_SHIP IS INITIAL.
WHEN 2. " Sur-Este-Oeste-Norte
PERFORM ADJUST_SOUTH. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_EAST. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_WEST. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_NORTH. CHECK PLACED_SHIP IS INITIAL.
WHEN 3. " Este-Oeste-Norte-Sur
PERFORM ADJUST_EAST. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_WEST. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_NORTH. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_SOUTH. CHECK PLACED_SHIP IS INITIAL.
WHEN 4. " Oeste-Norte-Sur-Este
PERFORM ADJUST_WEST. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_NORTH. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_SOUTH. CHECK PLACED_SHIP IS INITIAL.
PERFORM ADJUST_EAST. CHECK PLACED_SHIP IS INITIAL.
ENDCASE.
ENDFORM. " PLACE_SHIP
*&---------------------------------------------------------------------*
*& Form OBTAIN_CELL
*&---------------------------------------------------------------------*
* Obtiene aleatoriamente las coordenadas de una celda
*----------------------------------------------------------------------*
FORM OBTAIN_CELL.
*---------------------------------------------------------------- Numero
CLEAR INTEGER2.
* Llamo 5 veces a la funcion para que el numero sea realmente aleatorio,
* si solo la llamo una o dos veces los dos primeros numeros de la
* secuencia son siempre los mismos.
DO 5 TIMES.
CALL FUNCTION 'RANDOM_I2'
EXPORTING RND_MIN = 1 RND_MAX = 10
IMPORTING RND_VALUE = INTEGER2.
ENDDO.
NUMERO = INTEGER2.
*----------------------------------------------------------------- Letra
CLEAR CHAR0128.
CALL FUNCTION 'RANDOM_C'
EXPORTING LEN_MIN = 1 LEN_MAX = 1 CHAR_MIN = 64 CHAR_MAX = 73
IMPORTING RND_VALUE = CHAR0128.
LETRA = CHAR0128.
*-------------------------------------------- Conversion Letra -> Numero
SEARCH ALPHABET FOR LETRA.
NUMLETRA = SY-FDPOS.
ADD 1 TO NUMLETRA.
*------------------------------------- Comprobar que la celda esta vacia
MOVE NUMERO TO CHAR2_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' LETRA INTO CELL_NAME.
ASSIGN (CELL_NAME) TO .
IF IS INITIAL.
NOREPEAT_OBTAINCELL = 'X'.
ENDIF.
ENDFORM. " OBTAIN_CELL
*&---------------------------------------------------------------------*
*& Form OBTAIN_LIMITS
*&---------------------------------------------------------------------*
* Obtiene las celdas vacias o libres alrededor de la seleccionada
*----------------------------------------------------------------------*
FORM OBTAIN_LIMITS.
*------------------------------------------------ Celdas libres al Norte
CLEAR COPY_SYINDEX.
INT_TMP = NUMERO.
DO FILAS TIMES.
SUBTRACT 1 FROM INT_TMP.
IF INT_TMP = 0. CELLS_NORTH = SY-INDEX - 1. EXIT. ENDIF.
CHAR2_TMP = INT_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' LETRA INTO CELL_NAME.
ASSIGN (CELL_NAME) TO .
IF NOT IS INITIAL. CELLS_NORTH = SY-INDEX - 1. EXIT. ENDIF.
ENDDO.
*-------------------------------------------------- Celdas libres al Sur
CLEAR COPY_SYINDEX.
INT_TMP = NUMERO.
DO FILAS TIMES.
ADD 1 TO INT_TMP.
IF INT_TMP = 11. CELLS_SOUTH = SY-INDEX - 1. EXIT. ENDIF.
CHAR2_TMP = INT_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' LETRA INTO CELL_NAME.
ASSIGN (CELL_NAME) TO .
IF NOT IS INITIAL. CELLS_SOUTH = SY-INDEX - 1. EXIT. ENDIF.
ENDDO.
*------------------------------------------------- Celdas libres al Este
CLEAR COPY_SYINDEX.
INT_TMP = NUMLETRA - 1.
DO FILAS TIMES.
ADD 1 TO INT_TMP.
IF INT_TMP = 10. CELLS_EAST = SY-INDEX - 1. EXIT. ENDIF.
MOVE: ALPHABET+INT_TMP(1) TO CHAR1_TMP,
NUMERO TO CHAR2_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' CHAR1_TMP INTO CELL_NAME.
ASSIGN (CELL_NAME) TO .
IF NOT IS INITIAL. CELLS_EAST = SY-INDEX - 1. EXIT. ENDIF.
ENDDO.
*------------------------------------------------ Celdas libres al Oeste
CLEAR COPY_SYINDEX.
INT_TMP = NUMLETRA - 1.
DO FILAS TIMES.
SUBTRACT 1 FROM INT_TMP.
IF INT_TMP = -1. CELLS_WEST = SY-INDEX - 1. EXIT. ENDIF.
MOVE: ALPHABET+INT_TMP(1) TO CHAR1_TMP,
NUMERO TO CHAR2_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' CHAR1_TMP INTO CELL_NAME.
ASSIGN (CELL_NAME) TO .
IF NOT IS INITIAL. CELLS_WEST = SY-INDEX - 1. EXIT. ENDIF.
ENDDO.
ENDFORM. " OBTAIN_LIMITS
*&---------------------------------------------------------------------*
*& Form ADJUST_NORTH
*&---------------------------------------------------------------------*
* Intenta colocar el barco orientado al Norte
*----------------------------------------------------------------------*
FORM ADJUST_NORTH.
ADD 1 TO CELLS_NORTH." Para incluir la propia celda seleccionada
IF CELLS_NORTH GE LENSHIP.
MOVE NUMERO TO INT_TMP.
DO LENSHIP TIMES.
MOVE INT_TMP TO CHAR2_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' LETRA INTO CELL_NAME.
CONDENSE CELL_NAME.
ASSIGN (CELL_NAME) TO .
= SHIPNAME.
SUBTRACT 1 FROM INT_TMP.
ENDDO.
PLACED_SHIP = 'X'.
ENDIF.
ENDFORM. " ADJUST_NORTH
*&---------------------------------------------------------------------*
*& Form ADJUST_SOUTH
*&---------------------------------------------------------------------*
* Intenta colocar el barco orientado al Sur
*----------------------------------------------------------------------*
FORM ADJUST_SOUTH.
ADD 1 TO CELLS_SOUTH." Para incluir la propia celda seleccionada
IF CELLS_SOUTH GE LENSHIP.
MOVE NUMERO TO INT_TMP.
DO LENSHIP TIMES.
MOVE INT_TMP TO CHAR2_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' LETRA INTO CELL_NAME.
CONDENSE CELL_NAME.
ASSIGN (CELL_NAME) TO .
= SHIPNAME.
ADD 1 TO INT_TMP.
ENDDO.
PLACED_SHIP = 'X'.
ENDIF.
ENDFORM. " ADJUST_SOUTH
*&---------------------------------------------------------------------*
*& Form ADJUST_EAST
*&---------------------------------------------------------------------*
* Intenta colocar el barco orientado al Este
*----------------------------------------------------------------------*
FORM ADJUST_EAST.
ADD 1 TO CELLS_EAST." Para incluir la propia celda seleccionada
IF CELLS_EAST GE LENSHIP.
MOVE NUMLETRA TO INT_TMP.
SUBTRACT 1 FROM INT_TMP.
DO LENSHIP TIMES.
MOVE: ALPHABET+INT_TMP(1) TO CHAR1_TMP,
NUMERO TO CHAR2_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' CHAR1_TMP INTO CELL_NAME.
CONDENSE CELL_NAME.
ASSIGN (CELL_NAME) TO .
= SHIPNAME.
ADD 1 TO INT_TMP.
ENDDO.
PLACED_SHIP = 'X'.
ENDIF.
ENDFORM. " ADJUST_EAST
*&---------------------------------------------------------------------*
*& Form ADJUST_WEST
*&---------------------------------------------------------------------*
* Intenta colocar el barco orientado al Oeste
*----------------------------------------------------------------------*
FORM ADJUST_WEST.
ADD 1 TO CELLS_WEST." Para incluir la propia celda seleccionada
IF CELLS_WEST GE LENSHIP.
MOVE NUMLETRA TO INT_TMP.
SUBTRACT 1 FROM INT_TMP.
DO LENSHIP TIMES.
MOVE: ALPHABET+INT_TMP(1) TO CHAR1_TMP,
NUMERO TO CHAR2_TMP.
CONCATENATE 'ITAB_NUM-' CHAR2_TMP '-' CHAR1_TMP INTO CELL_NAME.
CONDENSE CELL_NAME.
ASSIGN (CELL_NAME) TO .
= SHIPNAME.
SUBTRACT 1 FROM INT_TMP.
ENDDO.
PLACED_SHIP = 'X'.
ENDIF.
ENDFORM. " ADJUST_WEST
*&---------------------------------------------------------------------*
*& Form WRITE_TABLA
*&---------------------------------------------------------------------*
* text
*----------------------------------------------------------------------*
FORM WRITE_TABLA.
SKIP 3.
CABLET = ' | A | B | C | D | E | F | G | H | I | J |'.
LONGITUD = STRLEN( CABLET ).
WRITE AT POSINI CABLET.
ULINE AT /POSINI(LONGITUD).
NEW-LINE.
DO FILAS TIMES." ------------------------------------------------- Filas
MOVE SY-INDEX TO NUMFILA.
ASSIGN COMPONENT SY-INDEX OF STRUCTURE ITAB_NUM TO .
POSITION POSINI.
WRITE: NUMFILA NO-GAP RIGHT-JUSTIFIED.
WRITE: SY-VLINE NO-GAP.
DO FILAS TIMES." -------------------------------------------- Columnas
ASSIGN COMPONENT SY-INDEX OF STRUCTURE TO .
WRITE: HOTSPOT NO-GAP,
SY-VLINE NO-GAP.
ENDDO.
ULINE /POSINI(LONGITUD). NEW-LINE.
ENDDO.
ENDFORM. " WRITE_TABLA
|