Enterprise Resource Planning Portal ERPGenie.COM Enterprise Resource Planning Portal

   Advertise | BLOG

Web ERPGenie.COM

Home | Vote for us |

ERPGenie.COM -> SAP Technical -> ABAP -> Example code -> Minesweeper

*&==============================================================
*&                Developed by ROMAN LOPEZ NAVARRO                  *
*&           http://personales.com/espana/madrid/abap/              *
*&           http://www.geocities.com/romlopabap/                   *
*&==============================================================
*&---------------------------------------------------------------------*
*& Report ZBUSCAMIN                                                 *
*&---------------------------------------------------------------------*
* Una celda marcada como bomba ' B ' no admite ser marcada como detecta-
* da ' D ' ya que implicitamente esta detectada.
* Una vez que el juego acabo no se muestran mas mensajes aunque si se
* permite seguir explorando las celdas ocultas.
* Si algunas de las celdas marcadas como detectadas son incorrectas, es-
* tas se muestran en un nuevo listado.
* Evidentemente NUM_BOMB debe ser superior o igual a MAX_HERI.
* El boton que aparece debajo del tablero indica la accion actual del
* usuario, y que puede ser una de las dos siguientes:
* 1.- <pisando bombas> : La casilla se marca con el numero de bombas que
*                        rodean a dicha casilla.
* 2.- <marcando bombas>: La casilla se marca con una < D > (aunque el
*                        jugador se haya equivocado y no haya bomba).
* Para marcar bombas (detectar bombas) hay que hacer clic en el boton
* hasta que aparezca el texto '<marcando bombas>'.
*&---------------------------------------------------------------------*
   REPORT ZBUSCAMIN NO STANDARD PAGE HEADING.
   INCLUDE <icon>.
   CONSTANTS:
     LINE_INI TYPE I VALUE 2,"       Primera linea de comienzo de escritura
     POSINI TYPE I VALUE 4,"       Justificacion a la izquierda del tablero
     FILAS TYPE I VALUE 10,"                    Numero de filas del tablero
     COLUMNAS TYPE I VALUE 10,"              Numero de columnas del tablero
     BOMBA(3) VALUE ' B ',"                           Simbolo para la bomba
     DETECT(3) VALUE ' D ',"                   Simbolo para bomba detectada
     LINE_MSG TYPE I VALUE 25,"           Numero de linea para los mensajes
     LINE_BOTON TYPE I VALUE 27,"             Numero de linea para el boton
     BOTON_ON(17)  VALUE '<pisando  bombas>',
     BOTON_OFF(17) VALUE '<marcando bombas>',
     ICON_ON  LIKE ICONS-L2 VALUE '@1A@',
     ICON_OFF LIKE ICONS-L2 VALUE '@1C@',
     ICON_ERR LIKE ICONT-ID VALUE '@3C@'.
   DATA:
     MSG_1(45),"                                                    Mensaje
     GAME_OVER,"                                  Flag de partida terminada
     STR_TMP(255),"                                Variable string temporal
     BOTON(17),"                                            Texto del boton
     ICON_BOTON LIKE ICONT-ID,"                      Icono adjunto al boton
     CONTA_RADAR TYPE I,"          Contador de bombas limitrofes a la celda
     CONTA_HERIDAS TYPE I,"                             Contador de errores
     CONTA_DETECT TYPE I,"      Contador de celdas marcadas como detectadas
     CONTA_GENERAL TYPE I,"                    conta_detect + conta_heridas
     CELL_NAME LIKE DD03D-FIELDNAME,"                   Nombre de una celda
     FILA      LIKE DATATYPE-INTEGER2,"                   Fila de una celda
     COLUMNA   LIKE DATATYPE-INTEGER2,"                Columna de una celda
     FILA_CHAR2(2),
     COLUMNA_CHAR2(2).
   DATA:
     BEGIN OF ITAB_LET,
       1(3), 2(3), 3(3), 4(3), 5(3), 6(3), 7(3), 8(3), 9(3), 10(3),
     END OF ITAB_LET,
* Estructura con todas las celdas del tablero
     BEGIN OF ITAB,
       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,
* Estructura con las bombas pisadas
     BIS_ITAB LIKE ITAB,
