메뉴 건너뛰기

SAP 한국 커뮤니티



REPORT z_memory_game

노름마치 2007.11.05 13:03 조회 수 : 5199

REPORT z_memory.
*---------------------------------------------------------------------*
* Memory Game                                                         *
* From a copy of http://www.geocities.com/ralfonsii/abap_4_fun.htm    *
*---------------------------------------------------------------------*
* Author : Ralf Rubel (http://www.ralf-rubel.de/ ) / Michel PIOUD     *
* Email : mpioud@yahoo.fr  HomePage : http://www.geocities.com/mpioud *
*---------------------------------------------------------------------*
* Create the report Z_MEMORY                                          *
* Create the dynpro 0100                                              *
* Upload the dynpro 0100                                              *
*    from http://www.geocities.com/mpioud/Z_MEMORY_screen_0100.txt    *
* Create the status BASE with the BACK, EXIT, CANCEL functions        *
*---------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b0 WITH FRAME.
PARAMETERS :
  p_row  TYPE n DEFAULT 4 OBLIGATORY,
  p_col  TYPE n DEFAULT 4 OBLIGATORY.
SELECTION-SCREEN SKIP.
PARAMETERS :
  p_wait TYPE n DEFAULT 2 OBLIGATORY.
SELECTION-SCREEN SKIP.
PARAMETERS :
  p_random AS CHECKBOX DEFAULT 'X',
  p_option AS CHECKBOX DEFAULT 'X'.
SELECTION-SCREEN END OF BLOCK b0.


*---------------------------------------------------------------------*
AT SELECTION-SCREEN.


  IF p_row < 2 OR p_row > 8.
    MESSAGE e002(sy) WITH ''.
  ENDIF.
  IF p_col < 2 OR p_col > 8.
    MESSAGE e002(sy) WITH ''.
  ENDIF.


*---------------------------------------------------------------------*
* Eventhandler
CLASS lcl_event_handler DEFINITION.


  PUBLIC SECTION.


    CLASS-METHODS on_control_click
        FOR EVENT control_click
               OF cl_gui_picture
        IMPORTING sender.


ENDCLASS.
*---------------------------------------------------------------------*
TYPES:
  BEGIN OF ty_boardline,
    visible(1),
    ico(4),
    icon      TYPE i,
    index     TYPE i,
    row       TYPE i,
    column    TYPE i,
    count     TYPE i,
    picture   TYPE REF TO cl_gui_picture,
    container TYPE REF TO cl_gui_container,
  END OF ty_boardline,


  BEGIN OF ty_highscoreline,
    no(2),
    name(12),
    date(10),
    time(5),
    score(6),
  END OF ty_highscoreline.
*---------------------------------------------------------------------*
* register events at control framework
DATA g_row          TYPE i.
DATA g_line         TYPE i.
DATA g_row_col      TYPE numc3.
DATA wa_events      TYPE cntl_simple_event.
DATA events         TYPE cntl_simple_events.
DATA g_row_m_1      TYPE i.
DATA wa_board       TYPE ty_boardline.
DATA wa_cell_first  TYPE ty_boardline.
DATA wa_cell_second TYPE ty_boardline.
DATA gt_board       TYPE TABLE OF ty_boardline.
DATA score          TYPE i.
DATA container      TYPE REF TO cl_gui_custom_container.
DATA splitter       TYPE REF TO cl_gui_splitter_container.
DATA first_clicked  TYPE REF TO cl_gui_picture.
DATA second_clicked TYPE REF TO cl_gui_picture.
DATA event_handler  TYPE REF TO lcl_event_handler.


DATA g_counter    TYPE i.
DATA pairs_left   TYPE i.
DATA wa_highscore TYPE ty_highscoreline.
DATA gt_highscore TYPE TABLE OF ty_highscoreline.
DATA tx_container TYPE REF TO cl_gui_custom_container.
DATA tx_editor    TYPE REF TO cl_gui_textedit.
DATA wa_lines     TYPE tline.
DATA gt_lines     TYPE TABLE OF tline.


DATA svcode TYPE syucomm.
DATA okcode TYPE syucomm.
DATA objects_created TYPE flag.
DATA g_indx_key(10) VALUE 'MEMORY'.


*---------------------------------------------------------------------*
START-OF-SELECTION.


  g_row = p_row.
  g_line = p_col.
  g_row_m_1 = p_row - 1.
  g_row_col = p_row * p_col.
  pairs_left = ( ( p_row * p_col ) - 1 ) / 2.
  CONCATENATE g_indx_key g_row_col INTO g_indx_key.


  CALL SCREEN 100.


*---------------------------------------------------------------------*
*       Module  USER_COMMAND_0100  INPUT
*---------------------------------------------------------------------*
MODULE user_command_0100 INPUT.


  svcode = okcode.
  CLEAR okcode.


  CASE svcode.
    WHEN 'BACK'.
      PERFORM housekeeping.
      SET SCREEN 0.
    WHEN 'EXIT'.
      PERFORM housekeeping.
      SET SCREEN 0.
    WHEN 'ZRESET'.
      PERFORM f_reset.
      EXPORT gt_lines TO DATABASE indx(st) ID g_indx_key.
      SET SCREEN 0.
  ENDCASE.


ENDMODULE.                             " USER_COMMAND_0100  INPUT
*---------------------------------------------------------------------*
*       Module  EXIT  INPUT
*---------------------------------------------------------------------*
MODULE exit INPUT.


  CASE okcode.
    WHEN 'EXIT'.
      PERFORM housekeeping.
      LEAVE PROGRAM.
    WHEN 'CANCEL'.
      PERFORM housekeeping.
      SET SCREEN 0.
  ENDCASE.


ENDMODULE.                             " EXIT  INPUT
*---------------------------------------------------------------------*
*       Module  STATUS_0100  OUTPUT
*---------------------------------------------------------------------*
MODULE status_0100 OUTPUT.


  SET PF-STATUS 'BASE'.
  SET TITLEBAR 'BAS'.


  PERFORM create_objects.


ENDMODULE.                             " STATUS_0100  OUTPUT
*---------------------------------------------------------------------*
*       Form  SHOW_CELL
*---------------------------------------------------------------------*
FORM show_cell USING u_row       TYPE i
                     u_column    TYPE i
                     u_container TYPE REF TO cl_gui_container
                     u_picture   TYPE REF TO cl_gui_picture
                     u_icon      TYPE icon_d.


  CALL METHOD splitter->get_container
    EXPORTING
      row       = u_row
      column    = u_column
    RECEIVING
      container = u_container.


  IF u_picture IS INITIAL.
    CREATE OBJECT u_picture
        EXPORTING parent = u_container.


*   Register events
    wa_events-eventid = u_picture->eventid_control_click.
    APPEND wa_events TO events.


    CALL METHOD u_picture->set_registered_events
       EXPORTING events = events.


    SET HANDLER event_handler->on_control_click FOR u_picture.
  ENDIF.


  IF NOT u_icon IS INITIAL.
    CALL METHOD u_picture->load_picture_from_sap_icons
      EXPORTING icon = u_icon.


    CALL METHOD u_picture->set_display_mode
      EXPORTING display_mode = cl_gui_picture=>display_mode_fit_center.
  ENDIF.


ENDFORM.                                                    " SHOW_CELL
*---------------------------------------------------------------------*
*       CLASS lcl_event_handler IMPLEMENTATION
*---------------------------------------------------------------------*
CLASS lcl_event_handler IMPLEMENTATION.


  METHOD on_control_click.
*   First_clicked
    IF first_clicked IS INITIAL.
      READ TABLE gt_board INTO wa_cell_first
        WITH KEY picture = sender.


      IF wa_cell_first-visible IS INITIAL AND
         NOT wa_cell_first-ico IS INITIAL.


*       Show icon
        PERFORM show_cell USING wa_cell_first-row
                                wa_cell_first-column
                                wa_cell_first-container
                                wa_cell_first-picture
                                wa_cell_first-ico.


        first_clicked = sender.
        ADD 1 TO  wa_cell_first-count.
      ENDIF.


*   Second_clicked
    ELSE.
      CHECK sender <> first_clicked.


      READ TABLE gt_board INTO wa_cell_second
        WITH KEY picture = sender.


      IF wa_cell_second-visible IS INITIAL AND
         NOT wa_cell_second-ico IS INITIAL.


*       Show icon
        PERFORM show_cell USING wa_cell_second-row
                                wa_cell_second-column
                                wa_cell_second-container
                                wa_cell_second-picture
                                wa_cell_second-ico.
        second_clicked = sender.
        ADD 1 TO  wa_cell_second-count.
      ENDIF.
    ENDIF.


*   Pair visible
    IF NOT first_clicked IS INITIAL AND NOT second_clicked IS INITIAL.
      IF wa_cell_first-icon = wa_cell_second-icon.
        wa_cell_first-visible = wa_cell_second-visible = 'X'.
        MODIFY gt_board FROM wa_cell_first  INDEX wa_cell_first-index.
        MODIFY gt_board FROM wa_cell_second INDEX wa_cell_second-index.
        pairs_left = pairs_left - 1.
      ELSE.
        MODIFY gt_board FROM wa_cell_first  INDEX wa_cell_first-index.
        MODIFY gt_board FROM wa_cell_second INDEX wa_cell_second-index.


        IF p_option = 'X' AND
         ( wa_cell_first-count > 1 OR wa_cell_second-count > 1 ).
          MESSAGE i319(01) WITH 'Game over'.
          LEAVE TO SCREEN 0.
        ENDIF.


        CALL METHOD cl_gui_cfw=>update_view.
        WAIT UP TO p_wait SECONDS.
        CALL METHOD wa_cell_first-picture->clear_picture.
        CALL METHOD wa_cell_second-picture->clear_picture.
      ENDIF.
      CLEAR: first_clicked,
             second_clicked,
             wa_cell_first,
             wa_cell_second.
*     Cause field transport when scored
      score = score + 1.
      CALL METHOD cl_gui_cfw=>set_new_ok_code
        EXPORTING new_code = 'ENTE'.
*     Game over ?
      IF pairs_left = 0.
        PERFORM game_over.
      ENDIF.
    ENDIF.
  ENDMETHOD.


ENDCLASS.
*---------------------------------------------------------------------*
*       Form  BOARD_INIT
*---------------------------------------------------------------------*
FORM board_init.


  DATA:
    l_index        TYPE i,
    l_no_freecells TYPE i,
    l_random_cell  TYPE i,
    l_icon         TYPE icon_d,
    lt_icon        TYPE TABLE OF icon_d,
    lt_freecells   TYPE TABLE OF ty_boardline.


* Read icon ids from DB
  IF NOT p_random IS INITIAL.
    SELECT id FROM icon INTO TABLE lt_icon
             WHERE locked = space
               AND name <> 'ICON_SPACE'.
  ELSE.
    SELECT id FROM icon INTO TABLE lt_icon
                UP TO pairs_left ROWS
             WHERE locked = space
               AND name <> 'ICON_SPACE'
             ORDER BY PRIMARY KEY.
  ENDIF.


  g_row_col = p_row * p_col.


  g_counter = 0.


  DO p_row TIMES.
    l_index = sy-index.
    DO p_col TIMES.
      g_counter = g_counter + 1.
      CLEAR wa_board.
      wa_board-row  = l_index.
      wa_board-index  = g_counter.
      wa_board-column = sy-index.


      PERFORM show_cell USING wa_board-row
                              wa_board-column
                              wa_board-container
                              wa_board-picture
                              space.


      APPEND wa_board TO gt_board.
      APPEND wa_board TO lt_freecells.
    ENDDO.
  ENDDO.


  CLEAR g_counter.
  g_row_col = ( ( p_row * p_col ) - 1 ) / 2.
  DO g_row_col TIMES.
    g_counter = g_counter + 1.


    DESCRIBE TABLE lt_icon LINES l_no_freecells.


    CHECK NOT l_no_freecells IS INITIAL.


    CALL FUNCTION 'QF05_RANDOM_INTEGER'
         EXPORTING
              ran_int_max = l_no_freecells
              ran_int_min = 1
         IMPORTING
              ran_int     = l_random_cell.


    READ TABLE lt_icon INTO l_icon
                      INDEX l_random_cell.


*   Delete entry in lt_icon
    DELETE lt_icon INDEX sy-tabix.


    DO 2 TIMES.
      DESCRIBE TABLE lt_freecells LINES l_no_freecells.


      CALL FUNCTION 'QF05_RANDOM_INTEGER'
           EXPORTING
                ran_int_max = l_no_freecells
                ran_int_min = 1
           IMPORTING
                ran_int     = l_random_cell.


*     Read freecells
      READ TABLE lt_freecells INTO wa_board
                             INDEX l_random_cell.


*     Delete entry in freecells
      DELETE lt_freecells INDEX sy-tabix.


*     Update board
      wa_board-icon = g_counter.
      wa_board-ico  = l_icon.
      MODIFY gt_board FROM wa_board INDEX wa_board-index.


    ENDDO.


  ENDDO.


ENDFORM.                               " BOARD_INIT
*---------------------------------------------------------------------*
*       Form  GAME_OVER
*---------------------------------------------------------------------*
FORM game_over.


  DATA:
    l_no TYPE i,
    l_hs TYPE i,
    l_new_highscore(1).


* New Highscore ?
  PERFORM read_highscore.


  g_counter = 5. l_no = 1.
  LOOP AT gt_highscore INTO wa_highscore.
    READ TABLE gt_lines INTO wa_lines INDEX g_counter.
    IF score < wa_highscore-score AND l_new_highscore <> 'X'.
      l_new_highscore = 'X'.
      WRITE l_no NO-SIGN TO wa_lines-tdline(2).
      wa_lines-tdline+4(12) = sy-uname.
      WRITE sy-datum DD/MM/YYYY TO wa_lines-tdline+17(10).
      WRITE sy-uzeit(5) USING EDIT MASK '__:__'
         TO wa_lines-tdline+28(5)
            .
      WRITE score NO-SIGN TO wa_lines-tdline+34(6).
      l_hs = l_no.
      l_no = l_no + 1.
      MODIFY gt_lines FROM wa_lines INDEX g_counter.
      g_counter = g_counter + 1.
    ENDIF.
    CHECK l_no < 31.
    WRITE l_no NO-SIGN TO wa_lines-tdline(2).
    wa_lines-tdline+4(12)  = wa_highscore-name.
    wa_lines-tdline+17(10) = wa_highscore-date.
    wa_lines-tdline+28(5)  = wa_highscore-time.
    wa_lines-tdline+34(6)  = wa_highscore-score.
    MODIFY gt_lines FROM wa_lines INDEX g_counter.
    g_counter = g_counter + 1.
    l_no = l_no + 1.
  ENDLOOP.
  IF l_new_highscore = 'X'.


    SELECT SINGLE mandt
             INTO sy-mandt
             FROM t000
            WHERE mandt = sy-mandt
              AND cccategory = 'T'.
    IF sy-subrc EQ 0.
      EXPORT gt_lines TO DATABASE indx(st) ID g_indx_key.
    ENDIF.


    CALL METHOD tx_editor->set_text_as_r3table
      EXPORTING table = gt_lines.


    MESSAGE i319(01) WITH 'New Highscore' 'No.' l_hs.
  ELSE.
    MESSAGE i319(01) WITH 'Game over'.
  ENDIF.
  LEAVE TO SCREEN 0.


ENDFORM.                                                    " GAME_OVER
*---------------------------------------------------------------------*
*       Form  read_highscore
*---------------------------------------------------------------------*
FORM read_highscore.


  REFRESH gt_highscore.


  IMPORT gt_lines FROM DATABASE indx(st) ID g_indx_key.


  IF gt_lines[] IS INITIAL.
    PERFORM f_reset_score.
  ENDIF.


  LOOP AT gt_lines INTO wa_lines.
    IF sy-tabix > 4.
      CLEAR wa_highscore.
      wa_highscore-no    = wa_lines-tdline(2).
      wa_highscore-name  = wa_lines-tdline+4(12).
      wa_highscore-date  = wa_lines-tdline+17(10).
      wa_highscore-time  = wa_lines-tdline+28(5).
      wa_highscore-score = wa_lines-tdline+34(6).
      APPEND wa_highscore TO gt_highscore.
    ENDIF.
  ENDLOOP.


ENDFORM.                               " READ_HIGHSCORE
*---------------------------------------------------------------------*
*       Form  housekeeping
*---------------------------------------------------------------------*
FORM housekeeping.


  LOOP AT gt_board INTO wa_board.
    IF NOT wa_board-picture IS INITIAL.
      CALL METHOD wa_board-picture->free.
    ENDIF.
    CALL METHOD wa_board-container->free.
  ENDLOOP.


  CALL METHOD tx_editor->free.
  CALL METHOD tx_container->free.


ENDFORM.                               " HOUSEKEEPING
*---------------------------------------------------------------------*
*      Form  create_objects
*---------------------------------------------------------------------*
FORM create_objects.


  CHECK objects_created IS INITIAL.
  objects_created = 'X'.


* Splitter container
  CREATE OBJECT container
      EXPORTING container_name = 'CONTAINER'.


* Splitter
  CREATE OBJECT splitter
    EXPORTING
      parent            = container
      rows              = g_row
      columns           = g_line
    EXCEPTIONS
      others            = 3.
  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
               WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.


  CLEAR g_counter.
  DO g_row_m_1 TIMES.
    g_counter = g_counter + 1.
    CALL METHOD splitter->set_column_sash
      EXPORTING
        id                = g_counter
        type              = splitter->type_movable
        value             = splitter->false
      EXCEPTIONS
        OTHERS            = 3.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.


    CALL METHOD splitter->set_row_sash
      EXPORTING
        id                = g_counter
        type              = splitter->type_movable
        value             = splitter->false
      EXCEPTIONS
        OTHERS            = 3.
    IF sy-subrc <> 0.
      MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
                 WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
    ENDIF.
  ENDDO.


* Highscore-Table
  PERFORM read_highscore.


  CREATE OBJECT tx_container
      EXPORTING container_name = 'TX_CONTAINER'.


  CREATE OBJECT tx_editor
      EXPORTING
        parent = tx_container
        wordwrap_mode = cl_gui_textedit=>wordwrap_at_fixed_position
        wordwrap_position = 42
        wordwrap_to_linebreak_mode = cl_gui_textedit=>true.


  CALL METHOD tx_editor->set_text_as_r3table
    EXPORTING table = gt_lines.


  CALL METHOD tx_editor->set_toolbar_mode
    EXPORTING toolbar_mode = tx_editor->false.


  CALL METHOD tx_editor->set_statusbar_mode
    EXPORTING statusbar_mode = tx_editor->false.


  CALL METHOD tx_editor->set_readonly_mode
    EXPORTING readonly_mode = tx_editor->true.


  PERFORM board_init.


  PERFORM f_show_all.


ENDFORM.                    " CREATE_OBJECTS
*---------------------------------------------------------------------*
*      Form  f_reset_score
*---------------------------------------------------------------------*
FORM f_reset_score.


  DATA:
    lf_count TYPE i.


  REFRESH gt_lines.
  wa_lines-tdformat = '*'.
  wa_lines-tdline   = '        * * * High Scores * * *'.
  APPEND wa_lines TO gt_lines.
  wa_lines-tdformat = '/'.
  wa_lines-tdline = ' '.
  APPEND wa_lines TO gt_lines.
  wa_lines-tdformat = '/'.
  wa_lines-tdline = 'No. Name         Date       Time   Score'.
  APPEND wa_lines TO gt_lines.
  wa_lines-tdformat = '/'.
  wa_lines-tdline = '----------------------------------------'.
  APPEND wa_lines TO gt_lines.
  lf_count = 1.


  DO 30 TIMES.
    wa_lines-tdformat = '/'.
    wa_lines-tdline = '30. NN           01.01.2002 12:00  99999'
.
    WRITE lf_count TO wa_lines-tdline(2).
    APPEND wa_lines TO gt_lines.
    lf_count = lf_count + 1.
  ENDDO.


ENDFORM.                    " f_reset_score
*---------------------------------------------------------------------*
*       FORM f_show_all                                               *
*---------------------------------------------------------------------*
FORM f_show_all.


*  LOOP AT gt_board INTO wa_board.
*    PERFORM show_cell USING wa_board-row
*                            wa_board-column
*                            wa_board-container
*                            wa_board-picture
*                            wa_board-ico.
*  ENDLOOP.


ENDFORM.
*---------------------------------------------------------------------*
*      Form  f_reset
*---------------------------------------------------------------------*
FORM f_reset.


  DATA:
    l_answer.


  CALL FUNCTION 'POPUP_TO_CONFIRM_STEP'
       EXPORTING
            defaultoption = 'N'
            textline1     = 'Delete Scores ?'
            titel         = 'Delete Score'
       IMPORTING
            answer        = l_answer.


  CHECK l_answer = 'J'.


  PERFORM f_reset_score.


ENDFORM.                    " f_reset
*********************** END OF PROGRAM Z_MEMORY ***********************