Use este código para criar e jogar Campo Minado em ABAP!
*&============================================================== *& Developed by ROMAN LOPEZ NAVARRO * *& https://personales.com/espana/madrid/abap/ * *& https://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.-: La casilla se marca con el numero de bombas que * rodean a dicha casilla. * 2.- : 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 ' '. *&---------------------------------------------------------------------* REPORT ZPC_TESTEG3 NO STANDARD PAGE HEADING. INCLUDE . CONSTANTS: LINE_INI TYPE I VALUE 2," Primera linea de comienzo de escritura POSINI TYPE I VALUE 4," Justificacion a la izquierda del tablero * NUM_BOMB TYPE I VALUE 15," Numero de bombas en el tablero * MAX_HERI TYPE I VALUE 1," Numero de errores permitidos 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 ' ', BOTON_OFF(17) VALUE ' ', 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: , , , . 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 ." ----------- Tabla tablero ctual CONCATENATE 'BIS_' CELL_NAME INTO STR_TMP. ASSIGN (STR_TMP) TO ." -------------- Tabla bombas pisadas CONCATENATE 'BOMB_' CELL_NAME INTO STR_TMP. ASSIGN (STR_TMP) TO ." ------ 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 NE BOMBA AND NE DETECT. MODIFY LINE SY-LILLI FIELD VALUE FROM DETECT FIELD FORMAT COLOR COL_POSITIVE. = 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 = DETECT. SUBTRACT 1 FROM CONTA_DETECT. ENDIF. * Si la celda es una bomba, marcarla con una ' B ' IF = 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 . POSITION POSINI. WRITE: NUMFILA NO-GAP RIGHT-JUSTIFIED. WRITE: SY-VLINE NO-GAP. DO COLUMNAS TIMES." ------------------------------ Columnas ASSIGN COMPONENT SY-INDEX OF STRUCTURE TO . WRITE: HOTSPOT NO-GAP, SY-VLINE NO-GAP. ENDDO. ULINE at /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 . IF IS INITIAL. = 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. = CONTA_RADAR. * SY-LILLI = LINE_INI * ( FILA + 1 ). MODIFY LINE SY-LILLI FIELD VALUE FROM CONTA_RADAR FIELD FORMAT 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 . IF = 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 NE BOMBA. * Marcar la bomba en el tablero = BOMBA. MODIFY LINE SY-LILLI FIELD VALUE FROM FIELD FORMAT 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: , . 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 . * Se comprueba que la celda que se ha se¤alado como 'D' - Detectada, * realmente contiene una bomba. IF = DETECT. CONCATENATE 'BOMB_ITAB-' FILA_CHAR3 '-' COLUMNA_CHAR3 INTO STR_TMP. CONDENSE STR_TMP NO-GAPS. ASSIGN (STR_TMP) TO . IF 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