* Estructura con todas las bombas calculadas iniciales
     BOMB_ITAB LIKE ITAB.
   FIELD-SYMBOLS: <fs1>, <fs2>, <fs3>, <fs4>.
   SELECTION-SCREEN BEGIN OF BLOCK BLOQUE1 WITH FRAME TITLE TITULO1.
     SELECTION-SCREEN: BEGIN OF LINE,
       COMMENT 1(16) COMENT1,
       POSITION 20.
       PARAMETERS NUM_BOMB(2) TYPE N DEFAULT 15.
     SELECTION-SCREEN END OF LINE.
     SELECTION-SCREEN: BEGIN OF LINE,
       COMMENT 1(18) COMENT2.
       POSITION 20.
       PARAMETERS MAX_HERI(2) TYPE N DEFAULT 1.
     SELECTION-SCREEN END OF LINE.
   SELECTION-SCREEN END OF BLOCK BLOQUE1.
************************************************************************
*                             INITIALIZATION                        *
************************************************************************
   INITIALIZATION.
     TITULO1 = 'Opciones de usuario'.
     COMENT1 = 'Numero de bombas'.
     COMENT2 = 'Errores permitidos'.
************************************************************************
*                          START-OF-SELECTION                       *
************************************************************************
   START-OF-SELECTION.
     PERFORM DISPLAY_TABLERO.
     PERFORM ASIGNAR_BOMBAS.
************************************************************************
*                         AT LINE-OF-SELECTION                      *
************************************************************************
   AT LINE-SELECTION.
     GET CURSOR FIELD CELL_NAME.
*----------------------------------------------------------------------*
*                      Cambiar el texto del  boton                   *
*----------------------------------------------------------------------*
* Solo se permite si la partida no ha terminado. Cuando una partida ha
* terminado el boton queda permanentemente en estado ON.
     IF CELL_NAME = 'BOTON' AND GAME_OVER IS INITIAL.
       PERFORM CHANGE_BOTON.
     ENDIF.
*----------------------------------------------------------------------*
*     Obtener el valor de la celda seleccionada en todas las tablas *
*----------------------------------------------------------------------*
     CHECK CELL_NAME CS 'ITAB-'.
     ASSIGN (CELL_NAME) TO <fs1>." ------------------- Tabla tablero actual
     CONCATENATE 'BIS_' CELL_NAME INTO STR_TMP.
     ASSIGN (STR_TMP) TO <fs2>." --------------------- Tabla bombas pisadas
     CONCATENATE 'BOMB_' CELL_NAME INTO STR_TMP.
     ASSIGN (STR_TMP) TO <fs3>." --------------- Tabla con todas las bombas
     SUBTRACT 1 FROM SY-LSIND.
*&====================================================================&*
*&                           Detectar bomba                           &*
*&             Marcar con una 'D' la celda seleccionada               &*
*&====================================================================&*
     IF BOTON = BOTON_OFF.
*   Si el juego ha terminado no permitir detectar mas bombas (para evi-
*   tar mensajes cruzados de la rutina de deteccion). Sobra, porque el
*   boton solo puede estar en OFF si la partida no ha acabado.
*   CHECK GAME_OVER IS INITIAL.
*   Comprobar que no es una bomba ya pisada ni ya detectada
       CHECK <fs1> NE BOMBA AND <fs1> NE DETECT.
       MODIFY LINE SY-LILLI FIELD VALUE  <fs1> FROM DETECT
                            FIELD FORMAT <fs1> COLOR COL_POSITIVE.
       <fs1> = DETECT.
       ADD 1 TO CONTA_DETECT.
       CONTA_GENERAL = CONTA_HERIDAS + CONTA_DETECT.
       IF CONTA_GENERAL = NUM_BOMB.
         PERFORM CHECK_SUCCESS.
       ENDIF.
       EXIT.
     ENDIF.
*&====================================================================&*
*&                            Pisar celdas                            &*
*&  Muestra si la celda es una bomba o bien las bombas que la rodean  &*
*&====================================================================&*
     IF <fs1> = DETECT. SUBTRACT 1 FROM CONTA_DETECT. ENDIF.
* Si la celda es una bomba, marcarla con una ' B '
     IF <fs3> = BOMBA.
       PERFORM X_BOMBA.
* Si la celda no es una bomba, mostrar las bombas limitrofes
     ELSE.
       PERFORM OBTAIN_COORDENADAS.
       PERFORM OBTAIN_LIMITS.
     ENDIF.
     SET CURSOR 0 0.
