Top Banner

of 33

DEV262 - Evolution of the ABAP Programming Language_exercise_solution

Mar 01, 2016

Download

Documents

RAJA

abap programming
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
  • EVOLUTION OF THE ABAP PROGRAMMING LANGUAGE DEV262

    Exercises / Solutions Karsten Bohlmann, Holger Janz / ABAP Language Team

    These exercises familiarize you with the modern ABAP features that are introduced and

    explained during the presentation part of this workshop.

    A few programs which have been developed without the new ABAP constructs (7.0 style)

    serve as a starting point. Each program implements a popular mini game.

    You are asked to employ modern ABAP in a few places so as to make the source code of

    these mini games more concise and expressive.

    For all exercises the following logon data are used:

    System: TDI [local]

    Client: 001

    User: DEV262

    Password: welcome

    The icon for the SAP GUI Logon can be found on the desktop. The ADT (ABAP

    Development Tools, aka ABAP in Eclipse) can be found in the start menu with the following

    path:

    SAP SAP NetWeaver ABAP Development Tools ABAP in Eclipse DEV262

  • DEV262

    2

    EXERCISE 1: SWEEP THESE MINES In this exercise we work on an implementation of the popular Minesweeper game. Open program

    ZDEV262_EXERCISE1_MINESWEEPER . Start the game and try it out. Then have a look at the source

    code (it is also listed in APPENDIX A of this document).

    Constructor Method

    First lets have a look at the constructor of class game. It builds the initial playing field. Mines are

    placed using the random number generator cl_abap_random_int.

    1. Shorten the source code using inline declaration instead of classical declaration for the

    following local variables: size, level, r, x, y. Similarly, inline-declare local field

    symbols , , , .

    2. Use the CONV operator to eliminate the need for local variable i in the creation of the

    cl_abap_random_int instance.

    3. Eliminate the IF statements which check and set the local variables n (between 2 and 32)

    and level (between 1 and 5). Hint: Use the COND operator or built-in functions nmax /

    nmin.

    Display Method

    Use expressions to rewrite the call of method cl_abap_brwoser=>show_html within the display

    method of class game.

    1. Use the CONV operator directly within the method call such that local variable title is not

    needed anymore.

    2. Use the COND operator directly within the method call such that local variable size is not

    needed for passing the parameter.

    Detect Method

    Use inline declaration for the local variables u, d, l, r.

    Starting the Game

    At START-OF-SELECTION, class game is instantiated and started by calling method display. Use

    operator NEW and method call chaining to write this in one statement without the use of variable

    my_game. Remove the declaration of this variable.

    Check if the game still works! This completes the first exercise. If you still have time and more ideas how to use the new features, you may proceed with the optional part.

    Solution: APPENDIX B

    Optional (if there is time)

    Find further possibilities to rewrite the code of ZDEV262_EXERCISE1_MINESWEEPER.Try to shorten it

    as much as possible. One possible solution can be found in APPENDIX C.

  • DEV262

    3

    EXERCISE 1: GET READY FOR 2048 2048 is a mini puzzle game: Slide numbered tiles on a grid to combine them (two tiles with the same value merge into a new tile with doubled value); you win when you reach a tile with number 2048.

    Program ZDEV262_EXERCISE2_2048 is an ABAP implementation of this game. The task is to

    improve the implementation using modern ABAP. Start the game and try it out. Then have a look at the source code (also listed in APPENDIX D of this document).

    Constructor Method

    The constructor of class game builds the initial playing field. After comment build field, there are two

    nested DO loops. Rewrite this part using nested condition-driven table comprehensions

    VALUE #( FOR UNTIL ).

    Hint: A statement like CONCATENATE a b INTO c. can be rewritten using a string template: c = |{ a }{ b }|.

    Lets Build a Line

    In method build_line, a sequence of two READ statements is used to retrieve an entry of table

    field. Use the table selection operator [ ] and REF #( ) for an equivalent expression

    which goes directly into the APPEND statement.

    Create New Tiles

    In method new_tiles, there is another sequence of two READs waiting for your optimization. Use

    statement ASSIGN with table selection [ ] to rewrite this code in one statement. Local variables

    x and y should no longer be used to derive the coordinates from pos and n.

    Check if the game still works! This completes the second exercise. If you still have time and more ideas how to use the new features, you may proceed with the optional part.

    Solution: APPENDIX E

    Optional (if there is time)

    Find further possibilities to rewrite the code of ZDEV262_EXERCISE2_2048.Try to shorten it as much

    as possible. (Hint: Methods display and build_line can each be reduced to a single statement) One possible solution can be found in APPENDIX F.

  • DEV262

    4

    APPENDIX A: MINESWEEPER WITHOUT EXPRESSIONS PROGRAM ZDEV262_EXERCISE1_MINESWEEPER. CLASS game DEFINITION. PUBLIC SECTION. METHODS: constructor, display. PRIVATE SECTION. TYPES: BEGIN OF t_cell, bomb TYPE abap_bool, " cell contains bomb y/n bombs TYPE i, " # of neighboring bombs state TYPE char1, " [h]idden, [v]isible, [f]lagged END OF t_cell, t_cells TYPE STANDARD TABLE OF t_cell WITH DEFAULT KEY, t_field TYPE STANDARD TABLE OF t_cells WITH DEFAULT KEY. DATA: field TYPE t_field, n TYPE i, " dimension of field bombs TYPE i, " # of existing bombs hidden TYPE i, " # of hidden cells flags TYPE i, " # of flagged cells moves TYPE i, " # of moves over TYPE char1, " game over: [w]in, [d]ead header TYPE string. " HTML header string METHODS: at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action, detect IMPORTING VALUE(x) TYPE i VALUE(y) TYPE i. ENDCLASS. CLASS game IMPLEMENTATION. METHOD constructor. DATA: i TYPE i, j TYPE i, threshold TYPE i. DATA: cells TYPE t_cells, cell TYPE t_cell. DATA: r TYPE REF TO cl_abap_random_int. CONCATENATE ##NO_TEXT `` `a{text-decoration:none;width:13px;height:9px}` `.hid{@#404080} .flg{@red} .bmb{@black}` `.b0{@#e0e0e0} .b1{@lightblue} .b2{@lightgreen} .b3{@orange}` `function setloc(e){window.location=e;}` `` INTO header. REPLACE ALL OCCURRENCES OF `@` IN header WITH `background-color:` ##NO_TEXT. DATA size TYPE i VALUE 10. DATA level TYPE i VALUE 3. cl_demo_input=>add_field( CHANGING field = size ). cl_demo_input=>request( CHANGING field = level ). IF size < 2. n = 2. ELSEIF size > 32. n = 32. ELSE. n = size. ENDIF. " size: 2..32 IF level < 1. level = 1. ELSEIF level > 5.

  • DEV262

    5

    level = 5. ENDIF. " level: 1..5 " place hidden bombs randomly i = sy-uzeit. r = cl_abap_random_int=>create( seed = i min = 0 max = 99 ). threshold = 100 - level * 7. cell-state = 'h'. " initially all cells are hidden DO n TIMES. CLEAR cells. DO n TIMES. CLEAR cell-bomb. i = r->get_next( ). IF i > threshold. cell-bomb = 'X'. ENDIF. APPEND cell TO cells. ENDDO. APPEND cells TO field. ENDDO. " compute neighboring-bombs count for each cell, and overall count DATA: x TYPE i, y TYPE i. FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell, TYPE t_cells, TYPE t_cell. LOOP AT field ASSIGNING . y = sy-tabix. LOOP AT ASSIGNING . IF -bomb = 'X'. bombs = bombs + 1. ELSE. x = sy-tabix. DO 3 TIMES. i = y - 2 + sy-index. CHECK i >= 1 AND i = 1 AND j title. DATA: x TYPE i, y TYPE i. DATA: xn TYPE n LENGTH 2, yn TYPE n LENGTH 2. DATA: b TYPE char1, b_lim TYPE char1. FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell. html = header.

  • DEV262

    6

    LOOP AT field ASSIGNING . y = sy-tabix. yn = y. CONCATENATE html '' INTO html. LOOP AT ASSIGNING . x = sy-tabix. xn = x. WRITE -bombs TO b. b_lim = b. IF b_lim > '3'. b_lim = '3'. ENDIF. " determine CSS style (hid,flg,b0,...,b3) of cell IF over '' AND -bomb = 'X'. style = `bmb`. "cell with bomb (game over) ELSEIF -state = 'f'. style = `flg`. "cell flagged by player ELSEIF -state = 'v'. CONCATENATE 'b' b_lim INTO style. "visible cell ELSEIF over ''. style = `b0`. "empty cell (game over) ELSE. style = `hid`. "hidden cell ENDIF. CONCATENATE html '' b '' INTO html. " bombs value ELSE. " HTML events on cell (left: try; right: flag) CONCATENATE html ##NO_TEXT ` oncontextmenu="setloc('sapevent:flg` 'x' xn 'y' yn `');` `return false;">` INTO html. ENDIF. CONCATENATE html `` INTO html. ENDLOOP. CONCATENATE html `` INTO html. ENDLOOP. CONCATENATE html `` INTO html. IF over = 'd'. CONCATENATE html `*** Bomb - Game over ***` INTO html. ELSEIF over = 'w'. DATA m TYPE string. m = moves. CONDENSE m. CONCATENATE html `Finished in ` m ` moves!` INTO html ##NO_TEXT. ENDIF. CONCATENATE html `` INTO html. DATA size TYPE string. IF n < 20. size = cl_abap_browser=>small. ELSE. size = cl_abap_browser=>medium. ENDIF. title = sy-title. cl_abap_browser=>show_html( title = title size = size format = cl_abap_browser=>portrait

  • DEV262

    7

    context_menu = 'X' html_string = html ). ENDMETHOD. METHOD at_click. DATA: x TYPE i, y TYPE i. FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell. IF over ''. " game is over, final click cl_abap_browser=>close_browser( ). LEAVE PROGRAM. ENDIF. moves = moves + 1. x = action+4(2). y = action+7(2). READ TABLE field INDEX y ASSIGNING . READ TABLE INDEX x ASSIGNING . IF action(3) = 'try'. IF -bomb = 'X'. over = 'd'. " hit bomb -> game over ELSE. detect( x = x y = y ). ENDIF. ELSE. " action(3) = 'flg' IF -state = 'h'. -state = 'f'. flags = flags + 1. hidden = hidden - 1. ELSE. -state = 'h'. flags = flags - 1. hidden = hidden + 1. ENDIF. ENDIF. IF hidden = 0 AND flags = bombs. over = 'w'. " all cells opened, all bombs found -> win ENDIF. display( ). ENDMETHOD. METHOD detect. DATA: u TYPE i, d TYPE i, l TYPE i, r TYPE i. FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell. CHECK x >= 1 AND x = 1 AND y

  • DEV262

    8

    detect( y = d x = r ). ENDMETHOD. ENDCLASS. DATA: my_game TYPE REF TO game. START-OF-SELECTION. CREATE OBJECT my_game. my_game->display( ).

  • DEV262

    9

    APPENDIX B: MINESWEEPER WITH SOME EXPRESSIONS SOLUTION EXERCISE 1 PROGRAM ZDEV262_EXERCISE1_SOLUTION. CLASS game DEFINITION. PUBLIC SECTION. METHODS: constructor, display. PRIVATE SECTION. TYPES: BEGIN OF t_cell, bomb TYPE abap_bool, " cell contains bomb y/n bombs TYPE i, " # of neighboring bombs state TYPE char1, " [h]idden, [v]isible, [f]lagged END OF t_cell, t_cells TYPE STANDARD TABLE OF t_cell WITH DEFAULT KEY, t_field TYPE STANDARD TABLE OF t_cells WITH DEFAULT KEY. DATA: field TYPE t_field, n TYPE i, " dimension of field bombs TYPE i, " # of existing bombs hidden TYPE i, " # of hidden cells flags TYPE i, " # of flagged cells moves TYPE i, " # of moves over TYPE char1, " game over: [w]in, [d]ead header TYPE string. " HTML header string METHODS: at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action, detect IMPORTING VALUE(x) TYPE i VALUE(y) TYPE i. ENDCLASS. CLASS game IMPLEMENTATION. METHOD constructor. DATA: i TYPE i, j TYPE i, threshold TYPE i. DATA: cells TYPE t_cells, cell TYPE t_cell. CONCATENATE ##NO_TEXT `` `a{text-decoration:none;width:13px;height:9px}` `.hid{@#404080} .flg{@red} .bmb{@black}` `.b0{@#e0e0e0} .b1{@lightblue} .b2{@lightgreen} .b3{@orange}` `function setloc(e){window.location=e;}` `` INTO header. REPLACE ALL OCCURRENCES OF `@` IN header WITH `background-color:` ##NO_TEXT. DATA(size) = 10. DATA(level) = 3. cl_demo_input=>add_field( CHANGING field = size ). cl_demo_input=>request( CHANGING field = level ). " size: 2..32 n = nmax( val1 = 2 val2 = nmin( val1 = size val2 = 32 ) ). " level: 1..5 level = nmax( val1 = 1 val2 = nmin( val1 = level val2 = 5 ) ). " place hidden bombs randomly DATA(r) = cl_abap_random_int=>create( seed = CONV i( sy-uzeit ) min = 0 max = 99 ). threshold = 100 - level * 7. cell-state = 'h'. " initially all cells are hidden

  • DEV262

    10

    DO n TIMES. CLEAR cells. DO n TIMES. CLEAR cell-bomb. i = r->get_next( ). IF i > threshold. cell-bomb = 'X'. ENDIF. APPEND cell TO cells. ENDDO. APPEND cells TO field. ENDDO. " compute neighboring-bombs count for each cell, and overall count LOOP AT field ASSIGNING FIELD-SYMBOL(). DATA(y) = sy-tabix. LOOP AT ASSIGNING FIELD-SYMBOL(). IF -bomb = 'X'. bombs = bombs + 1. ELSE. DATA(x) = sy-tabix. DO 3 TIMES. i = y - 2 + sy-index. CHECK i >= 1 AND i = 1 AND j

  • DEV262

    11

    b_lim = b. IF b_lim > '3'. b_lim = '3'. ENDIF. " determine CSS style (hid,flg,b0,...,b3) of cell IF over '' AND -bomb = 'X'. style = `bmb`. "cell with bomb (game over) ELSEIF -state = 'f'. style = `flg`. "cell flagged by player ELSEIF -state = 'v'. CONCATENATE 'b' b_lim INTO style. "visible cell ELSEIF over ''. style = `b0`. "empty cell (game over) ELSE. style = `hid`. "hidden cell ENDIF. CONCATENATE html '' b '' INTO html. " bombs value ELSE. " HTML events on cell (left: try; right: flag) CONCATENATE html ##NO_TEXT ` oncontextmenu="setloc('sapevent:flg` 'x' xn 'y' yn `');` `return false;">` INTO html. ENDIF. CONCATENATE html `` INTO html. ENDLOOP. CONCATENATE html `` INTO html. ENDLOOP. CONCATENATE html `` INTO html. IF over = 'd'. CONCATENATE html `*** Bomb - Game over ***` INTO html. ELSEIF over = 'w'. DATA m TYPE string. m = moves. CONDENSE m. CONCATENATE html `Finished in ` m ` moves!` INTO html ##NO_TEXT. ENDIF. CONCATENATE html `` INTO html. cl_abap_browser=>show_html( title = CONV cl_abap_browser=>title( sy-title ) size = COND #( WHEN n < 20 THEN cl_abap_browser=>small ELSE cl_abap_browser=>medium ) format = cl_abap_browser=>portrait context_menu = 'X' html_string = html ). ENDMETHOD. METHOD at_click. DATA: x TYPE i, y TYPE i. FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell. IF over ''. " game is over, final click cl_abap_browser=>close_browser( ). LEAVE PROGRAM. ENDIF. moves = moves + 1. x = action+4(2). y = action+7(2). READ TABLE field INDEX y ASSIGNING . READ TABLE INDEX x ASSIGNING .

  • DEV262

    12

    IF action(3) = 'try'. IF -bomb = 'X'. over = 'd'. " hit bomb -> game over ELSE. detect( x = x y = y ). ENDIF. ELSE. " action(3) = 'flg' IF -state = 'h'. -state = 'f'. flags = flags + 1. hidden = hidden - 1. ELSE. -state = 'h'. flags = flags - 1. hidden = hidden + 1. ENDIF. ENDIF. IF hidden = 0 AND flags = bombs. over = 'w'. " all cells opened, all bombs found -> win ENDIF. display( ). ENDMETHOD. METHOD detect. FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell. CHECK x >= 1 AND x = 1 AND y display( ).

  • DEV262

    13

    APPENDIX C: MINESWEEPER WITH EXPRESSIONS SOLUTION EXERCISE 1 EXTREME PROGRAM ZDEV262_EXERCISE1_XTREM. CLASS game DEFINITION. PUBLIC SECTION. METHODS: constructor, display. PRIVATE SECTION. TYPES: BEGIN OF t_cell, bomb TYPE abap_bool, " cell contains bomb y/n bombs TYPE i, " # of neighboring bombs state TYPE char1, " [h]idden, [v]isible, [f]lagged END OF t_cell, t_cells TYPE STANDARD TABLE OF t_cell WITH EMPTY KEY, t_field TYPE STANDARD TABLE OF t_cells WITH EMPTY KEY. DATA: field TYPE t_field, n TYPE i, " dimension of field bombs TYPE i, " # of existing bombs hidden TYPE i, " # of hidden cells flags TYPE i, " # of flagged cells moves TYPE i, " # of moves over TYPE char1, " game over: [w]in, [d]ead header TYPE string. " HTML header string METHODS: at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action, detect IMPORTING VALUE(x) TYPE i VALUE(y) TYPE i. ENDCLASS. CLASS game IMPLEMENTATION. METHOD constructor. header = replace( occ = 0 sub = `@` with = `background-color:` val = `` && `a{text-decoration:none;width:13px;height:9px}` && `.hid{@#404080} .flg{@red} .bmb{@black}` && `.b0{@#e0e0e0} .b1{@lightblue} .b2{@lightgreen} .b3{@orange}` && `function setloc(e){window.location=e;}` && `` ) ##NO_TEXT. DATA(size) = 10. DATA(level) = 3. cl_demo_input=>add_field( CHANGING field = size ). cl_demo_input=>request( CHANGING field = level ). " size: 2..32 n = nmax( val1 = 2 val2 = nmin( val1 = size val2 = 32 ) ). " level: 1..5 level = nmax( val1 = 1 val2 = nmin( val1 = level val2 = 5 ) ). DATA(threshold) = 100 - level * 7. " place hidden bombs randomly field = VALUE #( LET r = cl_abap_random_int=>create( seed = CONV i( sy-uzeit ) min = 0 max = 99 ) IN FOR i = 1 UNTIL i > n ( VALUE #( FOR j = 1 UNTIL j > n ( state = 'h' bomb = COND #( WHEN r->get_next( ) > threshold

  • DEV262

    14

    THEN 'X' ) ) ) ) ). " compute neighboring-bombs count for each cell, and overall count LOOP AT field ASSIGNING FIELD-SYMBOL(). DATA(y) = sy-tabix. LOOP AT ASSIGNING FIELD-SYMBOL(). IF -bomb = 'X'. bombs = bombs + 1. ELSE. DATA(x) = sy-tabix. -bombs = REDUCE i( INIT b = 0 FOR i = nmax( val1 = 1 val2 = y - 1 ) WHILE i title( sy-title ) size = COND #( WHEN n < 20 THEN cl_abap_browser=>small ELSE cl_abap_browser=>medium ) format = cl_abap_browser=>portrait context_menu = 'X' html_string = REDUCE string( INIT h = header FOR y = 1 UNTIL y > n NEXT h = h && || && REDUCE string( INIT k = `` FOR x = 1 UNTIL x > n LET c = field[ y ][ x ] " CSS style (hid,flg,bmb,b0,...,b3) of cell style = COND string( WHEN over '' AND c-bomb = 'X' THEN `bmb` " bomb WHEN c-state = 'f' THEN `flg` " flagged WHEN c-state = 'v' " visible THEN |b{ nmin( val1 = c-bombs val2 = 3 ) }| WHEN over '' " empty THEN `b0` ELSE `hid` ) " hidden pos = |x{ x WIDTH = 2 ALIGN = RIGHT PAD = '0' }| & |y{ y WIDTH = 2 ALIGN = RIGHT PAD = '0' }| IN NEXT k = |{ k }{ c-bombs }| " bombs value ELSE " HTML events on cell (left: try; right: flag) | oncontextmenu="setloc('sapevent:flg{ pos }');| & |return false;">| )

  • DEV262

    15

    && `` ) && `` ) && `` && COND #( WHEN over = 'd' THEN `*** Bomb - Game over ***` WHEN over = 'w' THEN |Finished in { moves } moves!| ) && `` ). ENDMETHOD. METHOD at_click. IF over ''. " game is over, final click cl_abap_browser=>close_browser( ). LEAVE PROGRAM. ENDIF. moves = moves + 1. DATA(x) = CONV i( action+4(2) ). DATA(y) = CONV i( action+7(2) ). ASSIGN field[ y ][ x ] TO FIELD-SYMBOL(). IF action(3) = 'try'. IF -bomb = 'X'. over = 'd'. " hit bomb -> game over ELSE. detect( x = x y = y ). ENDIF. ELSE. " action(3) = 'flg' IF -state = 'h'. -state = 'f'. flags = flags + 1. hidden = hidden - 1. ELSE. -state = 'h'. flags = flags - 1. hidden = hidden + 1. ENDIF. ENDIF. IF hidden = 0 AND flags = bombs . over = 'w'. " all cells opened, all bombs found -> win ENDIF. display( ). ENDMETHOD. METHOD detect. CHECK x >= 1 AND x = 1 AND y

  • DEV262

    16

    ENDCLASS. START-OF-SELECTION. NEW game( )->display( ).

  • DEV262

    17

    APPENDIX D: 2048 WITHOUT EXPRESSIONS PROGRAM ZDEV262_EXERCISE2_2048. TYPE-POOLS abap. CLASS game DEFINITION. PUBLIC SECTION. METHODS: constructor, display. PRIVATE SECTION. TYPES: BEGIN OF t_cell, value TYPE i, id TYPE string, born TYPE i, END OF t_cell, t_cells TYPE STANDARD TABLE OF t_cell WITH DEFAULT KEY, t_field TYPE STANDARD TABLE OF t_cells WITH DEFAULT KEY, t_ref TYPE REF TO t_cell, t_refs TYPE STANDARD TABLE OF t_ref WITH DEFAULT KEY. CONSTANTS tile_colors TYPE string VALUE `eee4da ede0c8 f2b179 f59563 f67c5f f65e3b ` & `edcf72 f67c5f edc850 edc53f edc22e` ##NO_TEXT. DATA: rnd TYPE REF TO cl_abap_random_int, field TYPE t_field, n TYPE i, " dimension of field nsq TYPE i, " n * n target TYPE i VALUE 2048, " target value score TYPE i, " current score moves TYPE i, " # of moves header TYPE string, " HTML header string over TYPE string, " game-over message line TYPE t_refs. METHODS: at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action, build_line IMPORTING VALUE(direction) TYPE char1 VALUE(i) TYPE i, move_lines IMPORTING VALUE(direction) TYPE char1 RETURNING VALUE(valid) TYPE abap_bool, move_line RETURNING VALUE(valid) TYPE abap_bool, new_tiles IMPORTING VALUE(factor) TYPE i DEFAULT 1, check_game. ENDCLASS. CLASS game IMPLEMENTATION. METHOD constructor. DATA: size TYPE i VALUE 4, seed TYPE i, limit TYPE i. DATA: x TYPE string, y TYPE string, s TYPE string. DATA: cell TYPE t_cell. FIELD-SYMBOLS TYPE t_cells. cl_demo_input=>add_field( CHANGING field = size ). cl_demo_input=>add_field( CHANGING field = target ). cl_demo_input=>request( ). n = size. IF n < 3. n = 3. ELSEIF n > 8. n = 8.

  • DEV262

    18

    ENDIF. " size: 3..8 nsq = n * n. " target tile value must be a power of 2, at least 8 IF target < 8. target = 8. ENDIF. target = 2 ** ceil( log( target ) / log( 2 ) ). seed = sy-uzeit. limit = nsq - 1. rnd = cl_abap_random_int=>create( seed = seed min = 0 max = limit ). " build field cell-born = -1. DO n TIMES. y = sy-index. CONDENSE y. APPEND INITIAL LINE to field ASSIGNING . DO n TIMES. x = sy-index. CONDENSE x. CONCATENATE y x INTO cell-id. APPEND cell TO . ENDDO. ENDDO. " place initial tiles in field new_tiles( 2 ). " build HTML header with styles for tiles; " cell/font sizes depend on n DATA w TYPE string. w = trunc( 360 / n ). CONDENSE w. DATA w2 TYPE string. w2 = trunc( w / 2 ). CONDENSE w2. DATA w3 TYPE string. w3 = trunc( w / 3 ). CONDENSE w3. DATA w4 TYPE string. w4 = trunc( w / 4 ). CONDENSE w4. header = `` & `.t0{background-color:#cbbdb0}` & `td{border:1px solid bbada0;color:#776e65` & `;text-align:center;vertical-align:center` & `;font-family:'Century Gothic',sans-serif;font-weight:bold`. CONCATENATE header `;width:` w `px;height:` w `px` INTO header. CONCATENATE header `;font-size:` w2 `px}` INTO header. DATA: pow TYPE i VALUE 2, off TYPE i. DO 11 TIMES. s = pow. CONDENSE s. CONCATENATE header `.t` s `{background-color:#` tile_colors+off(6) INTO header. pow = pow * 2. off = off + 7. IF sy-index >= 3. CONCATENATE header `;color:#f9f6f2` INTO header. ENDIF. IF sy-index >= 10. CONCATENATE header `;font-size:` w4 `px` INTO header. ELSEIF sy-index >= 7. CONCATENATE header `;font-size:` w3 `px` INTO header. ENDIF. CONCATENATE header `}` INTO header. ENDDO. CONCATENATE header ##NO_TEXT `div{text-align:center}` & `function okd(e)` & `{c=window.event.keyCode;window.location='sapevent:'+c;}` & `document.onkeydown = okd; `

  • DEV262

    19

    INTO header. SET HANDLER at_click. ENDMETHOD. METHOD display. DATA: title TYPE cl_abap_browser=>title. DATA: html TYPE string, s TYPE string. FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell. s = target. CONCATENATE `Join the numbers and get to the ` s `tile` INTO title ##NO_TEXT. s = score. CONCATENATE header `Score ` s `` & `` INTO html. LOOP AT field ASSIGNING . CONCATENATE html `` INTO html. LOOP AT ASSIGNING . s = -value. CONDENSE s. CONCATENATE html `` s `` INTO html. ENDLOOP. CONCATENATE html `` INTO html. ENDLOOP. IF over IS INITIAL. CONCATENATE html `` & `Use arrow keys to join tiles` INTO html. ELSE. CONCATENATE html `` over `` INTO html. ENDIF. cl_abap_browser=>show_html( title = title size = cl_abap_browser=>small format = cl_abap_browser=>portrait context_menu = 'X' html_string = html ). ENDMETHOD. METHOD at_click. DATA direction TYPE char1. CASE action. WHEN 37. direction = 'L'. WHEN 38. direction = 'U'. WHEN 39. direction = 'R'. WHEN 40. direction = 'D'. ENDCASE. IF over ``. " game is over; leave game with any non-arrow key IF direction IS INITIAL. cl_abap_browser=>close_browser( ). LEAVE PROGRAM. ENDIF. RETURN. ENDIF. IF move_lines( direction ) = abap_true. moves = moves + 1.

  • DEV262

    20

    new_tiles( ). check_game( ). display( ). ENDIF. ENDMETHOD. METHOD check_game. DATA: max_value TYPE i, off TYPE i, idx TYPE i, empty_cell TYPE abap_bool. CONSTANTS dirs TYPE char4 VALUE 'LRUD'. " find highest tile value and check if an empty cell exists FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell, TYPE t_ref, TYPE t_ref. LOOP AT field ASSIGNING . LOOP AT ASSIGNING . IF -value > max_value. max_value = -value. ENDIF. IF -value = 0. empty_cell = abap_true. ENDIF. ENDLOOP. ENDLOOP. " game is won if target value is reached IF max_value >= target. over = moves. CONCATENATE `Finished in ` over `moves!` INTO over ##NO_TEXT. ELSEIF empty_cell IS INITIAL. " no empty cell -> check if stuck: try move in all 4 directions DO 4 TIMES. off = sy-index - 1. DO n TIMES. build_line( direction = dirs+off(1) i = sy-index ). LOOP AT line FROM 2 ASSIGNING . idx = sy-tabix - 1. READ TABLE line INDEX idx ASSIGNING . IF ->value = ->value. RETURN. " found a possible move; game not over ENDIF. ENDLOOP. ENDDO. ENDDO. over = `*** Stuck - Game over ***`. ENDIF. ENDMETHOD. METHOD move_lines. CHECK direction IS NOT INITIAL. DO n TIMES. build_line( direction = direction i = sy-index ). IF move_line( ) = abap_true. valid = abap_true. ENDIF. ENDDO. CLEAR line. ENDMETHOD. METHOD build_line.

  • DEV262

    21

    DATA: x TYPE i, y TYPE i, j TYPE i. DATA: r_cell TYPE t_ref. FIELD-SYMBOLS: TYPE t_cells. " build cell references to line i, starting at end (wrt direction) CLEAR line. j = n + 1. DO n TIMES. j = j - 1. CASE direction. WHEN 'L'. y = i. x = n + 1 - j. WHEN 'R'. y = i. x = j. WHEN 'U'. y = n + 1 - j. x = i. WHEN 'D'. y = j. x = i. ENDCASE. " append reference of cell to line READ TABLE field INDEX y ASSIGNING . READ TABLE INDEX x REFERENCE INTO r_cell. APPEND r_cell TO line. ENDDO. ENDMETHOD. METHOD move_line. DATA: idx TYPE i VALUE 1, next_idx TYPE i VALUE 2. DATA: curr TYPE t_ref, next TYPE t_ref. READ TABLE line INTO curr INDEX 1. WHILE next_idx value > 0. IF curr->value = next->value. curr->value = curr->value * 2. " join tiles next->value = 0. valid = abap_true. score = score + curr->value. idx = idx + 1. " proceed READ TABLE line INTO curr INDEX idx. ELSEIF next->value > 0 OR next_idx = n. idx = idx + 1. " proceed READ TABLE line INTO curr INDEX idx. next_idx = idx. ENDIF. ELSEIF next->value 0. curr->value = next->value. " shift tile to empty cell next->value = 0. valid = abap_true. ENDIF. next_idx = next_idx + 1. ENDWHILE. ENDMETHOD. METHOD new_tiles. " place 1 or more (for n>4) new tiles (* 2 at start of game) DATA: num TYPE i, pos TYPE i, attempts TYPE i, threshold TYPE i. DATA: x type i, y TYPE i.

  • DEV262

    22

    FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell. num = n - 3. IF num < 1. num = 1. ENDIF. num = num * factor. threshold = nsq / 4. DO num TIMES. pos = rnd->get_next( ). attempts = nsq. DO. " try to place new tile at this or next free position y = 1 + pos DIV n. x = 1 + pos MOD n. READ TABLE field INDEX y ASSIGNING . READ TABLE INDEX x ASSIGNING . IF -value = 0. " free position found - tile value: 2 (likelihood 75%) or 4 IF rnd->get_next( ) > threshold. -value = 2. ELSE. -value = 4. ENDIF. " remember when tile was born, to display it as 'new' -born = -1. IF moves > 0. -born = moves. ENDIF. EXIT. ENDIF. pos = ( pos + 1 ) MOD nsq. attempts = attempts - 1. IF attempts = 0. RETURN. ENDIF. ENDDO. ENDDO. ENDMETHOD. ENDCLASS. DATA my_game TYPE REF TO game. START-OF-SELECTION. CREATE OBJECT my_game. my_game->display( ).

  • DEV262

    23

    APPENDIX E: 2048 WITH SOME EXPRESSIONS SOLUTION EXERCISE 2 PROGRAM ZDEV262_EXERCISE2_SOLUTION. TYPE-POOLS abap. CLASS game DEFINITION. PUBLIC SECTION. METHODS: constructor, display. PRIVATE SECTION. TYPES: BEGIN OF t_cell, value TYPE i, id TYPE string, born TYPE i, END OF t_cell, t_cells TYPE STANDARD TABLE OF t_cell WITH DEFAULT KEY, t_field TYPE STANDARD TABLE OF t_cells WITH DEFAULT KEY, t_ref TYPE REF TO t_cell, t_refs TYPE STANDARD TABLE OF t_ref WITH DEFAULT KEY. CONSTANTS tile_colors TYPE string VALUE `eee4da ede0c8 f2b179 f59563 f67c5f f65e3b ` & `edcf72 f67c5f edc850 edc53f edc22e` ##NO_TEXT. DATA: rnd TYPE REF TO cl_abap_random_int, field TYPE t_field, n TYPE i, " dimension of field nsq TYPE i, " n * n target TYPE i VALUE 2048, " target value score TYPE i, " current score moves TYPE i, " # of moves header TYPE string, " HTML header string over TYPE string, " game-over message line TYPE t_refs. METHODS: at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action, build_line IMPORTING VALUE(direction) TYPE char1 VALUE(i) TYPE i, move_lines IMPORTING VALUE(direction) TYPE char1 RETURNING VALUE(valid) TYPE abap_bool, move_line RETURNING VALUE(valid) TYPE abap_bool, new_tiles IMPORTING VALUE(factor) TYPE i DEFAULT 1, check_game. ENDCLASS. CLASS game IMPLEMENTATION. METHOD constructor. DATA: size TYPE i VALUE 4, seed TYPE i, limit TYPE i. DATA: s TYPE string. cl_demo_input=>add_field( CHANGING field = size ). cl_demo_input=>add_field( CHANGING field = target ). cl_demo_input=>request( ). n = size. IF n < 3. n = 3. ELSEIF n > 8. n = 8. ENDIF. " size: 3..8

  • DEV262

    24

    nsq = n * n. " target tile value must be a power of 2, at least 8 IF target < 8. target = 8. ENDIF. target = 2 ** ceil( log( target ) / log( 2 ) ). seed = sy-uzeit. limit = nsq - 1. rnd = cl_abap_random_int=>create( seed = seed min = 0 max = limit ). " build field field = VALUE #( FOR i = 1 UNTIL i > n ( VALUE #( FOR j = 1 UNTIL j > n ( id = |{ i }{ j }| born = -1 ) ) ) ). " place initial tiles in field new_tiles( 2 ). " build HTML header with styles for tiles; " cell/font sizes depend on n DATA w TYPE string. w = trunc( 360 / n ). CONDENSE w. DATA w2 TYPE string. w2 = trunc( w / 2 ). CONDENSE w2. DATA w3 TYPE string. w3 = trunc( w / 3 ). CONDENSE w3. DATA w4 TYPE string. w4 = trunc( w / 4 ). CONDENSE w4. header = `` & `.t0{background-color:#cbbdb0}` & `td{border:1px solid bbada0;color:#776e65` & `;text-align:center;vertical-align:center` & `;font-family:'Century Gothic',sans-serif;font-weight:bold`. CONCATENATE header `;width:` w `px;height:` w `px` INTO header. CONCATENATE header `;font-size:` w2 `px}` INTO header. DATA: pow TYPE i VALUE 2, off TYPE i. DO 11 TIMES. s = pow. CONDENSE s. CONCATENATE header `.t` s `{background-color:#` tile_colors+off(6) INTO header. pow = pow * 2. off = off + 7. IF sy-index >= 3. CONCATENATE header `;color:#f9f6f2` INTO header. ENDIF. IF sy-index >= 10. CONCATENATE header `;font-size:` w4 `px` INTO header. ELSEIF sy-index >= 7. CONCATENATE header `;font-size:` w3 `px` INTO header. ENDIF. CONCATENATE header `}` INTO header. ENDDO. CONCATENATE header ##NO_TEXT `div{text-align:center}` & `function okd(e)` & `{c=window.event.keyCode;window.location='sapevent:'+c;}` & `document.onkeydown = okd; ` INTO header. SET HANDLER at_click. ENDMETHOD. METHOD display. DATA: title TYPE cl_abap_browser=>title. DATA: html TYPE string, s TYPE string. FIELD-SYMBOLS: TYPE t_cells,

  • DEV262

    25

    TYPE t_cell. s = target. CONCATENATE `Join the numbers and get to the ` s `tile` INTO title ##NO_TEXT. s = score. CONCATENATE header `Score ` s `` & `` INTO html. LOOP AT field ASSIGNING . CONCATENATE html `` INTO html. LOOP AT ASSIGNING . s = -value. CONDENSE s. CONCATENATE html `` s `` INTO html. ENDLOOP. CONCATENATE html `` INTO html. ENDLOOP. IF over IS INITIAL. CONCATENATE html `` & `Use arrow keys to join tiles` INTO html. ELSE. CONCATENATE html `` over `` INTO html. ENDIF. cl_abap_browser=>show_html( title = title size = cl_abap_browser=>small format = cl_abap_browser=>portrait context_menu = 'X' html_string = html ). ENDMETHOD. METHOD at_click. DATA direction TYPE char1. CASE action. WHEN 37. direction = 'L'. WHEN 38. direction = 'U'. WHEN 39. direction = 'R'. WHEN 40. direction = 'D'. ENDCASE. IF over ``. " game is over; leave game with any non-arrow key IF direction IS INITIAL. cl_abap_browser=>close_browser( ). LEAVE PROGRAM. ENDIF. RETURN. ENDIF. IF move_lines( direction ) = abap_true. moves = moves + 1. new_tiles( ). check_game( ). display( ). ENDIF. ENDMETHOD. METHOD check_game. DATA: max_value TYPE i, off TYPE i, idx TYPE i,

  • DEV262

    26

    empty_cell TYPE abap_bool. CONSTANTS dirs TYPE char4 VALUE 'LRUD'. " find highest tile value and check if an empty cell exists FIELD-SYMBOLS: TYPE t_cells, TYPE t_cell, TYPE t_ref, TYPE t_ref. LOOP AT field ASSIGNING . LOOP AT ASSIGNING . IF -value > max_value. max_value = -value. ENDIF. IF -value = 0. empty_cell = abap_true. ENDIF. ENDLOOP. ENDLOOP. " game is won if target value is reached IF max_value >= target. over = moves. CONCATENATE `Finished in ` over `moves!` INTO over ##NO_TEXT. ELSEIF empty_cell IS INITIAL. " no empty cell -> check if stuck: try move in all 4 directions DO 4 TIMES. off = sy-index - 1. DO n TIMES. build_line( direction = dirs+off(1) i = sy-index ). LOOP AT line FROM 2 ASSIGNING . idx = sy-tabix - 1. READ TABLE line INDEX idx ASSIGNING . IF ->value = ->value. RETURN. " found a possible move; game not over ENDIF. ENDLOOP. ENDDO. ENDDO. over = `*** Stuck - Game over ***`. ENDIF. ENDMETHOD. METHOD move_lines. CHECK direction IS NOT INITIAL. DO n TIMES. build_line( direction = direction i = sy-index ). IF move_line( ) = abap_true. valid = abap_true. ENDIF. ENDDO. CLEAR line. ENDMETHOD. METHOD build_line. DATA: x TYPE i, y TYPE i, j TYPE i. " build cell references to line i, starting at end (wrt direction) CLEAR line. j = n + 1. DO n TIMES. j = j - 1. CASE direction. WHEN 'L'.

  • DEV262

    27

    y = i. x = n + 1 - j. WHEN 'R'. y = i. x = j. WHEN 'U'. y = n + 1 - j. x = i. WHEN 'D'. y = j. x = i. ENDCASE. " append reference of cell to line APPEND ref #( field[ y ][ x ] ) TO line. ENDDO. ENDMETHOD. METHOD move_line. DATA: idx TYPE i VALUE 1, next_idx TYPE i VALUE 2. DATA: curr TYPE t_ref, next TYPE t_ref. READ TABLE line INTO curr INDEX 1. WHILE next_idx value > 0. IF curr->value = next->value. curr->value = curr->value * 2. " join tiles next->value = 0. valid = abap_true. score = score + curr->value. idx = idx + 1. " proceed READ TABLE line INTO curr INDEX idx. ELSEIF next->value > 0 OR next_idx = n. idx = idx + 1. " proceed READ TABLE line INTO curr INDEX idx. next_idx = idx. ENDIF. ELSEIF next->value 0. curr->value = next->value. " shift tile to empty cell next->value = 0. valid = abap_true. ENDIF. next_idx = next_idx + 1. ENDWHILE. ENDMETHOD. METHOD new_tiles. " place 1 or more (for n>4) new tiles (* 2 at start of game) DATA: num TYPE i, pos TYPE i, attempts TYPE i, threshold TYPE i. FIELD-SYMBOLS TYPE t_cell. num = n - 3. IF num < 1. num = 1. ENDIF. num = num * factor. threshold = nsq / 4. DO num TIMES. pos = rnd->get_next( ). attempts = nsq. DO. " try to place new tile at this or next free position ASSIGN field[ 1 + pos DIV n ][ 1 + pos MOD n ] TO . IF -value = 0. " free position found - tile value: 2 (likelihood 75%) or 4 IF rnd->get_next( ) > threshold.

  • DEV262

    28

    -value = 2. ELSE. -value = 4. ENDIF. " remember when tile was born, to display it as 'new' -born = -1. IF moves > 0. -born = moves. ENDIF. EXIT. ENDIF. pos = ( pos + 1 ) MOD nsq. attempts = attempts - 1. IF attempts = 0. RETURN. ENDIF. ENDDO. ENDDO. ENDMETHOD. ENDCLASS. DATA my_game TYPE REF TO game. START-OF-SELECTION. CREATE OBJECT my_game. my_game->display( ).

  • DEV262

    29

    APPENDIX F: 2048 WITH EXPRESSIONS SOLUTION EXERCISE 2 EXTREME PROGRAM ZDEV262_EXERCISE2_XTREM. CLASS game DEFINITION. PUBLIC SECTION. METHODS: constructor, display. PRIVATE SECTION. TYPES: BEGIN OF t_cell, value TYPE i, id TYPE string, born TYPE i, END OF t_cell, t_cells TYPE STANDARD TABLE OF t_cell WITH EMPTY KEY, t_field TYPE STANDARD TABLE OF t_cells WITH EMPTY KEY, t_ref TYPE REF TO t_cell, t_refs TYPE STANDARD TABLE OF t_ref WITH EMPTY KEY. CONSTANTS tile_colors TYPE string VALUE `eee4da ede0c8 f2b179 f59563 f67c5f f65e3b ` & `edcf72 f67c5f edc850 edc53f edc22e` ##NO_TEXT. DATA: rnd TYPE REF TO cl_abap_random_int, field TYPE t_field, n TYPE i, " dimension of field nsq TYPE i, " n * n target TYPE i VALUE 2048, " target value score TYPE i, " current score moves TYPE i, " # of moves header TYPE string, " HTML header string over TYPE string, " game-over message line TYPE t_refs. METHODS: at_click FOR EVENT sapevent OF cl_abap_browser IMPORTING action, build_line IMPORTING VALUE(direction) TYPE char1 VALUE(i) TYPE i, move_lines IMPORTING VALUE(direction) TYPE char1 RETURNING VALUE(valid) TYPE abap_bool, move_line RETURNING VALUE(valid) TYPE abap_bool, new_tiles IMPORTING VALUE(factor) TYPE i DEFAULT 1, check_game. ENDCLASS. CLASS game IMPLEMENTATION. METHOD constructor. DATA(size) = 4. cl_demo_input=>add_field( CHANGING field = size ). cl_demo_input=>add_field( CHANGING field = target ). cl_demo_input=>request( ). n = nmax( val1 = 3 val2 = nmin( val1 = size val2 = 8 ) ). nsq = n * n. " target tile value must be a power of 2, at least 8 target = nmax( val1 = 8 val2 = target ). target = ipow( base = 2 exp = ceil( log( target ) / log( 2 ) ) ). rnd = cl_abap_random_int=>create( seed = CONV i( sy-uzeit ) min = 0 max = nsq - 1 ). field = VALUE #( FOR i = 1 UNTIL i > n

  • DEV262

    30

    ( VALUE #( FOR j = 1 UNTIL j > n ( id = |{ i }{ j }| born = -1 ) ) ) ). new_tiles( 2 ). " place initial tiles in field " build header with styles for tiles; cell/font sizes depend on n header = REDUCE string( ##NO_TEXT LET w = 360 / n IN INIT h = `` & `.t0{background-color:#cbbdb0}` & `td{border:1px solid bbada0;color:#776e65` & `;text-align:center;vertical-align:center` & `;font-family:'Century Gothic',sans-serif;font-weight:bold` && |;width:{ w }px;height:{ w }px;font-size:{ w / 2 }px\}| FOR i = 1 UNTIL i > 11 NEXT h = |{ h }.t{ ipow( base = 2 exp = i ) }\{| & |background-color:#{ segment( val = tile_colors index = i ) }| & |{ COND #( WHEN i >= 3 THEN `;color:#f9f6f2` ) }| & |{ COND #( WHEN i >= 10 THEN |;font-size:{ w / 4 }px| WHEN i >= 7 THEN |;font-size:{ w / 3 }px| ) }\}| ). header = header && ##NO_TEXT `div{text-align:center}` & `function okd(e)` & `{c=window.event.keyCode;window.location='sapevent:'+c;}` & `document.onkeydown = okd; `. SET HANDLER at_click. ENDMETHOD. METHOD display. cl_abap_browser=>show_html( title = |Join the numbers and get to the { target } tile!| size = cl_abap_browser=>small format = cl_abap_browser=>portrait context_menu = 'X' html_string = REDUCE string( INIT h = |{ header }Score { score }| & || FOR IN field NEXT h = h && || && REDUCE string( INIT k = `` FOR IN NEXT k = |{ k }{ COND #( WHEN -value = 0 THEN `` ELSE -value ) }| ) && `` ) && `` && COND #( WHEN over = `` THEN `Use arrow keys to join tiles` ELSE |{ over }| ) && `` ). ENDMETHOD. METHOD at_click. DATA(direction) = SWITCH #( action WHEN 37 THEN 'L'

  • DEV262

    31

    WHEN 38 THEN 'U' WHEN 39 THEN 'R' WHEN 40 THEN 'D' ). IF over ``. " game is over; leave game with any non-arrow key IF direction IS INITIAL. cl_abap_browser=>close_browser( ). LEAVE PROGRAM. ENDIF. RETURN. ENDIF. IF move_lines( direction ). moves = moves + 1. new_tiles( ). check_game( ). display( ). ENDIF. ENDMETHOD. METHOD check_game. CONSTANTS dirs TYPE char4 VALUE 'LRUD'. " find highest tile value and check if an empty cell exists DATA(fill) = REDUCE t_cell( INIT m = VALUE #( ) FOR IN field FOR IN NEXT m-value = nmax( val1 = m-value val2 = -value ) m-id = COND #( WHEN -value = 0 THEN `!` ELSE m-id ) ). " game is won if target value is reached IF fill-value >= target. over = |Finished in { moves } moves!|. ELSEIF fill-id `!`. " no empty cell -> check if stuck: try move in all 4 directions DO 4 TIMES. DATA(off) = sy-index - 1. DO n TIMES. build_line( direction = dirs+off(1) i = sy-index ). LOOP AT line FROM 2 ASSIGNING FIELD-SYMBOL(). ASSIGN line[ sy-tabix - 1 ] TO FIELD-SYMBOL(). IF ->value = ->value. RETURN. " found a possible move; game not over ENDIF. ENDLOOP. ENDDO. ENDDO. over = `*** Stuck - Game over ***`. ENDIF. ENDMETHOD. METHOD move_lines. CHECK direction IS NOT INITIAL. DO n TIMES. build_line( direction = direction i = sy-index ). valid = cmax( val1 = move_line( ) val2 = valid ). ENDDO. CLEAR line. ENDMETHOD. METHOD build_line. " build cell references to line i, starting at end (wrt direction) line = VALUE #( FOR j = n THEN j - 1 UNTIL j = 0 " j = n...1

  • DEV262

    32

    LET y = SWITCH i( direction WHEN 'L' OR 'R' THEN i WHEN 'D' THEN j WHEN 'U' THEN n + 1 - j ) x = SWITCH i( direction WHEN 'U' OR 'D' THEN i WHEN 'R' THEN j WHEN 'L' THEN n + 1 - j ) IN ( REF #( field[ y ][ x ] ) ) ). ENDMETHOD. METHOD move_line. DATA: idx TYPE i VALUE 1, next_idx TYPE i VALUE 2. DATA(curr) = line[ 1 ]. WHILE next_idx value > 0. IF curr->value = next->value. curr->value = curr->value * 2. " join tiles next->value = 0. valid = abap_true. score = score + curr->value. idx = idx + 1. curr = line[ idx ]. " proceed ELSEIF next->value > 0 OR next_idx = n. idx = idx + 1. curr = line[ idx ]. " proceed next_idx = idx. ENDIF. ELSEIF next->value 0. curr->value = next->value. " shift tile to empty cell next->value = 0. valid = abap_true. ENDIF. next_idx = next_idx + 1. ENDWHILE. ENDMETHOD. METHOD new_tiles. " place 1 or more (for n>4) new tiles (* 2 at start of game) DO nmax( val1 = n - 3 val2 = 1 ) * factor TIMES. DATA(pos) = rnd->get_next( ). DATA(attempts) = nsq. DO. " try to place new tile at this or next free position ASSIGN field[ 1 + pos DIV n ][ 1 + pos MOD n ] TO FIELD-SYMBOL(). IF -value = 0. " free position found - tile value: 2 (likelihood 75%) or 4 -value = COND #( WHEN rnd->get_next( ) > nsq / 4 THEN 2 ELSE 4 ). " remember when tile was born, to display it as 'new' -born = COND #( WHEN moves > 0 THEN moves ELSE -1 ). EXIT. ENDIF. pos = ( pos + 1 ) MOD nsq. attempts = attempts - 1. IF attempts = 0. RETURN. ENDIF. ENDDO. ENDDO. ENDMETHOD.

  • DEV262

    33

    ENDCLASS. START-OF-SELECTION. NEW game( )->display( ).