• 用ABAP语言写的扫雷游戏


    1. REPORT ztest_mine_bom NO STANDARD PAGE HEADING LINE-SIZE 125.
    2. INCLUDE <icon>.
    3. CONSTANTS:
    4. " >> board cell values
    5. blank_hidden TYPE c VALUE '0',
    6. blank_marked TYPE c VALUE 'm',
    7. blank_opened TYPE c VALUE '.',
    8. bomb_hidden TYPE c VALUE '*',
    9. bomb_marked TYPE c VALUE 'M',
    10. bomb_opened TYPE c VALUE '&',
    11. endgame_bomb_boom TYPE c VALUE 'X',
    12. endgame_bomb_missmark TYPE c VALUE '@',
    13. border TYPE c VALUE '#',
    14. " >> game state
    15. game_in VALUE '1',
    16. game_over VALUE '2',
    17. game_win VALUE '3'.
    18. DATA:
    19. board(9999) TYPE c, " 2D board, x_size * y_size + borders
    20. ofs TYPE i, " board[ofs] = cell unique ID
    21. min TYPE i, " board[min] .. board[max]
    22. max TYPE i,
    23. rdx TYPE i, " = 2 + width of board
    24. rdy TYPE i, " = 2 + height of board
    25. square TYPE i, " = x_size * y_size = visible area
    26. square2 TYPE i, " = rdx * rdy = visible area + border
    27. range TYPE i, " = max - min + 1
    28. rest TYPE i, " = square - bomb_cnt = empty cells to invent
    29. game TYPE c, " gamestate = 1,2,3
    30. game_size TYPE c, " B=Beginner, I=Interm, E=Expert, C=Custom
    31. game_time(5) TYPE c, " seconds
    32. b_left(4) TYPE c. " unmarked bombs left
    33. " >> eight directions: North, South, East, West, NE, NW, SE, SW
    34. DATA: eight_directions TYPE TABLE OF i INITIAL SIZE 8 WITH HEADER LINE .
    35. " >> cells2update list, to track board[] changes
    36. TYPES:
    37. BEGIN OF celltype,
    38. offset(4) TYPE c,
    39. color TYPE c,
    40. END OF celltype.
    41. DATA: cells2update TYPE TABLE OF celltype INITIAL SIZE 1000 WITH HEADER LINE.
    42. " >> misc
    43. CONSTANTS:
    44. x_ofs TYPE i VALUE 1,
    45. y_ofs TYPE i VALUE 5.
    46. DATA:
    47. game_time1 TYPE timestamp, " game begin
    48. game_time2 TYPE timestamp.
    49. " >> high_scores
    50. CONSTANTS:
    51. database_id_prefix(21) TYPE c VALUE 'ABAPMINESWEEPERSCORES'.
    52. TYPES:
    53. BEGIN OF score_line,
    54. user LIKE sy-uname,
    55. time(5) TYPE c,
    56. END OF score_line.
    57. DATA:
    58. high_scores TYPE SORTED TABLE OF score_line
    59. WITH UNIQUE KEY time WITH HEADER LINE,
    60. database_id LIKE indx-srtfd. " export/import to database ID
    61. " >> game difficulty
    62. SELECTION-SCREEN BEGIN OF BLOCK bl_game_difficulty.
    63. SELECTION-SCREEN: BEGIN OF LINE.
    64. SELECTION-SCREEN: COMMENT (23) hstitle1.
    65. SELECTION-SCREEN: END OF LINE.
    66. SELECTION-SCREEN: BEGIN OF LINE.
    67. PARAMETERS g1 RADIOBUTTON GROUP one
    68. USER-COMMAND radiogroup01.
    69. SELECTION-SCREEN: COMMENT (10) text1.
    70. SELECTION-SCREEN: END OF LINE.
    71. SELECTION-SCREEN: BEGIN OF LINE.
    72. PARAMETERS g2 RADIOBUTTON GROUP one.
    73. SELECTION-SCREEN: COMMENT (12) text2.
    74. SELECTION-SCREEN: END OF LINE.
    75. SELECTION-SCREEN: BEGIN OF LINE.
    76. PARAMETERS g3 RADIOBUTTON GROUP one.
    77. SELECTION-SCREEN: COMMENT (10) text3.
    78. SELECTION-SCREEN: END OF LINE.
    79. SELECTION-SCREEN: BEGIN OF LINE.
    80. PARAMETERS g4 RADIOBUTTON GROUP one.
    81. SELECTION-SCREEN: COMMENT (10) text4.
    82. SELECTION-SCREEN: END OF LINE.
    83. SELECTION-SCREEN: END OF BLOCK bl_game_difficulty.
    84. " >> High Scores table
    85. SELECTION-SCREEN BEGIN OF BLOCK bl_high_scores.
    86. SELECTION-SCREEN: BEGIN OF LINE.
    87. SELECTION-SCREEN: COMMENT (1) dummy1.
    88. SELECTION-SCREEN: END OF LINE.
    89. SELECTION-SCREEN: BEGIN OF LINE.
    90. SELECTION-SCREEN: COMMENT (23) hstitle2.
    91. SELECTION-SCREEN: END OF LINE.
    92. DEFINE displ_hsline.
    93. selection-screen: begin of line.
    94. selection-screen: comment (1) hs1_&1.
    95. selection-screen: comment (12) hs2_&1.
    96. selection-screen: comment (5) hs3_&1.
    97. selection-screen: end of line.
    98. END-OF-DEFINITION.
    99. SELECTION-SCREEN ULINE /1(20).
    100. displ_hsline 0.
    101. SELECTION-SCREEN ULINE /1(20).
    102. displ_hsline 1.
    103. displ_hsline 2.
    104. displ_hsline 3.
    105. displ_hsline 4.
    106. displ_hsline 5.
    107. displ_hsline 6.
    108. displ_hsline 7.
    109. displ_hsline 8.
    110. displ_hsline 9.
    111. SELECTION-SCREEN: END OF BLOCK bl_high_scores.
    112. " >> Window: Custom Game Dimensions
    113. SELECTION-SCREEN BEGIN OF SCREEN 1001.
    114. SELECTION-SCREEN: BEGIN OF LINE.
    115. SELECTION-SCREEN: COMMENT (12) txtcustw.
    116. PARAMETERS: x_size TYPE i DEFAULT '09'.
    117. SELECTION-SCREEN: END OF LINE.
    118. SELECTION-SCREEN: BEGIN OF LINE.
    119. SELECTION-SCREEN: COMMENT (12) txtcusth.
    120. PARAMETERS: y_size TYPE i DEFAULT '09'.
    121. SELECTION-SCREEN: END OF LINE.
    122. SELECTION-SCREEN: BEGIN OF LINE.
    123. SELECTION-SCREEN: COMMENT (12) txtcustb.
    124. PARAMETERS: bomb_cnt TYPE i DEFAULT '10'.
    125. SELECTION-SCREEN: END OF LINE.
    126. SELECTION-SCREEN END OF SCREEN 1001.
    127. " >> modify board[ofs] and track changes
    128. DEFINE setcell.
    129. board+ofs(1) = &1.
    130. cells2update-offset = ofs.
    131. cells2update-color = &1.
    132. append cells2update.
    133. if game_time1 is initial.
    134. get time stamp field game_time1.
    135. endif.
    136. END-OF-DEFINITION.
    137. *----------------------------------------------------------------------*
    138. * CLASS cl_my_gui_html_viewer DEFINITION
    139. *----------------------------------------------------------------------*
    140. * Custom HTML contol
    141. *----------------------------------------------------------------------*
    142. CLASS cl_my_gui_html_viewer DEFINITION INHERITING FROM
    143. cl_gui_html_viewer.
    144. PUBLIC SECTION.
    145. METHODS: constructor IMPORTING parent TYPE REF TO cl_gui_container.
    146. METHODS: html_board_update.
    147. PRIVATE SECTION.
    148. METHODS: on_sapevent FOR EVENT sapevent OF cl_gui_html_viewer
    149. IMPORTING action query_table.
    150. DATA: js TYPE STANDARD TABLE OF char255 INITIAL SIZE 1000.
    151. ENDCLASS. "cl_my_gui_html_viewer DEFINITION
    152. DATA:
    153. lo_dock TYPE REF TO cl_gui_docking_container,
    154. lo_cont TYPE REF TO cl_gui_container,
    155. html_control TYPE REF TO cl_my_gui_html_viewer,
    156. wnd_style TYPE i.
    157. INITIALIZATION.
    158. hstitle1 = ' :: GAME DIFFICULTY ::'.
    159. text1 = 'Beginner'.
    160. text2 = 'Intermediate'.
    161. text3 = 'Expert'.
    162. text4 = 'Custom'.
    163. txtcustw = 'Width'.
    164. txtcusth = 'Height'.
    165. txtcustb = 'Bombs'.
    166. hstitle2 = ' :: HIGH SCORES ::'.
    167. hs1_0 = '#'.
    168. hs2_0 = 'user'.
    169. hs3_0 = 'time'.
    170. hs1_1 = '1'.
    171. hs1_2 = '2'.
    172. hs1_3 = '3'.
    173. hs1_4 = '4'.
    174. hs1_5 = '5'.
    175. hs1_6 = '6'.
    176. hs1_7 = '7'.
    177. hs1_8 = '8'.
    178. hs1_9 = '9'.
    179. " >> create controls
    180. wnd_style = cl_gui_control=>ws_thickframe + cl_gui_control=>ws_child.
    181. CREATE OBJECT lo_dock
    182. EXPORTING
    183. repid = sy-cprog
    184. dynnr = sy-dynnr
    185. ratio = 80
    186. side = cl_gui_docking_container=>dock_at_right
    187. name = 'DOCK_CONT'
    188. style = wnd_style.
    189. lo_cont = lo_dock.
    190. CREATE OBJECT html_control
    191. EXPORTING
    192. parent = lo_cont.
    193. " >>
    194. PERFORM game_create USING 'B' x_size y_size bomb_cnt.
    195. PERFORM html_load_gifs.
    196. PERFORM html_show.
    197. AT LINE-SELECTION. " abap-mode, cmd 'PICK'
    198. ADD -1 TO sy-lsind.
    199. IF sy-lisel CS 'switch'.
    200. LEAVE LIST-PROCESSING.
    201. ELSE.
    202. CHECK game = game_in.
    203. PERFORM cell_get_clicked CHANGING ofs.
    204. CHECK ofs > 0.
    205. PERFORM cell_open USING ofs.
    206. IF rest <= 0 AND game = game_in.
    207. GET TIME STAMP FIELD game_time2.
    208. game_time = game_time2 - game_time1.
    209. PERFORM game_ok.
    210. ENDIF.
    211. PERFORM game_print_abap.
    212. ENDIF.
    213. AT PF09. " abap-mode, cmd 'MARK'
    214. ADD -1 TO sy-lsind.
    215. IF game = game_in.
    216. PERFORM cell_get_clicked CHANGING ofs.
    217. CHECK ofs > 0.
    218. PERFORM cell_mark USING ofs.
    219. PERFORM game_print_abap.
    220. ENDIF.
    221. AT SELECTION-SCREEN OUTPUT.
    222. IF lines( cells2update ) > 0.
    223. " here: switch back from abap to html
    224. CALL METHOD html_control->html_board_update( ).
    225. ENDIF.
    226. AT SELECTION-SCREEN ON RADIOBUTTON GROUP one.
    227. CHECK sy-ucomm = 'RADIOGROUP01'.
    228. IF g1 = 'X'.
    229. PERFORM game_create USING 'B' 09 09 10.
    230. ELSEIF g2 = 'X'.
    231. PERFORM game_create USING 'I' 16 16 40.
    232. ELSEIF g3 = 'X'.
    233. PERFORM game_create USING 'E' 30 16 99.
    234. ELSE.
    235. CALL SELECTION-SCREEN 1001
    236. STARTING AT 20 4.
    237. PERFORM game_create USING 'C' x_size y_size bomb_cnt.
    238. ENDIF.
    239. PERFORM html_show.
    240. *&---------------------------------------------------------------------*
    241. *& Form game_print_abap.
    242. *&---------------------------------------------------------------------*
    243. FORM game_print_abap.
    244. DATA: ofs TYPE i, ch TYPE c.
    245. SKIP TO LINE 3.
    246. WRITE: / 'Bombs left: ', b_left NO-ZERO.
    247. ofs = rdx.
    248. SKIP TO LINE y_ofs.
    249. DO y_size TIMES.
    250. WRITE AT x_ofs '|' NO-GAP.
    251. DO x_size TIMES.
    252. ADD 1 TO ofs.
    253. ch = board+ofs(1).
    254. CASE ch.
    255. WHEN blank_opened.
    256. WRITE: ' '.
    257. WHEN '1' OR '2' OR '3' OR '4' OR '5' OR '6' OR '7' OR '8'.
    258. WRITE: ' ' NO-GAP, ch NO-GAP.
    259. WHEN bomb_marked.
    260. WRITE icon_breakpoint AS ICON NO-GAP.
    261. WHEN blank_marked
    262. OR 'a' OR 'b' OR 'c' OR 'd' OR 'e' OR 'f' OR 'g' OR 'h'.
    263. WRITE icon_breakpoint AS ICON NO-GAP.
    264. WHEN endgame_bomb_missmark.
    265. WRITE icon_breakpoint_disable AS ICON NO-GAP.
    266. WHEN endgame_bomb_boom.
    267. WRITE icon_system_cancel AS ICON NO-GAP.
    268. WHEN bomb_opened. "endgame only
    269. WRITE icon_dummy AS ICON NO-GAP.
    270. WHEN OTHERS.
    271. WRITE: icon_wd_transparent_container AS ICON NO-GAP.
    272. ENDCASE.
    273. ENDDO.
    274. WRITE '|'.
    275. ADD 2 TO ofs.
    276. NEW-LINE.
    277. ENDDO.
    278. WRITE: AT x_ofs '' NO-GAP, ' switch back ' COLOR 2 HOTSPOT ON.
    279. IF game = game_over.
    280. WRITE: /, /4 'Game over', /, /.
    281. ELSEIF game = game_win.
    282. WRITE: /, /4 'You win', /, /.
    283. ELSE.
    284. SKIP 3.
    285. ENDIF.
    286. WRITE: / ' open: double-click'.
    287. WRITE: / ' mark: click and press F9'.
    288. ENDFORM. "game_print_abap
    289. *&---------------------------------------------------------------------*
    290. *& Form CELL_MARK
    291. *&---------------------------------------------------------------------*
    292. * mark a cell with 'bomb sign'
    293. *----------------------------------------------------------------------*
    294. FORM cell_mark USING VALUE(ofs) TYPE i.
    295. DATA: ch TYPE c.
    296. ch = board+ofs(1).
    297. CASE ch.
    298. WHEN blank_hidden. setcell blank_marked. ADD -1 TO b_left.
    299. WHEN blank_marked. setcell blank_hidden. ADD +1 TO b_left.
    300. WHEN bomb_hidden. setcell bomb_marked. ADD -1 TO b_left.
    301. WHEN bomb_marked. setcell bomb_hidden. ADD +1 TO b_left.
    302. WHEN 'A' OR 'B' OR 'C' OR 'D' OR 'E' OR 'F' OR 'G' OR 'H'.
    303. TRANSLATE ch TO LOWER CASE.
    304. setcell ch. ADD -1 TO b_left.
    305. WHEN 'a' OR 'b' OR 'c' OR 'd' OR 'e' OR 'f' OR 'g' OR 'h'.
    306. TRANSLATE ch TO UPPER CASE.
    307. setcell ch. ADD +1 TO b_left.
    308. ENDCASE.
    309. ENDFORM. "CELL_MARK
    310. *&---------------------------------------------------------------------*
    311. *& Form cell_open
    312. *&---------------------------------------------------------------------*
    313. * open a cell, at one's own risk
    314. *----------------------------------------------------------------------*
    315. FORM cell_open USING VALUE(ofs) TYPE i.
    316. CASE board+ofs(1).
    317. WHEN blank_hidden.
    318. PERFORM cell_floodfill USING ofs.
    319. WHEN 'A'. setcell '1'. ADD -1 TO rest.
    320. WHEN 'B'. setcell '2'. ADD -1 TO rest.
    321. WHEN 'C'. setcell '3'. ADD -1 TO rest.
    322. WHEN 'D'. setcell '4'. ADD -1 TO rest.
    323. WHEN 'E'. setcell '5'. ADD -1 TO rest.
    324. WHEN 'F'. setcell '6'. ADD -1 TO rest.
    325. WHEN 'G'. setcell '7'. ADD -1 TO rest.
    326. WHEN 'H'. setcell '8'. ADD -1 TO rest.
    327. WHEN '1' OR '2' OR '3' OR '4' OR '5' OR '6' OR '7' OR '8'.
    328. PERFORM cell_open_around USING ofs.
    329. WHEN bomb_hidden.
    330. setcell endgame_bomb_boom.
    331. PERFORM game_lose.
    332. ENDCASE.
    333. ENDFORM. "cell_open
    334. *&---------------------------------------------------------------------*
    335. *& Form cell_get_clicked
    336. *&---------------------------------------------------------------------*
    337. FORM cell_get_clicked CHANGING ofs TYPE i.
    338. DATA: row TYPE i, col TYPE i.
    339. row = sy-curow - y_ofs.
    340. col = ( sy-cucol - x_ofs - 2 ) DIV 2.
    341. ofs = ( 1 + row ) * rdx + col + 1.
    342. IF row < 0 OR row > y_size OR
    343. col < 0 OR col > x_size.
    344. ofs = 0.
    345. ENDIF.
    346. ENDFORM. "cell_get_clicked
    347. DATA: floodfill TYPE TABLE OF i INITIAL SIZE 1000.
    348. *&---------------------------------------------------------------------*
    349. *& Form cell_flood_fill
    350. *&---------------------------------------------------------------------*
    351. * open all adjacent empty cells
    352. *----------------------------------------------------------------------*
    353. FORM cell_floodfill USING VALUE(x) TYPE i.
    354. DATA: ofs TYPE i.
    355. ofs = x + 00. " cell itself
    356. setcell blank_opened. ADD -1 TO rest.
    357. APPEND x TO floodfill.
    358. LOOP AT floodfill INTO x.
    359. LOOP AT eight_directions.
    360. ofs = x + eight_directions.
    361. CASE board+ofs(1).
    362. WHEN blank_hidden.
    363. setcell blank_opened. ADD -1 TO rest.
    364. APPEND ofs TO floodfill.
    365. WHEN 'A'. setcell '1'. ADD -1 TO rest.
    366. WHEN 'B'. setcell '2'. ADD -1 TO rest.
    367. WHEN 'C'. setcell '3'. ADD -1 TO rest.
    368. WHEN 'D'. setcell '4'. ADD -1 TO rest.
    369. WHEN 'E'. setcell '5'. ADD -1 TO rest.
    370. WHEN 'F'. setcell '6'. ADD -1 TO rest.
    371. WHEN 'G'. setcell '7'. ADD -1 TO rest.
    372. WHEN 'H'. setcell '8'. ADD -1 TO rest.
    373. ENDCASE.
    374. ENDLOOP.
    375. ENDLOOP.
    376. REFRESH floodfill.
    377. ENDFORM. "cell_flood_fill
    378. *&---------------------------------------------------------------------*
    379. *& Form cell_open_eight_directions
    380. *&---------------------------------------------------------------------*
    381. * Open up to 8 cells around current one
    382. *----------------------------------------------------------------------*
    383. FORM cell_open_around USING VALUE(x) TYPE i.
    384. DATA: ofs TYPE i.
    385. DATA: value TYPE i.
    386. " 1 >> get cell's VALUE (1 to 8)
    387. value = board+x(1).
    388. " 2 >> look around it, get count of marked
    389. LOOP AT eight_directions.
    390. ofs = x + eight_directions.
    391. CASE board+ofs(1).
    392. WHEN bomb_marked
    393. OR blank_marked
    394. OR 'a' " digit_maked
    395. OR 'b' " ..
    396. OR 'c'
    397. OR 'd'
    398. OR 'e'
    399. OR 'f'
    400. OR 'g'
    401. OR 'h'.
    402. value = value - 1.
    403. ENDCASE.
    404. ENDLOOP.
    405. " 3 >> check its EQness
    406. CHECK value = 0.
    407. " 4 >> here: opening is possible
    408. " 5 >> do open
    409. LOOP AT eight_directions.
    410. ofs = x + eight_directions.
    411. CASE board+ofs(1).
    412. WHEN blank_hidden.
    413. PERFORM cell_floodfill USING ofs.
    414. WHEN 'A'. setcell '1'. ADD -1 TO rest.
    415. WHEN 'B'. setcell '2'. ADD -1 TO rest.
    416. WHEN 'C'. setcell '3'. ADD -1 TO rest.
    417. WHEN 'D'. setcell '4'. ADD -1 TO rest.
    418. WHEN 'E'. setcell '5'. ADD -1 TO rest.
    419. WHEN 'F'. setcell '6'. ADD -1 TO rest.
    420. WHEN 'G'. setcell '7'. ADD -1 TO rest.
    421. WHEN 'H'. setcell '8'. ADD -1 TO rest.
    422. WHEN blank_marked
    423. OR 'a'
    424. OR 'b'
    425. OR 'c'
    426. OR 'd'
    427. OR 'e'
    428. OR 'f'
    429. OR 'g'
    430. OR 'h'.
    431. setcell endgame_bomb_missmark.
    432. WHEN bomb_hidden.
    433. setcell endgame_bomb_boom.
    434. PERFORM game_lose.
    435. ENDCASE.
    436. ENDLOOP.
    437. ENDFORM. "cell_open_eight_directions
    438. *&---------------------------------------------------------------------*
    439. *& Form game_lose
    440. *&---------------------------------------------------------------------
    441. FORM game_lose.
    442. game = game_over.
    443. ADD -1 TO b_left.
    444. " >> show actual bombs
    445. WHILE board(square2) CA '*abcdefghm'. " digit_marked + blank_marked
    446. ofs = sy-fdpos.
    447. IF board+ofs(1) = bomb_hidden. " if = '*'
    448. setcell bomb_opened.
    449. ELSE.
    450. setcell endgame_bomb_missmark.
    451. ENDIF.
    452. ENDWHILE.
    453. MESSAGE s000(su) WITH 'Game over'.
    454. ENDFORM. "game_lose
    455. *&---------------------------------------------------------------------*
    456. *& Form game_ok
    457. *&---------------------------------------------------------------------*
    458. FORM game_ok.
    459. game = game_win.
    460. b_left = 0.
    461. " >> show bombs
    462. WHILE board(square2) CS bomb_hidden.
    463. ofs = sy-fdpos.
    464. setcell bomb_marked.
    465. ENDWHILE.
    466. MESSAGE s000(su) WITH 'You win!' .
    467. CHECK game_size <> 'C'.
    468. PERFORM high_scores_read.
    469. PERFORM high_scores_update.
    470. PERFORM high_scores_show.
    471. ENDFORM. "game_ok
    472. *&---------------------------------------------------------------------*
    473. *& Form game_create
    474. *&---------------------------------------------------------------------*
    475. FORM game_create USING
    476. VALUE(sz) TYPE c
    477. VALUE(x) TYPE i
    478. VALUE(y) TYPE i
    479. VALUE(b) TYPE i.
    480. DATA:
    481. ofs TYPE i,
    482. j TYPE i,
    483. drop_cnt TYPE i,
    484. drop_bombs TYPE c.
    485. DATA:
    486. prng TYPE REF TO cl_abap_random_int,
    487. backgr TYPE c,
    488. foregr TYPE c,
    489. half TYPE i.
    490. game_size = sz.
    491. x_size = x.
    492. y_size = y.
    493. bomb_cnt = b.
    494. CONCATENATE database_id_prefix game_size INTO database_id.
    495. CLEAR:
    496. game_time,
    497. game_time1,
    498. game_time2.
    499. game = game_in.
    500. PERFORM high_scores_read.
    501. PERFORM high_scores_show.
    502. CLEAR: board.
    503. square = x_size * y_size.
    504. IF bomb_cnt > square.
    505. bomb_cnt = square. " limit bombs to 100%
    506. ENDIF.
    507. b_left = bomb_cnt.
    508. rest = square - bomb_cnt. " empty places to invent
    509. rdx = 2 + x_size. " width + left and right border
    510. rdy = 2 + y_size. " height + top and button border
    511. square2 = rdx * rdy.
    512. IF square2 > 9999.
    513. MESSAGE e000(su) WITH 'board too large (9999)'.
    514. ENDIF.
    515. " >> board[9999]'s used space
    516. min = 1 + 1 * rdx. " topleft
    517. max = square2 - rdx - 2. " bottomright
    518. range = max - min + 1.
    519. " >> directions
    520. REFRESH eight_directions.
    521. eight_directions = -1 + rdx * -1. APPEND eight_directions. " NW
    522. eight_directions = 00 + rdx * -1. APPEND eight_directions. " North
    523. eight_directions = +1 + rdx * -1. APPEND eight_directions. " NE
    524. eight_directions = -1 + rdx * 00. APPEND eight_directions. " W
    525. eight_directions = +1 + rdx * 00. APPEND eight_directions. " E
    526. eight_directions = -1 + rdx * +1. APPEND eight_directions. " SW
    527. eight_directions = 00 + rdx * +1. APPEND eight_directions. " S
    528. eight_directions = 01 + rdx * +1. APPEND eight_directions. " SE
    529. " >> bomb placement
    530. " >> speed optimization:
    531. " if bombs < 50%, place bombs randomly
    532. " if bombs > 50%, place spaces randomly
    533. half = x_size * y_size DIV 2.
    534. IF bomb_cnt < half.
    535. drop_bombs = 'X'. " straight order
    536. drop_cnt = bomb_cnt.
    537. backgr = blank_hidden.
    538. foregr = bomb_hidden.
    539. ELSE.
    540. drop_bombs = ' '. " reversed order
    541. drop_cnt = rest.
    542. backgr = bomb_hidden.
    543. foregr = blank_hidden.
    544. ENDIF.
    545. " >> fill background
    546. ofs = min.
    547. DO range TIMES.
    548. board+ofs(1) = backgr.
    549. ADD 1 TO ofs.
    550. ENDDO.
    551. " >> horizontal border
    552. DO rdx TIMES.
    553. ofs = sy-index - 1.
    554. board+ofs(1) = border.
    555. ofs = square2 - sy-index .
    556. board+ofs(1) = border.
    557. ENDDO.
    558. " >> vertical border
    559. DO y_size TIMES.
    560. ofs = rdx * sy-index.
    561. board+ofs(1) = border.
    562. ofs = sy-index * rdx + rdx - 1.
    563. board+ofs(1) = border.
    564. ENDDO.
    565. " >> actual placement
    566. DATA: seed TYPE i.
    567. seed = cl_abap_random=>seed( ).
    568. prng = cl_abap_random_int=>create(
    569. seed = seed min = min max = max ).
    570. DO drop_cnt TIMES.
    571. DO.
    572. ofs = prng->get_next( ).
    573. CASE board+ofs(1).
    574. WHEN foregr OR border.
    575. " skip used cells
    576. WHEN OTHERS.
    577. EXIT. " found unused (BG 1 2 3 4 5 6 7 8)
    578. ENDCASE.
    579. ENDDO.
    580. board+ofs(1) = foregr.
    581. IF drop_bombs = 'X'.
    582. " add 1 point to cells around
    583. LOOP AT eight_directions.
    584. j = ofs + eight_directions.
    585. CASE board+j(1).
    586. WHEN bomb_hidden OR border.
    587. WHEN OTHERS.
    588. board+j(1) = board+j(1) + 1.
    589. ENDCASE.
    590. ENDLOOP.
    591. ELSE.
    592. " get 1 point from every bomb around
    593. LOOP AT eight_directions.
    594. j = ofs + eight_directions.
    595. CASE board+j(1).
    596. WHEN bomb_hidden.
    597. board+ofs(1) = board+ofs(1) + 1.
    598. ENDCASE.
    599. ENDLOOP.
    600. ENDIF.
    601. ENDDO.
    602. " >> hide digits
    603. TRANSLATE board(square2) USING '1A2B3C4D5E6F7G8H'.
    604. ENDFORM. "game_create
    605. *----------------------------------------------------------------------*
    606. * CLASS my_cl_gui_html_viewer IMPLEMENTATION
    607. *----------------------------------------------------------------------*
    608. *
    609. *----------------------------------------------------------------------*
    610. CLASS cl_my_gui_html_viewer IMPLEMENTATION.
    611. METHOD constructor.
    612. DATA: myevent_tab TYPE cntl_simple_events,
    613. myevent TYPE cntl_simple_event.
    614. CALL METHOD super->constructor(
    615. parent = parent
    616. uiflag = html_control->uiflag_noiemenu
    617. ).
    618. myevent-appl_event = 'X'.
    619. myevent-eventid = html_control->m_id_sapevent.
    620. APPEND myevent TO myevent_tab.
    621. myevent-eventid = html_control->m_id_navigate_complete.
    622. APPEND myevent TO myevent_tab.
    623. CALL METHOD html_control->set_registered_events(
    624. events = myevent_tab
    625. ).
    626. SET HANDLER me->on_sapevent FOR html_control.
    627. ENDMETHOD. "constructor
    628. " >> HTML callback event
    629. METHOD on_sapevent. " arguments: action, query_table[]
    630. DATA: param LIKE LINE OF query_table.
    631. DATA: cell_ofs TYPE i.
    632. READ TABLE query_table WITH KEY name = 'ID' INTO param.
    633. IF sy-subrc EQ 0. cell_ofs = param-value. ENDIF.
    634. READ TABLE query_table WITH KEY name = 'TIME' INTO param.
    635. IF sy-subrc EQ 0. game_time = param-value. ENDIF.
    636. CASE action.
    637. WHEN 'click'. " left-click
    638. CHECK game = game_in.
    639. PERFORM cell_open USING cell_ofs.
    640. IF rest <= 0 AND game = game_in.
    641. PERFORM game_ok.
    642. ENDIF.
    643. CALL METHOD me->html_board_update( ).
    644. WHEN 'mouseup'. " right-click
    645. CHECK game = game_in.
    646. PERFORM cell_mark USING cell_ofs.
    647. CALL METHOD me->html_board_update( ).
    648. WHEN 'newgame'.
    649. PERFORM game_create USING game_size x_size y_size bomb_cnt.
    650. PERFORM html_show.
    651. WHEN 'switch'.
    652. LEAVE TO LIST-PROCESSING.
    653. SET PF-STATUS space.
    654. PERFORM game_print_abap.
    655. ENDCASE.
    656. ENDMETHOD. "on_sapevent
    657. " >> transport board[]'s changes (saved in cells2update[]), to HTML
    658. METHOD html_board_update.
    659. DATA: ofs TYPE i, new TYPE i, len TYPE i, end TYPE i.
    660. DATA: buf TYPE string.
    661. DATA: jsline LIKE LINE OF js.
    662. " >> convert cells2update[] to plain string
    663. CONCATENATE LINES OF cells2update INTO buf SEPARATED BY '|'.
    664. CONDENSE buf NO-GAPS.
    665. " >> convert plain string to JavaScript code
    666. " and pack it to HTML_VIEWER's compatible table
    667. ofs = 0.
    668. end = strlen( buf ).
    669. WHILE ofs < end.
    670. new = ofs + 249. " 255 - strlen ( b+=""; ) is 249
    671. IF new > end. "
    672. len = end - ofs.
    673. ELSE.
    674. len = 249.
    675. ENDIF.
    676. CONCATENATE 'b+="' buf+ofs(len) '";' INTO jsline.
    677. APPEND jsline TO js.
    678. ofs = ofs + len.
    679. ENDWHILE.
    680. CONCATENATE 'updateCells(' game ',"' b_left+1 '")' INTO jsline.
    681. APPEND jsline TO js.
    682. " >> actual transfer
    683. CALL METHOD me->set_script( script = js[] ).
    684. CALL METHOD me->execute_script( ).
    685. " >>
    686. REFRESH js.
    687. REFRESH cells2update.
    688. ENDMETHOD. "html_board_update
    689. ENDCLASS. "cl_my_gui_html_viewer IMPLEMENTATION
    690. *&---------------------------------------------------------------------*
    691. *& Form html_create
    692. *&---------------------------------------------------------------------*
    693. * text
    694. *----------------------------------------------------------------------*
    695. * -->S text
    696. *----------------------------------------------------------------------*
    697. FORM html_create TABLES html.
    698. DATA: html_str TYPE string, s TYPE string,
    699. table1 TYPE TABLE OF char255 WITH HEADER LINE INITIAL SIZE 150.
    700. IF 1 = 2.
    701. " CALL FUNCTION 'WS_UPLOAD'
    702. " EXPORTING
    703. " filename = 'C:\SAP\game\source.html'
    704. " filetype = 'ASC'
    705. " TABLES
    706. " data_tab = html[]
    707. " EXCEPTIONS
    708. " OTHERS = 1.
    709. " CHECK sy-subrc EQ 0.
    710. "
    711. " CONCATENATE LINES OF html INTO html_str SEPARATED BY '~'.
    712. ELSE.
    713. " >> create html
    714. CONCATENATE
    715. ''
    716. '" content="text/html">'
    717. ''
    718. ''
    719. '">'
    720. '
      '
    721. '
      '
    722. '
    723. '
    724. '
    725. '
    726. '
    727. '
    728. '
    729. '
    730. '
    731. 0
      ">
      0
      '
    732. '
      '
    733. ''
    734. '
      '
  • '
    '
  • ''
  • ''
  • INTO html_str SEPARATED BY '~'.
  • ENDIF.
  • CONDENSE html_str.
  • " >> patch html with game parameters
  • DATA: xstr(4) TYPE c, ystr(4) TYPE c.
  • WRITE x_size TO xstr NO-GROUPING.
  • WRITE y_size TO ystr NO-GROUPING.
  • CONCATENATE 'DX=' xstr ',DY=' ystr ',BB="' b_left '";' INTO s.
  • REPLACE FIRST OCCURRENCE OF
  • '/*VARIABLES_INITIALIZATION_HERE_DONT_DELETE*/'
  • IN html_str WITH s.
  • IF sy-subrc <> 0.
  • MESSAGE e000(su) WITH 'html template is broken'.
  • ENDIF.
  • " >> performance improvement: condense html to width 255,
  • " to reduce whitespaces sent to client
  • SPLIT html_str AT '~' INTO TABLE table1.
  • DATA: ofs TYPE i, len TYPE i, nex TYPE i.
  • REFRESH html.
  • ofs = 0.
  • LOOP AT table1.
  • len = strlen( table1 ).
  • CHECK len > 0.
  • nex = ofs + len.
  • IF nex < 255.
  • html+ofs(len) = table1.
  • ofs = nex.
  • ELSE.
  • APPEND html.
  • html = table1.
  • ofs = len.
  • ENDIF.
  • ENDLOOP.
  • APPEND html.
  • ENDFORM. "html_create
  • *&---------------------------------------------------------------------*
  • *& Form load_graphics
  • *&---------------------------------------------------------------------*
  • * create GIF-images from scratch
  • *----------------------------------------------------------------------*
  • FORM html_load_gifs.
  • PERFORM html_load_gif USING 'open0.gif'
  • 'R0lGODlhEAAQAIAAAHt7e729vSH5BAAAAAAALAAAAAAQABAAA'
  • 'AIdhI9pwe0PnnRxzmphlniz7oGbmJGWeXmU2qAcyxQAOw=='
  • '' '' '' ''.
  • PERFORM html_load_gif USING 'open1.gif'
  • 'R0lGODlhEAAQAJEAAAAA/3t7e729vQAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAIpjI9pwu0fnnRRAiCruxg+3lEbmFlX+Z1eGjZaw6'
  • 'EMGLsjLU7Tq9v9UwAAOw==' '' '' ''.
  • PERFORM html_load_gif USING 'open2.gif'
  • 'R0lGODlhEAAQAJEAAAB7AHt7e729vQAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAItjI9pwu0fnnSRgYsvtbm3ijkhU02jUIon+ngbt3'
  • '4wMJFzR9sCnsm1lPrphI0CADs=' '' '' ''.
  • PERFORM html_load_gif USING 'open3.gif'
  • 'R0lGODlhEAAQAJEAAHt7e729vf8AAAAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAIshI9pwe0PnnQxiIsxZbmLVk0aE0pjUFrd5niseI'
  • 'ETF5O0V6O3K89S6tMFHQUAOw==' '' '' ''.
  • PERFORM html_load_gif USING 'open4.gif'
  • 'R0lGODlhEAAQAJEAAAAAe3t7e729vQAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAIujI9pwu0fnnSxgSsuoE5n3FTfNnKMV4anxoJC1b'
  • 'bqhDLiU79Tau/5vZsFTcNGAQA7' '' '' ''.
  • PERFORM html_load_gif USING 'open5.gif'
  • 'R0lGODlhEAAQAJEAAHsAAHt7e729vQAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAIpjI9pwu0fnnRRgItzq7mDzWATaF0jw3kmqYro6Q'
  • 'rVFKcte5MntUO9UwAAOw==' '' '' ''.
  • PERFORM html_load_gif USING 'open6.gif'
  • 'R0lGODlhEAAQAJEAAAB7e3t7e729vQAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAIsjI9pwu0fnnSRgYsvtTlvgU1NFYoC2ZUMmmorBz'
  • 'gqK7sn3I5NG+sm9AMGGwUAOw==' '' '' ''.
  • PERFORM html_load_gif USING 'open7.gif'
  • 'R0lGODlhEAAQAJEAAAAAAHt7e729vQAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAIqjI9pwu0fnnRRgItzq7mDPTEYGI5MJZlneVGTuq'
  • 'at+8CxYwtoSPO9zygAADs=' '' '' ''.
  • PERFORM html_load_gif USING 'open8.gif'
  • 'R0lGODlhEAAQAIAAAHt7e729vSH5BAAAAAAALAAAAAAQABAAA'
  • 'AIphI9pwe0PnnSRqdXqPdliXwXaJ37hRmVXWoZt96onuFpywk'
  • '6Sq8O9UwAAOw==' '' '' ''.
  • PERFORM html_load_gif USING 'blank.gif'
  • 'R0lGODlhEAAQAJEAAHt7e729vf///wAAACH5BAAAAAAALAAAA'
  • 'AAQABAAAAIqlI8ZyRdggpxUAiiqfnjXG3kTmIlWZ3KhSaZqya'
  • 'LxKrYpyF36ruf8DygAADs=' '' '' ''.
  • PERFORM html_load_gif USING 'bombdeath.gif'
  • 'R0lGODlhEAAQAJEAAAAAAHt7e/8AAP///yH5BAAAAAAALAAAA'
  • 'AAQABAAAAI0jI9pwu0fHgNSREnlFRR4zzUb933O5g1DmVlNup'
  • 'YiydbuVIMMmrdjfnrRQL5KK4ipjCqOAgA7' '' '' ''.
  • PERFORM html_load_gif USING 'bombflagged.gif'
  • 'R0lGODlhEAAQAKIAAAAAAHt7e729vf8AAP///wAAAAAAAAAAA'
  • 'CH5BAAAAAAALAAAAAAQABAAAAM8SLrc0nCJoIS92AZK8hjZVl'
  • 'nfF3JkCWJil5osisFXmwnAOWJ5vOOAoM8VLBY1MqMR+bsxJ5u'
  • 'oVAqdWjcJADs=' '' ''.
  • PERFORM html_load_gif USING 'bombmisflagged.gif'
  • 'R0lGODlhEAAQAKIAAAAAAHt7e729vf8AAP///wAAAAAAAAAAA'
  • 'CH5BAAAAAAALAAAAAAQABAAAANEGLrcKjDKGSYEVtQxJI6cBo'
  • 'VAWQqhOA5mmaoCwBEuG1WXzHInVLU6Vgtm4gg/RJ0SiVsVOzf'
  • 'QsRZFQWNSn9UjCTUzkwQAOw==' '' ''.
  • PERFORM html_load_gif USING 'bombrevealed.gif'
  • 'R0lGODlhEAAQAJEAAAAAAHt7e729vf///yH5BAAAAAAALAAAA'
  • 'AAQABAAAAI0jI9pwu0fHgNSREnlFRR4zzUb933O5g1DmVlNup'
  • 'YiydbuVIMMmrdjfnrRQL5KK4ipjCqOAgA7' '' '' ''.
  • PERFORM html_load_gif USING 'facedead.gif'
  • 'R0lGODlhGgAaAKIAAAAAAHt7e729vf//AP///wAAAAAAAAAAA'
  • 'CH5BAAAAAAALAAAAAAaABoAAAOAGLrcziKQSau9M0rMr95CKI'
  • '4kyWRlWp6ECrxvypbvYNvxOI/A7eO6BSrU+/0Aop2g2CsOmsA'
  • 'PiHhz4qqhnRN63UpRVuPx21qKz0jtWZwWlsOwmq+tGG6PWLKI'
  • 'yY4qzWtPSW4kYXNBdWU8cEiIUzRxMoQqlFlCUg+ZDZianZydm'
  • 'gkAOw=='.
  • PERFORM html_load_gif USING 'facesmile.gif'
  • 'R0lGODlhGgAaAKIAAAAAAHt7e729vf//AP///wAAAAAAAAAAA'
  • 'CH5BAAAAAAALAAAAAAaABoAAAN/GLrcziKQSau9M0rMr95CKI'
  • '4kyWRlWp6ECrxvypbvYNvxOI/A7eO6BSrU+/0Aop2gaDyGlMw'
  • 'aLvoUtpY+6UC7/YCwzSZyxwxnvaiyGUi+qXFu9BW8PcblojKM'
  • 'i8Tn111VCkNEZn2CXzxqOUlWLnsyjiqTiC0Pl5hemJsBmpyYC'
  • 'QA7'.
  • PERFORM html_load_gif USING 'facesmile.gif'
  • 'R0lGODlhGgAaAKIAAAAAAHt7e729vf//AP///wAAAAAAAAAAA'
  • 'CH5BAAAAAAALAAAAAAaABoAAAN/GLrcziKQSau9M0rMr95CKI'
  • '4kyWRlWp6ECrxvypbvYNvxOI/A7eO6BSrU+/0Aop2gaDyGlMw'
  • 'aLvoUtpY+6UC7/YCwzSZyxwxnvaiyGUi+qXFu9BW8PcblojKM'
  • 'i8Tn111VCkNEZn2CXzxqOUlWLnsyjiqTiC0Pl5hemJsBmpyYC'
  • 'QA7'.
  • PERFORM html_load_gif USING 'facewin.gif'
  • 'R0lGODlhGgAaAKIAAAAAAHt7AHt7e729vf//AP///wAAAAAAA'
  • 'CH5BAAAAAAALAAAAAAaABoAAAOEKLrczkOUSau9M0rMr95DKI'
  • '4kyWRlWp6FCrxvypYvYdvxOI/A7eO6BSrU+/0Aot2gaDyGlEW'
  • 'YtEZAfkBLnLS6rV5RvTCMWwt/W8tigMoNaM/Ephy5Y8p9dCE6'
  • 'izverFB4XUBwInZNVoWGd4mKhoc5SXouUjKTKphPQlcPnQ2cn'
  • 'qGgoZ4JADs='.
  • ENDFORM. "html_load_gifs
  • *&---------------------------------------------------------------------*
  • *& Form create_gif
  • *&---------------------------------------------------------------------*
  • FORM html_load_gif USING
  • image_name TYPE c
  • s1 TYPE c
  • s2 TYPE c
  • s3 TYPE c
  • s4 TYPE c
  • s5 TYPE c
  • s6 TYPE c.
  • DATA: gif_size TYPE i,
  • gif_base64 TYPE string,
  • gif_binary TYPE xstring,
  • gif_binary_table TYPE TABLE OF w3mime.
  • CONCATENATE s1 s2 s3 s4 s5 s6 INTO gif_base64.
  • CALL FUNCTION 'SSFC_BASE64_DECODE'
  • EXPORTING
  • b64data = gif_base64
  • IMPORTING
  • bindata = gif_binary
  • EXCEPTIONS
  • OTHERS = 1.
  • CHECK sy-subrc EQ 0.
  • PERFORM xstring_to_table
  • TABLES gif_binary_table
  • USING gif_binary
  • CHANGING gif_size.
  • CALL METHOD html_control->load_data
  • EXPORTING
  • url = image_name
  • type = 'image'
  • subtype = 'gif'
  • size = gif_size
  • CHANGING
  • data_table = gif_binary_table
  • EXCEPTIONS
  • dp_invalid_parameter = 1
  • dp_error_general = 2
  • cntl_error = 3
  • OTHERS = 4.
  • ENDFORM. "html_load_gif
  • *---------------------------------------------------------------------*
  • * FORM XSTRING_TO_TABLE *
  • *---------------------------------------------------------------------*
  • * convert xstring to xtable[255]
  • *---------------------------------------------------------------------*
  • FORM xstring_to_table
  • TABLES table1
  • USING buffer TYPE xstring
  • CHANGING binary_size TYPE i.
  • DATA: rows TYPE i, pos TYPE i.
  • FIELD-SYMBOLS: TYPE x.
  • ASSIGN COMPONENT 0 OF STRUCTURE table1 TO TYPE 'X'.
  • binary_size = xstrlen( buffer ).
  • rows = ( binary_size + 255 - 1 ) DIV 255.
  • DO rows TIMES.
  • = buffer+pos.
  • pos = pos + 255.
  • APPEND table1.
  • ENDDO.
  • ENDFORM. "xstring_to_table
  • *&---------------------------------------------------------------------*
  • *& Form html_show
  • *&---------------------------------------------------------------------*
  • FORM html_show.
  • DATA: doc_url(80),
  • html TYPE TABLE OF w3html INITIAL SIZE 150.
  • PERFORM html_create TABLES html.
  • CALL METHOD html_control->load_data(
  • IMPORTING
  • assigned_url = doc_url
  • CHANGING
  • data_table = html
  • EXCEPTIONS
  • dp_invalid_parameter = 1
  • dp_error_general = 2
  • cntl_error = 3
  • OTHERS = 4
  • ).
  • CALL METHOD html_control->show_url( url = doc_url ).
  • ENDFORM. "html_show
  • *---------------------------------------------------------------------*
  • * FORM high_scores_read *
  • *---------------------------------------------------------------------*
  • FORM high_scores_read.
  • REFRESH high_scores.
  • IMPORT lines = high_scores[] FROM DATABASE indx(st) ID database_id.
  • ENDFORM. "high_scores_read
  • *---------------------------------------------------------------------*
  • * FORM high_scores_show *
  • *---------------------------------------------------------------------*
  • FORM high_scores_show.
  • DATA: s(6) TYPE c, line TYPE c.
  • FIELD-SYMBOLS: <fs1> TYPE c, <fs2> TYPE c.
  • DO 9 TIMES.
  • line = sy-index.
  • CONCATENATE 'hs2_' line INTO s.
  • ASSIGN (s) TO <fs1>.
  • CONCATENATE 'hs3_' line INTO s.
  • ASSIGN (s) TO <fs2>.
  • READ TABLE high_scores INDEX sy-index.
  • IF sy-subrc EQ 0.
  • <fs1> = high_scores-user.
  • <fs2> = high_scores-time.
  • ELSE.
  • CLEAR: <fs1>, <fs2>.
  • ENDIF.
  • ENDDO.
  • ENDFORM. "high_scores_show
  • *---------------------------------------------------------------------*
  • * FORM high_scores_update *
  • *---------------------------------------------------------------------*
  • FORM high_scores_update.
  • high_scores-user = sy-uname.
  • WRITE game_time TO high_scores-time RIGHT-JUSTIFIED.
  • INSERT high_scores INTO TABLE high_scores[].
  • LOOP AT high_scores FROM 10.
  • DELETE high_scores INDEX sy-tabix.
  • ENDLOOP.
  • EXPORT lines = high_scores[] TO DATABASE indx(st) ID database_id.
  • ENDFORM. "high_scores_update
  • 相关阅读:
    Unity3D学习笔记6——GPU实例化(1)
    网络编程套接字应用分享【Linux &C/C++ 】【UDP应用 | TCP应用 | TCP&线程池小项目】
    基于Java+SpringBoot+Vue前后端分离医疗报销系统设计和实现
    两相障碍问题的FEM近似及其后验误差估计(Matlab代码实现)
    怎么提取pdf格式中的英语单词
    yolov5分割+检测c++ qt 中部署,以opencv方式(详细代码(全)+复制可用)
    【JavaScript保姆级教程】输出函数和初识变量
    题解:ABC320E - Somen Nagashi
    C++之委托构造函数实例(二百四十三)
    Java基础之浅谈集合
  • 原文地址:https://blog.csdn.net/qq_36952606/article/details/133786242