*&---------------------------------------------------------------------*
*&      Form  DISPLAY_TABLERO
*&---------------------------------------------------------------------*
   FORM DISPLAY_TABLERO.
     DATA: CABLET(255), LONGITUD TYPE I, NUMFILA(2), N TYPE I.
     SKIP TO LINE LINE_INI.
     CABLET = '  | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10|'.
     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 TO <fs1>.
       POSITION POSINI.
       WRITE: NUMFILA NO-GAP RIGHT-JUSTIFIED.
       WRITE: SY-VLINE NO-GAP.
     DO COLUMNAS TIMES." ----------------------------------------- Columnas
         ASSIGN COMPONENT SY-INDEX OF STRUCTURE <fs1> TO <fs2>.
         WRITE: <fs2> HOTSPOT NO-GAP,
                SY-VLINE NO-GAP.
       ENDDO.
       ULINE /POSINI(LONGITUD). NEW-LINE.
     ENDDO.
     SKIP TO LINE LINE_MSG." -------------------------------------- Mensaje
     MSG_1 = 'Bombas pisadas: 0  '.
     WRITE AT: POSINI MSG_1 INTENSIFIED OFF,
               SY-LINSZ SPACE.
     SKIP 1.
     ICON_BOTON = ICON_ON." ------------------------------- Icono del boton
     WRITE AT POSINI ICON_BOTON AS ICON.
     BOTON = BOTON_ON." ----------------------------------- Texto del boton
     CLEAR N.
     N = POSINI + 4.
     WRITE AT N BOTON HOTSPOT COLOR COL_TOTAL.
   ENDFORM.                    " DISPLAY_TABLERO
*&---------------------------------------------------------------------*
*&      Form  ASIGNAR_BOMBAS
*&---------------------------------------------------------------------*
* Llena la tabla BOMB_ITAB con las bombas calculadas
*&---------------------------------------------------------------------*
   FORM ASIGNAR_BOMBAS.
     DATA: CHAR2(2) TYPE C, FIELDNAME(255), CONTA_BOMBAS TYPE I.
     PERFORM INI_SEMILLA.
     WHILE CONTA_BOMBAS LT NUM_BOMB.
*------------------------------------------------------------------ Fila
       CALL FUNCTION 'RANDOM_I2'
            EXPORTING RND_MIN = 1   RND_MAX   = 10
            IMPORTING RND_VALUE = FILA.
       MOVE FILA TO CHAR2.
       CONCATENATE 'BOMB_ITAB-' CHAR2 INTO FIELDNAME.
*--------------------------------------------------------------- Columna
       CALL FUNCTION 'RANDOM_I2'
            EXPORTING RND_MIN = 1   RND_MAX   = 10
            IMPORTING RND_VALUE = COLUMNA.
       MOVE COLUMNA TO CHAR2.
       CONCATENATE FIELDNAME '-' CHAR2 INTO FIELDNAME.
       ASSIGN (FIELDNAME) TO <fs1>.
       IF <fs1> IS INITIAL.
         <fs1> = BOMBA.
         ADD 1 TO CONTA_BOMBAS.
       ENDIF.
     ENDWHILE.
   ENDFORM.                    " ASIGNAR_BOMBAS
*&---------------------------------------------------------------------*
*&      Form  INI_SEMILLA
*&---------------------------------------------------------------------*
* Asegura que la semilla sera aleatoria.
*----------------------------------------------------------------------*
   FORM INI_SEMILLA.
     DO 5 TIMES.
       CALL FUNCTION 'RANDOM_I2'
            EXPORTING RND_MIN = 1   RND_MAX   = 10
            IMPORTING RND_VALUE = FILA.
     ENDDO.
   ENDFORM.                    " INI_SEMILLA
*&---------------------------------------------------------------------*
*&      Form  OBTAIN_COORDENADAS
*&---------------------------------------------------------------------*
   FORM OBTAIN_COORDENADAS.
     DATA  STRING_COMPONENTES LIKE DD03D-FIELDNAME OCCURS 0.
     SPLIT CELL_NAME AT '-' INTO TABLE STRING_COMPONENTES.
     READ TABLE STRING_COMPONENTES INDEX 2 INTO FILA.
     READ TABLE STRING_COMPONENTES INDEX 3 INTO COLUMNA.
   ENDFORM.                    " OBTAIN_COORDENADAS
*&---------------------------------------------------------------------*
*&      Form  OBTAIN_LIMITS
*&---------------------------------------------------------------------*
* Averigua si las celdas limitrofes a la seleccionada tienen una bomba.
*----------------------------------------------------------------------*
   FORM OBTAIN_LIMITS.
     CLEAR CONTA_RADAR.
* Celda N
     FILA_CHAR2    = FILA - 1.
     COLUMNA_CHAR2 = COLUMNA.
     PERFORM RADAR.
* Celda NW
     FILA_CHAR2 = FILA - 1.
     COLUMNA_CHAR2 = COLUMNA - 1.
     PERFORM RADAR.
