Minesweeper Das bekannte Spiel Minesweeper in der

Anuncio
Minesweeper
Das bekannte Spiel Minesweeper in der SAP-Version. Leider ist alles in spanisch gehalten. Für das
Spielen ist es nicht relevant, aber im Sourcecode ist es schon merkwürdig, wenn man nicht weiss,
wofür ein Variablenname stehen könnte…
Minesweeper
REPORT zz_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>’.
*&———————————————————————*
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,”
boton_on(17)
VALUE ‘<pisando
Numero de linea para el boton
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,”
conta_radar TYPE i,”
Icono adjunto al boton
Contador de bombas limitrofes a la celda
conta_heridas TYPE i,”
conta_detect TYPE i,”
Contador de errores
Contador de celdas marcadas como detectadas
conta_general TYPE i,”
conta_detect + conta_heridas
cell_name LIKE dd03d-fieldname,”
Nombre de una celda
fila
TYPE i,”
Fila de una celda
columna
TYPE i,”
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 AT /posini(longitud). NEW-LINE.
ENDDO.
SKIP TO LINE line_msg.” ———————————
msg_1 = ‘Bombas pisadas: 0
mensaje
‘.
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 ‘QF05_RANDOM_INTEGER’
EXPORTING
ran_int_max = 10
ran_int_min = 1
IMPORTING
ran_int
= fila
EXCEPTIONS
OTHERS
= 2.
MOVE fila TO char2.
CONCATENATE ‘BOMB_ITAB-‘ char2 INTO fieldname.
*————————————————————— Columna
CALL FUNCTION ‘QF05_RANDOM_INTEGER’
EXPORTING
ran_int_max = 10
ran_int_min = 1
IMPORTING
ran_int
= columna
EXCEPTIONS
OTHERS
= 1.
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 ‘QF05_RANDOM_INTEGER’
EXPORTING
RAN_INT_MAX
= 10
RAN_INT_MIN
= 1
IMPORTING
RAN_INT
= fila
EXCEPTIONS
OTHERS
= 2.
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
Descargar