效果:
代码
*&---------------------------------------------------------------------*
*& Report ZLM_GAME2
*&---------------------------------------------------------------------*
*&
*&---------------------------------------------------------------------*
REPORT ZLM_GAME2 NO STANDARD PAGE HEADING LINE-SIZE 125.
INCLUDE <icon>.
CONSTANTS:
" >> board cell values
blank_hidden TYPE c VALUE '0',
blank_marked TYPE c VALUE 'm',
blank_opened TYPE c VALUE '.',
bomb_hidden TYPE c VALUE '*',
bomb_marked TYPE c VALUE 'M',
bomb_opened TYPE c VALUE '&',
"digit_hidden TYPE c VALUE 'A', " A B C D E F G H
"digit_marked TYPE c VALUE 'a', " a b c d e f g h
"digit_opened TYPE c VALUE '1', " 1 2 3 4 5 6 7 8
endgame_bomb_boom TYPE c VALUE 'X',
endgame_bomb_missmark TYPE c VALUE '@',
border TYPE c VALUE '#',
" >> game state
game_in VALUE '1',
game_over VALUE '2',
game_win VALUE '3'.
DATA:
board(9999) TYPE c, " 2D board, x_size * y_size + borders
ofs TYPE i, " board[ofs] = cell unique ID
min TYPE i, " board[min] .. board[max]
max TYPE i,
rdx TYPE i, " = 2 + width of board
rdy TYPE i, " = 2 + height of board
square TYPE i, " = x_size * y_size = visible area
square2 TYPE i, " = rdx * rdy = visible area + border
range TYPE i, " = max - min + 1
rest TYPE i, " = square - bomb_cnt = empty cells to invent
game TYPE c, " gamestate = 1,2,3
game_size TYPE c, " B=Beginner, I=Interm, E=Expert, C=Custom
game_time(5) TYPE c, " seconds
b_left(4) TYPE c. " unmarked bombs left
" >> eight directions: North, South, East, West, NE, NW, SE, SW
DATA: eight_directions TYPE TABLE OF i INITIAL SIZE 8 WITH HEADER LINE .
" >> cells2update list, to track board[] changes
TYPES:
BEGIN OF celltype,
offset(4) TYPE c,
color TYPE c,
END OF celltype.
DATA: cells2update TYPE TABLE OF celltype INITIAL SIZE 1000 WITH HEADER LINE.
" >> misc
CONSTANTS:
x_ofs TYPE i VALUE 1,
y_ofs TYPE i VALUE 5.
DATA:
game_time1 TYPE timestamp, " game begin
game_time2 TYPE timestamp.
" >> high_scores
CONSTANTS:
database_id_prefix(21) TYPE c VALUE 'ABAPMINESWEEPERSCORES'.
TYPES:
BEGIN OF score_line,
user LIKE sy-uname,
time(5) TYPE c,
END OF score_line.
DATA:
high_scores TYPE SORTED TABLE OF score_line
WITH UNIQUE KEY time WITH HEADER LINE,
database_id LIKE indx-srtfd. " export/import to database ID
" >> game difficulty
SELECTION-SCREEN BEGIN OF BLOCK bl_game_difficulty.
SELECTION-SCREEN: BEGIN OF LINE.
SELECTION-SCREEN: COMMENT (23) hstitle1.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: BEGIN OF LINE.
PARAMETERS g1 RADIOBUTTON GROUP one
USER-COMMAND radiogroup01.
SELECTION-SCREEN: COMMENT (10) text1.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: BEGIN OF LINE.
PARAMETERS g2 RADIOBUTTON GROUP one.
SELECTION-SCREEN: COMMENT (12) text2.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: BEGIN OF LINE.
PARAMETERS g3 RADIOBUTTON GROUP one.
SELECTION-SCREEN: COMMENT (10) text3.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: BEGIN OF LINE.
PARAMETERS g4 RADIOBUTTON GROUP one.
SELECTION-SCREEN: COMMENT (10) text4.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: END OF BLOCK bl_game_difficulty.
" >> High Scores table
SELECTION-SCREEN BEGIN OF BLOCK bl_high_scores.
SELECTION-SCREEN: BEGIN OF LINE.
SELECTION-SCREEN: COMMENT (1) dummy1.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: BEGIN OF LINE.
SELECTION-SCREEN: COMMENT (23) hstitle2.
SELECTION-SCREEN: END OF LINE.
DEFINE displ_hsline.
selection-screen: begin of line.
selection-screen: comment (1) hs1_&1.
selection-screen: comment (12) hs2_&1.
selection-screen: comment (5) hs3_&1.
selection-screen: end of line.
END-OF-DEFINITION.
SELECTION-SCREEN ULINE /1(20).
displ_hsline 0.
SELECTION-SCREEN ULINE /1(20).
displ_hsline 1.
displ_hsline 2.
displ_hsline 3.
displ_hsline 4.
displ_hsline 5.
displ_hsline 6.
displ_hsline 7.
displ_hsline 8.
displ_hsline 9.
SELECTION-SCREEN: END OF BLOCK bl_high_scores.
" >> Window: Custom Game Dimensions
SELECTION-SCREEN BEGIN OF SCREEN 1001.
SELECTION-SCREEN: BEGIN OF LINE.
SELECTION-SCREEN: COMMENT (12) txtcustw.
PARAMETERS: x_size TYPE i DEFAULT '09'.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: BEGIN OF LINE.
SELECTION-SCREEN: COMMENT (12) txtcusth.
PARAMETERS: y_size TYPE i DEFAULT '09'.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN: BEGIN OF LINE.
SELECTION-SCREEN: COMMENT (12) txtcustb.
PARAMETERS: bomb_cnt TYPE i DEFAULT '10'.
SELECTION-SCREEN: END OF LINE.
SELECTION-SCREEN END OF SCREEN 1001.
" >> modify board[ofs] and track changes
DEFINE setcell.
board+ofs(1) = &1.
cells2update-offset = ofs.
cells2update-color = &1.
append cells2update.
if game_time1 is initial.
get time stamp field game_time1.
endif.
END-OF-DEFINITION.
*----------------------------------------------------------------------*
* CLASS cl_my_gui_html_viewer DEFINITION
*----------------------------------------------------------------------*
* Custom HTML contol
*----------------------------------------------------------------------*
CLASS cl_my_gui_html_viewer DEFINITION INHERITING FROM
cl_gui_html_viewer.
PUBLIC SECTION.
METHODS: constructor IMPORTING parent TYPE REF TO cl_gui_container.
METHODS: html_board_update.
PRIVATE SECTION.
METHODS: on_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
IMPORTING action query_table.
DATA: js TYPE STANDARD TABLE OF char255 INITIAL SIZE 1000.
ENDCLASS. "cl_my_gui_html_viewer DEFINITION
DATA:
lo_dock TYPE REF TO cl_gui_docking_container,
lo_cont TYPE REF TO cl_gui_container,
html_control TYPE REF TO cl_my_gui_html_viewer,
wnd_style TYPE i.
INITIALIZATION.
hstitle1 = ' :: GAME DIFFICULTY ::'.
text1 = 'Beginner'.
text2 = 'Intermediate'.
text3 = 'Expert'.
text4 = 'Custom'.
txtcustw = 'Width'.
txtcusth = 'Height'.
txtcustb = 'Bombs'.
hstitle2 = ' :: HIGH SCORES ::'.
hs1_0 = '#'.
hs2_0 = 'user'.
hs3_0 = 'time'.
hs1_1 = '1'.
hs1_2 = '2'.
hs1_3 = '3'.
hs1_4 = '4'.
hs1_5 = '5'.
hs1_6 = '6'.
hs1_7 = '7'.
hs1_8 = '8'.
hs1_9 = '9'.
" >> create controls
wnd_style = cl_gui_control=>ws_thickframe + cl_gui_control=>ws_child.
CREATE OBJECT lo_dock
EXPORTING
repid = sy-cprog
dynnr = sy-dynnr
ratio = 80
side = cl_gui_docking_container=>dock_at_right
name = 'DOCK_CONT'
style = wnd_style.
lo_cont = lo_dock.
CREATE OBJECT html_control
EXPORTING
parent = lo_cont.
" >>
PERFORM game_create USING 'B' x_size y_size bomb_cnt.
PERFORM html_load_gifs.
PERFORM html_show.
AT LINE-SELECTION. " abap-mode, cmd 'PICK'
ADD -1 TO sy-lsind.
IF sy-lisel CS 'switch'.
LEAVE LIST-PROCESSING.
ELSE.
CHECK game = game_in.
PERFORM cell_get_clicked CHANGING ofs.
CHECK ofs > 0.
PERFORM cell_open USING ofs.
IF rest <= 0 AND game = game_in.
GET TIME STAMP FIELD game_time2.
game_time = game_time2 - game_time1.
PERFORM game_ok.
ENDIF.
PERFORM game_print_abap.
ENDIF.
AT PF09. " abap-mode, cmd 'MARK'
ADD -1 TO sy-lsind.
IF game = game_in.
PERFORM cell_get_clicked CHANGING ofs.
CHECK ofs > 0.
PERFORM cell_mark USING ofs.
PERFORM game_print_abap.
ENDIF.
AT SELECTION-SCREEN OUTPUT.
IF LINES( cells2update ) > 0.
" here: switch back from abap to html
CALL METHOD html_control->html_board_update( ).
ENDIF.
AT SELECTION-SCREEN ON RADIOBUTTON GROUP one.
CHECK sy-ucomm = 'RADIOGROUP01'.
IF g1 = 'X'.
PERFORM game_create USING 'B' 09 09 10.
ELSEIF g2 = 'X'.
PERFORM game_create USING 'I' 16 16 40.
ELSEIF g3 = 'X'.
PERFORM game_create USING 'E' 30 16 99.
ELSE.
CALL SELECTION-SCREEN 1001
STARTING AT 20 4.
PERFORM game_create USING 'C' x_size y_size bomb_cnt.
ENDIF.
PERFORM html_show.
*&---------------------------------------------------------------------*
*& Form game_print_abap.
*&---------------------------------------------------------------------*
FORM game_print_abap.
DATA: ofs TYPE i, ch TYPE c.
SKIP TO LINE 3.
WRITE: / 'Bombs left: ', b_left NO-ZERO.
ofs = rdx.
SKIP TO LINE y_ofs.
DO y_size TIMES.
WRITE AT x_ofs '|' NO-GAP.
DO x_size TIMES.
ADD 1 TO ofs.
ch = board+ofs(1).
CASE ch.
WHEN blank_opened.
WRITE: ' '.
WHEN '1' OR '2' OR '3' OR '4' OR '5' OR '6' OR '7' OR '8'.
WRITE: ' ' NO-GAP, ch NO-GAP.
WHEN bomb_marked.
WRITE icon_breakpoint AS ICON NO-GAP.
WHEN blank_marked
OR 'a' OR 'b' OR 'c' OR 'd' OR 'e' OR 'f' OR 'g' OR 'h'.
WRITE icon_breakpoint AS ICON NO-GAP.
WHEN endgame_bomb_missmark.
WRITE icon_breakpoint_disable AS ICON NO-GAP.
WHEN endgame_bomb_boom.
WRITE icon_system_cancel AS ICON NO-GAP.
WHEN bomb_opened. "endgame only
WRITE icon_dummy AS ICON NO-GAP.
WHEN OTHERS.
WRITE: icon_wd_transparent_container AS ICON NO-GAP.
ENDCASE.
ENDDO.
WRITE '|'.
ADD 2 TO ofs.
NEW-LINE.
ENDDO.
WRITE: AT x_ofs '' NO-GAP, ' switch back ' COLOR 2 HOTSPOT ON.
IF game = game_over.
WRITE: /, /4 'Game over', /, /.
ELSEIF game = game_win.
WRITE: /, /4 'You win', /, /.
ELSE.
SKIP 3.
ENDIF.
WRITE: / ' open: double-click'.
WRITE: / ' mark: click and press F9'.
ENDFORM. "game_print_abap
*&---------------------------------------------------------------------*
*& Form CELL_MARK
*&---------------------------------------------------------------------*
* mark a cell with 'bomb sign'
*----------------------------------------------------------------------*
FORM cell_mark USING value(ofs) TYPE i.
DATA: ch TYPE c.
ch = board+ofs(1).
CASE ch.
WHEN blank_hidden. setcell blank_marked. ADD -1 TO b_left.
WHEN blank_marked. setcell blank_hidden. ADD +1 TO b_left.
WHEN bomb_hidden. setcell bomb_marked. ADD -1 TO b_left.
WHEN bomb_marked. setcell bomb_hidden. ADD +1 TO b_left.
WHEN 'A' OR 'B' OR 'C' OR 'D' OR 'E' OR 'F' OR 'G' OR 'H'.
TRANSLATE ch TO LOWER CASE.
setcell ch. ADD -1 TO b_left.
WHEN 'a' OR 'b' OR 'c' OR 'd' OR 'e' OR 'f' OR 'g' OR 'h'.
TRANSLATE ch TO UPPER CASE.
setcell ch. ADD +1 TO b_left.
ENDCASE.
ENDFORM. "CELL_MARK
*&---------------------------------------------------------------------*
*& Form cell_open
*&---------------------------------------------------------------------*
* open a cell, at one's own risk
*----------------------------------------------------------------------*
FORM cell_open USING value(ofs) TYPE i.
CASE board+ofs(1).
WHEN blank_hidden.
PERFORM cell_floodfill USING ofs.
WHEN 'A'. setcell '1'. ADD -1 TO rest.
WHEN 'B'. setcell '2'. ADD -1 TO rest.
WHEN 'C'. setcell '3'. ADD -1 TO rest.
WHEN 'D'. setcell '4'. ADD -1 TO rest.
WHEN 'E'. setcell '5'. ADD -1 TO rest.
WHEN 'F'. setcell '6'. ADD -1 TO rest.
WHEN 'G'. setcell '7'. ADD -1 TO rest.
WHEN 'H'. setcell '8'. ADD -1 TO rest.
WHEN '1' OR '2' OR '3' OR '4' OR '5' OR '6' OR '7' OR '8'.
PERFORM cell_open_around USING ofs.
WHEN bomb_hidden.
setcell endgame_bomb_boom.
PERFORM game_lose.
ENDCASE.
ENDFORM. "cell_open
*&---------------------------------------------------------------------*
*& Form cell_get_clicked
*&---------------------------------------------------------------------*
FORM cell_get_clicked CHANGING ofs TYPE i.
DATA: row TYPE i, col TYPE i.
row = sy-curow - y_ofs.
col = ( sy-cucol - x_ofs - 2 ) DIV 2.
ofs = ( 1 + row ) * rdx + col + 1.
IF row < 0 OR row > y_size OR
col < 0 OR col > x_size.
ofs = 0.
ENDIF.
ENDFORM. "cell_get_clicked
DATA: floodfill TYPE TABLE OF i INITIAL SIZE 1000.
*&---------------------------------------------------------------------*
*& Form cell_flood_fill
*&---------------------------------------------------------------------*
* open all adjacent empty cells
*----------------------------------------------------------------------*
FORM cell_floodfill USING value(x) TYPE i.
DATA: ofs TYPE i.
ofs = x + 00. " cell itself
setcell blank_opened. ADD -1 TO rest.
APPEND x TO floodfill.
LOOP AT floodfill INTO x.
LOOP AT eight_directions.
ofs = x + eight_directions.
CASE board+ofs(1).
WHEN blank_hidden.
setcell blank_opened. ADD -1 TO rest.
APPEND ofs TO floodfill.
WHEN 'A'. setcell '1'. ADD -1 TO rest.
WHEN 'B'. setcell '2'. ADD -1 TO rest.
WHEN 'C'. setcell '3'. ADD -1 TO rest.
WHEN 'D'. setcell '4'. ADD -1 TO rest.
WHEN 'E'. setcell '5'. ADD -1 TO rest.
WHEN 'F'. setcell '6'. ADD -1 TO rest.
WHEN 'G'. setcell '7'. ADD -1 TO rest.
WHEN 'H'. setcell '8'. ADD -1 TO rest.
ENDCASE.
ENDLOOP.
ENDLOOP.
REFRESH floodfill.
ENDFORM. "cell_flood_fill
*&---------------------------------------------------------------------*
*& Form cell_open_eight_directions
*&---------------------------------------------------------------------*
* Open up to 8 cells around current one
*----------------------------------------------------------------------*
FORM cell_open_around USING value(x) TYPE i.
DATA: ofs TYPE i.
DATA: value TYPE i.
" 1 >> get cell's VALUE (1 to 8)
value = board+x(1).
" 2 >> look around it, get count of marked
LOOP AT eight_directions.
ofs = x + eight_directions.
CASE board+ofs(1).
WHEN bomb_marked
OR blank_marked
OR 'a' " digit_maked
OR 'b' " ..
OR 'c'
OR 'd'
OR 'e'
OR 'f'
OR 'g'
OR 'h'.
value = value - 1.
ENDCASE.
ENDLOOP.
" 3 >> check its EQness
CHECK value = 0.
" 4 >> here: opening is possible
" 5 >> do open
LOOP AT eight_directions.
ofs = x + eight_directions.
CASE board+ofs(1).
WHEN blank_hidden.
PERFORM cell_floodfill USING ofs.
WHEN 'A'. setcell '1'. ADD -1 TO rest.
WHEN 'B'. setcell '2'. ADD -1 TO rest.
WHEN 'C'. setcell '3'. ADD -1 TO rest.
WHEN 'D'. setcell '4'. ADD -1 TO rest.
WHEN 'E'. setcell '5'. ADD -1 TO rest.
WHEN 'F'. setcell '6'. ADD -1 TO rest.
WHEN 'G'. setcell '7'. ADD -1 TO rest.
WHEN 'H'. setcell '8'. ADD -1 TO rest.
WHEN blank_marked
OR 'a'
OR 'b'
OR 'c'
OR 'd'
OR 'e'
OR 'f'
OR 'g'
OR 'h'.
setcell endgame_bomb_missmark.
WHEN bomb_hidden.
setcell endgame_bomb_boom.
PERFORM game_lose.
ENDCASE.
ENDLOOP.
ENDFORM. "cell_open_eight_directions
*&---------------------------------------------------------------------*
*& Form game_lose
*&---------------------------------------------------------------------
FORM game_lose.
game = game_over.
ADD -1 TO b_left.
" >> show actual bombs
WHILE board(square2) CA '*abcdefghm'. " digit_marked + blank_marked
ofs = sy-fdpos.
IF board+ofs(1) = bomb_hidden. " if = '*'
setcell bomb_opened.
ELSE.
setcell endgame_bomb_missmark.
ENDIF.
ENDWHILE.
MESSAGE s000(su) WITH 'Game over'.
ENDFORM. "game_lose
字数限制,请继续阅读扫雷代码2