* Celda NE
     FILA_CHAR2 = FILA - 1.
     COLUMNA_CHAR2 = COLUMNA + 1.
     PERFORM RADAR.
* Celda S
     FILA_CHAR2 = FILA + 1.
     COLUMNA_CHAR2 = COLUMNA.
     PERFORM RADAR.
* Celda SW
    FILA_CHAR2 = FILA + 1.
     COLUMNA_CHAR2 = COLUMNA - 1.
     PERFORM RADAR.
* Celda SE
     FILA_CHAR2 = FILA + 1.
     COLUMNA_CHAR2 = COLUMNA + 1.
     PERFORM RADAR.
* Celda E

     FILA_CHAR2 = FILA.
     COLUMNA_CHAR2 = COLUMNA - 1.
     PERFORM RADAR.
* Celda W

     FILA_CHAR2 = FILA.
     COLUMNA_CHAR2 = COLUMNA + 1.
     PERFORM RADAR.
     <fs1> = CONTA_RADAR.
     MODIFY LINE SY-LILLI FIELD VALUE <fs1>  FROM CONTA_RADAR
                         FIELD FORMAT <fs1> COLOR COL_TOTAL.
   ENDFORM.                    " OBTAIN_LIMITS

*&---------------------------------------------------------------------*
*&      Form  RADAR
*&---------------------------------------------------------------------*
* Averigua si la celda pasada es una bomba.
*----------------------------------------------------------------------*
   FORM RADAR.
     CHECK FILA_CHAR2 NE '0'  AND COLUMNA_CHAR2 NE '0'  AND
           FILA_CHAR2 NE '11' AND COLUMNA_CHAR2 NE '11'.
     CONCATENATE 'BOMB_ITAB-' FILA_CHAR2 '-' COLUMNA_CHAR2 INTO STR_TMP.
     ASSIGN (STR_TMP) TO <fs3>.
     IF <fs3> = BOMBA. ADD 1 TO CONTA_RADAR. ENDIF.
   ENDFORM.                    " RADAR
*&---------------------------------------------------------------------*
*&      Form  X_BOMBA
*&---------------------------------------------------------------------*
* Marca la bomba en el tablero y muestra el mensaje correspondiente.
*----------------------------------------------------------------------*
   FORM X_BOMBA.
    DATA CONTA_CHAR(3).
* Compruebo que la bomba no ha sido pisada con anterioridad
     CHECK <fs1> NE BOMBA.
* Marcar la bomba en el tablero
     <fs1> = BOMBA.
     MODIFY LINE SY-LILLI FIELD VALUE <fs1>  FROM <fs1>
                          FIELD FORMAT <fs1> COLOR COL_NEGATIVE.
* Seguir solo si la partida no esta acabada
     CHECK GAME_OVER IS INITIAL.
     ADD 1 TO CONTA_HERIDAS.
     MOVE CONTA_HERIDAS TO CONTA_CHAR.
     CONCATENATE 'Bombas pisadas: ' CONTA_CHAR INTO MSG_1.
     CLEAR SY-LISEL.
     MODIFY LINE LINE_MSG FIELD VALUE MSG_1.
     IF CONTA_HERIDAS = MAX_HERI.
       MSG_1 =  'Has pisado demasiadas bombas!'.
       MODIFY LINE LINE_MSG FIELD VALUE MSG_1
                            FIELD FORMAT MSG_1 COLOR COL_NEGATIVE
                            INVERSE.
       GAME_OVER = 'X'.
     ENDIF.
    CONTA_GENERAL = CONTA_HERIDAS + CONTA_DETECT.
     IF CONTA_GENERAL = NUM_BOMB.
       PERFORM CHECK_SUCCESS.
     ENDIF.
   ENDFORM.                    " X_BOMBA
*&---------------------------------------------------------------------*
*&      Form  CHANGE_BOTON
*&---------------------------------------------------------------------*
* Cambia el titulo del boton de BOTON_ON a BOTON_OFF y vicevera.
*----------------------------------------------------------------------*
   FORM CHANGE_BOTON.
     DATA: BOTON_TMP LIKE BOTON, COLOR_TMP TYPE I, NEW_ICON LIKE ICONS-L2.
     CASE BOTON.
       WHEN BOTON_ON.
         BOTON = BOTON_OFF. NEW_ICON = ICON_OFF. COLOR_TMP = 5.
       WHEN BOTON_OFF.
         BOTON = BOTON_ON. NEW_ICON = ICON_ON. COLOR_TMP = 3.
     ENDCASE.
     WRITE BOTON TO BOTON_TMP.
     ICON_PREPARE_FOR_MODIFY NEW_ICON.
     MODIFY LINE LINE_BOTON FIELD VALUE BOTON FROM BOTON_TMP
                                        ICON_BOTON FROM NEW_ICON
                            FIELD FORMAT BOTON COLOR = COLOR_TMP.
     SET CURSOR 1 1.
   ENDFORM.                    " CHANGE_BOTON
*&---------------------------------------------------------------------*
*&      Form  CHECK_SUCCESS
*&---------------------------------------------------------------------*
* La partida ha terminado. Comprueba si se ha ganado.
*----------------------------------------------------------------------*
   FORM CHECK_SUCCESS.
     DATA: N TYPE I, M TYPE I, FILA_TMP TYPE I, COLUMNA_TMP TYPE I,
           FILA_TMP_FLOAT TYPE F, FILA_CHAR3(3), COLUMNA_CHAR3(3),
           NEW_ICON LIKE ICONS-L2.
     FIELD-SYMBOLS: <fs5>, <fs6>.
     N = FILAS * COLUMNAS.
* Para mostrar un NUEVO listado con las detecciones incorrectas.
     ADD 1 TO SY-LSIND.
* ---------------------------------------------------------------------*
* FILA_TMP y COLUMNA_TMP guardan las coordenadas de la celda a partir de
* su posicion absoluta (SY-INDEX)
* Por ejemplo, el campo 19 esta en la segunda fila, novena columna; para
* un total de 10 filas y 10 columnas.
*----------------------------------------------------------------------*
     DO N TIMES.
       FILA_TMP_FLOAT = SY-INDEX / COLUMNAS.
       FILA_TMP = CEIL( FILA_TMP_FLOAT ).
       COLUMNA_TMP = SY-INDEX - ( COLUMNAS * FILA_TMP ) + COLUMNAS.
       MOVE: FILA_TMP TO FILA_CHAR3, COLUMNA_TMP TO COLUMNA_CHAR3.
       CONCATENATE 'ITAB-' FILA_CHAR3 '-' COLUMNA_CHAR3
       INTO STR_TMP. CONDENSE STR_TMP NO-GAPS.
       ASSIGN (STR_TMP) TO <fs6>.
*   Se comprueba que la celda que se ha se¤alado como 'D' - Detectada,
*   realmente contiene una bomba.
       IF <fs6> = DETECT.
         CONCATENATE 'BOMB_ITAB-' FILA_CHAR3 '-' COLUMNA_CHAR3
         INTO STR_TMP. CONDENSE STR_TMP NO-GAPS.
         ASSIGN (STR_TMP) TO <fs5>.
         IF <fs5> NE BOMBA.
*       Mensaje(s) de celda(s) incorrecta(s) en nuevo listado.
           CONCATENATE 'La celda ' FILA_CHAR3 '-' COLUMNA_CHAR3
           ' no contenia ninguna bomba' INTO STR_TMP. WRITE STR_TMP.
           MSG_1 = 'Has perdido! Juega otra vez'.
           MODIFY LINE LINE_MSG FIELD VALUE MSG_1
                                FIELD FORMAT MSG_1 COLOR COL_NEGATIVE
                                                   INVERSE.
           GAME_OVER = 'X'." ------------------------------ Partida acabada
         ENDIF.
       ENDIF.
     ENDDO.
* Se pone el boton a ON (para no permitir detectar mas bombas tanto si
* la partida se ha ganado como si se ha perdido)
     NEW_ICON = ICON_ON.
     ICON_PREPARE_FOR_MODIFY NEW_ICON.
     BOTON = BOTON_ON.
     CLEAR SY-LISEL.
     MODIFY LINE LINE_BOTON FIELD VALUE  ICON_BOTON FROM NEW_ICON
                                         BOTON
                            FIELD FORMAT BOTON COLOR = 3.
* Mensaje de partida ganada (no se erro ninguna celda detectada)
     CHECK GAME_OVER IS INITIAL.
     MSG_1 = 'Enhorabuena! Ganaste la partida'.
     MODIFY LINE LINE_MSG FIELD VALUE  MSG_1
                          FIELD FORMAT MSG_1 COLOR COL_POSITIVE INVERSE.
     GAME_OVER = 'X'." ------------------------------------ Partida acabada
   ENDFORM.                    " CHECK_SUCCESS

Contact Us | Polls | Add URL | Contribute | About | Privacy | Terms | Feedback | Help!

Message Board | Discussion Forum | BLOG | Consultants: Post your resume | Companies: Advertise on ERPGenie.COM | Post Job