贪吃蛇 BY ABAP

REPORT ztest_xk08.

*Author:Zhou xk 20190404 IN ShangHai


CLASS zcl_snake DEFINITION.
  PUBLIC SECTION.
    TYPES:c2 TYPE char2,
          c4 TYPE char4.
    TYPES:BEGIN OF ty_bg,
            c101  TYPE c2,c102  TYPE c2,c103  TYPE c2,c104  TYPE c2,c105  TYPE c2,
            c106  TYPE c2,c107  TYPE c2,c108  TYPE c2,c109  TYPE c2,c110  TYPE c2,
            c111  TYPE c2,c112  TYPE c2,c113  TYPE c2,c114  TYPE c2,c115  TYPE c2,
            c116  TYPE c2,c117  TYPE c2,c118  TYPE c2,c119  TYPE c2,c120  TYPE c2,
            c121  TYPE c2,
            m101  TYPE c4,m102  TYPE c4,m103  TYPE c4,m104  TYPE c4,m105  TYPE c4,
            color TYPE lvc_t_scol,
            type  TYPE salv_t_int4_column,
          END OF ty_bg.
    TYPES:BEGIN OF ty_body,
            xcol TYPE c2,
            krow TYPE c2,
            ztop TYPE c2, "蛇头标记
          END OF ty_body.

*  背景框
    DATA:gs_bg TYPE ty_bg,
         gt_bg LIKE STANDARD TABLE OF gs_bg.

*   蛇身体
    DATA:gs_body TYPE ty_body,
         gt_body TYPE STANDARD TABLE OF ty_body.

    DATA:gc_st TYPE REF TO cl_salv_table.

    DATA:gc_timer TYPE REF TO cl_gui_timer.

*   行列确定地图上随机的一个点
    DATA:gv_random_col TYPE qf00-ran_int,
         gv_random_row TYPE qf00-ran_int.

*   常量
    CONSTANTS:cons_up     TYPE c VALUE '↑',
              cons_down   TYPE c VALUE '↓',
              cons_left   TYPE c VALUE '←',
              cons_right  TYPE c VALUE '→',
              cons_border TYPE c VALUE '✰',
              cons_food   TYPE c VALUE '❀',
              cons_body   TYPE c VALUE 'O'.

*   初始化 背景地图
    METHODS:init_bg.

*   定时器
    METHODS:handle_finished FOR EVENT finished OF cl_gui_timer.

*   热点hotspot事件
    METHODS:handle_link_click FOR EVENT link_click OF cl_salv_events_table IMPORTING row column.

*   刷新背景地图
    METHODS:refresh_bg.

*   运行游戏
    METHODS:run.

*   地图上随机产生一个点,贪吃蛇需要吃的果实
    METHODS:target_random.

*   构造蛇的主体
    METHODS:init_snake.

*   移动蛇体
    METHODS:move_snake IMPORTING direction TYPE c OPTIONAL RETURNING VALUE(r_flag) TYPE char1.

*   新的蛇体
    METHODS:new_snake IMPORTING i_flag TYPE char1.


ENDCLASS.

CLASS zcl_snake IMPLEMENTATION.

  METHOD:init_bg.
    CLEAR:gt_bg.
*   21*21的地图,1列 21列 1行 21行为边界
    DO 21 TIMES.
      APPEND INITIAL LINE TO gt_bg.
    ENDDO.

    LOOP AT gt_bg INTO gs_bg.
      IF sy-tabix = 1 OR sy-tabix = 21.
*       第1行 第21行 改变颜色作为边界
        gs_bg-color = VALUE #( FOR i = 1 UNTIL i > 21
                             ( fname = |C{ i + 100 }|  color = VALUE #( col = '1' int = '1' inv = '0' ) ) ) .
        DO 21 TIMES.
          ASSIGN COMPONENT |C{ sy-index + 100 }| OF STRUCTURE gs_bg TO FIELD-SYMBOL().
           = cons_border.
        ENDDO.

      ELSE.
*       第1列 第21列 改变颜色作为边界
        gs_bg-color = VALUE #( ( fname = 'C101' color = VALUE #( col = '1' int = '1' inv = '0' ) )
                               ( fname = 'C121' color = VALUE #( col = '1' int = '1' inv = '0' ) ) ).
        gs_bg-c101 = cons_border.
        gs_bg-c121 = cons_border.
      ENDIF.
      MODIFY gt_bg FROM gs_bg.

    ENDLOOP.


    cl_salv_table=>factory( IMPORTING r_salv_table = gc_st CHANGING t_table = gt_bg ).

*   hotspot event
    DATA(lc_events) = gc_st->get_event( ).
    SET HANDLER handle_link_click FOR lc_events.


*   开始按钮
*    READ TABLE gt_bg ASSIGNING FIELD-SYMBOL() INDEX 13.
*    IF sy-subrc = 0.
*      -m102 = 'GO'.
*      -type = VALUE salv_t_int4_column( "( columnname = 'M102' value = if_salv_c_cell_type=>button )
*                                               ( columnname = 'M102' value = if_salv_c_cell_type=>hotspot ) ).
*    ENDIF.


*   方向按钮
    READ TABLE gt_bg ASSIGNING FIELD-SYMBOL() INDEX 17.
    IF sy-subrc = 0.
      -m103 = icon_next_value.
      -type = VALUE salv_t_int4_column( ( columnname = 'M103' value = if_salv_c_cell_type=>hotspot ) ).
    ENDIF.
    READ TABLE gt_bg ASSIGNING  INDEX 18.
    IF sy-subrc = 0.
      -m102 = icon_column_left.
      -m104 = icon_column_right.
      -type = VALUE salv_t_int4_column( ( columnname = 'M102' value = if_salv_c_cell_type=>hotspot )
                                               ( columnname = 'M104' value = if_salv_c_cell_type=>hotspot ) ).
    ENDIF.
    READ TABLE gt_bg ASSIGNING  INDEX 19.
    IF sy-subrc = 0.
      -m103 = icon_previous_value.
      -type = VALUE salv_t_int4_column( ( columnname = 'M103' value = if_salv_c_cell_type=>hotspot ) ).
    ENDIF.

*   颜色样式和单元格样式
    DATA(lc_columns) = gc_st->get_columns( ).
    lc_columns->set_color_column( 'COLOR' ).
    lc_columns->set_cell_type_column( 'TYPE' ).

*   选择模式
    DATA(lc_selections) = gc_st->get_selections( ).
    lc_selections->set_selection_mode( if_salv_c_selection_mode=>cell ).


    DATA:lc_column TYPE REF TO cl_salv_column.
    DO 21 TIMES.
      lc_column = lc_columns->get_column( CONV lvc_fname( |C{ sy-index + 100 }| ) ).
*     居中显示
      lc_column->set_alignment( if_salv_c_alignment=>centered ).
    ENDDO.

    DATA:lc_column_table TYPE REF TO cl_salv_column_table.
    DO 5 TIMES.
      lc_column_table ?= lc_columns->get_column(  CONV lvc_fname( |M{ sy-index + 100 }| )  ).
*     将列设置为显示ICON
      lc_column_table->set_icon( if_salv_c_bool_sap=>true ).

      lc_column_table->set_alignment( if_salv_c_alignment=>centered ).
      lc_column_table->set_output_length( 2 ).

    ENDDO.



  ENDMETHOD.

  METHOD handle_finished.

    DATA(zflag) = move_snake( ).
    new_snake( zflag ).

    gc_st->refresh( ).

    CALL METHOD gc_timer->run.

  ENDMETHOD.

  METHOD handle_link_click.
    DATA(lv_direction) = COND string(  WHEN row = 17 AND column = 'M103' THEN 'UP'
                                       WHEN row = 18 AND column = 'M102' THEN 'LEFT'
                                       WHEN row = 18 AND column = 'M104' THEN 'RIGHT'
                                       WHEN row = 19 AND column = 'M103' THEN 'DOWN').
    CASE lv_direction.
      WHEN 'UP'.
        DATA(zflag) = move_snake( direction = cons_up ).
        new_snake( zflag ).
      WHEN 'LEFT'.
        zflag = move_snake( direction = cons_left ).
        new_snake( zflag ).
      WHEN 'RIGHT'.
        zflag = move_snake( direction = cons_right ).
        new_snake( zflag ).
      WHEN 'DOWN'.
        zflag = move_snake( direction = cons_down ).
        new_snake( zflag ).
      WHEN OTHERS.
    ENDCASE.

  ENDMETHOD.

  METHOD:refresh_bg.

    CREATE OBJECT gc_timer.

    SET HANDLER handle_finished FOR gc_timer.
    gc_timer->interval = 1.
    CALL METHOD gc_timer->run.


  ENDMETHOD.

  METHOD:run.
    init_snake( ).
    target_random( ).
    refresh_bg( ).
    gc_st->display( ).

  ENDMETHOD.

  METHOD:target_random.
    DATA:lv_flag TYPE c.

    CLEAR:lv_flag.

    WHILE lv_flag IS INITIAL.
*     随机一列
      CALL FUNCTION 'QF05_RANDOM_INTEGER'
        EXPORTING
          ran_int_max = 20
          ran_int_min = 2
        IMPORTING
          ran_int     = gv_random_col.
*     随机一行
      CALL FUNCTION 'QF05_RANDOM_INTEGER'
        EXPORTING
          ran_int_max = 20
          ran_int_min = 2
        IMPORTING
          ran_int     = gv_random_row.

*     新的果实不能占用蛇的身体
      IF line_exists( gt_body[ xcol = gv_random_col krow = gv_random_row ] ).
      ELSE.
        lv_flag = 'X'.
      ENDIF.


    ENDWHILE.

    READ TABLE gt_bg ASSIGNING FIELD-SYMBOL() INDEX gv_random_row.
    IF sy-subrc = 0.
      -color = VALUE #( ( fname = |C{ gv_random_col + 100 }| color = VALUE #( col = '7' int = '1' inv = '0' ) )
                               ( fname = 'C101' color = VALUE #( col = '1' int = '1' inv = '0' ) )
                               ( fname = 'C121' color = VALUE #( col = '1' int = '1' inv = '0' ) ) ).

      ASSIGN COMPONENT |C{ gv_random_col + 100 }| OF STRUCTURE  TO FIELD-SYMBOL().
       = cons_food.
    ENDIF.

  ENDMETHOD.

  METHOD:init_snake.
    CLEAR:gt_body.
    gt_body = VALUE #( ( xcol = 11 krow = 11 ztop = cons_up )
                       ( xcol = 11 krow = 12 )
                       ( xcol = 11 krow = 13 ) ).

    LOOP AT gt_body INTO gs_body.
      ASSIGN COMPONENT |C{ gs_body-xcol + 100 }| OF STRUCTURE gt_bg[ gs_body-krow ] TO FIELD-SYMBOL().
      IF gs_body-ztop = cons_up.
         = cons_up.
      ELSE.
         = cons_body.
      ENDIF.
    ENDLOOP.

  ENDMETHOD.

  METHOD:move_snake.
    CLEAR:r_flag.
    LOOP AT gt_bg INTO DATA(ls_bg).
*     查询到蛇头得位置,并判断方向
      DO 21 TIMES.
        ASSIGN COMPONENT |C{ sy-index + 100 }| OF STRUCTURE ls_bg TO FIELD-SYMBOL().

*       判断是否反方向运行 反方向则退出
        IF (  = cons_up    AND direction = cons_down  ) OR
           (  = cons_down  AND direction = cons_up    ) OR
           (  = cons_left  AND direction = cons_right ) OR
           (  = cons_right AND direction = cons_left  ).
          r_flag = 'X'.
          RETURN.
        ENDIF.



*       判断是否相同方向运行 同方向则不进行操作
        IF   = direction.
*       判断蛇头是否变更了方向
        ELSEIF (  = cons_up OR  = cons_down OR  = cons_left OR  = cons_right )  AND direction IS NOT INITIAL.
           = direction.
        ENDIF.
*       移动蛇之后的蛇头坐标
        CASE .
          WHEN cons_up.
            gs_body-xcol = sy-index.
            gs_body-krow = sy-tabix - 1.
            gs_body-ztop = cons_up.
          WHEN cons_down.
            gs_body-xcol = sy-index.
            gs_body-krow = sy-tabix + 1.
            gs_body-ztop = cons_down.
          WHEN cons_left.
            gs_body-xcol = sy-index - 1.
            gs_body-krow = sy-tabix.
            gs_body-ztop = cons_left.
          WHEN cons_right.
            gs_body-xcol = sy-index + 1.
            gs_body-krow = sy-tabix.
            gs_body-ztop = cons_right.
          WHEN OTHERS.
        ENDCASE.

*       删除移动前蛇在地图上的轨迹
         = ''.

*       将新坐标添加到内表
        IF gs_body-ztop IS NOT INITIAL.
          INSERT gs_body INTO gt_body INDEX 1.
          CLEAR:gs_body.

          READ TABLE gt_body ASSIGNING FIELD-SYMBOL() INDEX 2.
          IF sy-subrc = 0.
            -ztop = ''.
          ENDIF.

          RETURN.
        ENDIF.
      ENDDO.
    ENDLOOP.

  ENDMETHOD.

  METHOD:new_snake.


    LOOP AT gt_body INTO gs_body WHERE ztop IS NOT INITIAL.
      ASSIGN COMPONENT |C{ gs_body-xcol + 100 }| OF STRUCTURE gt_bg[ gs_body-krow ] TO FIELD-SYMBOL().
*     检查是否撞墙 或者撞上自己
      IF  = cons_border OR  = cons_body.
        MESSAGE 'YOU LOST!' TYPE 'I'.

        LEAVE TO SCREEN 0.

      ENDIF.
*     检查是否吃到果实
      IF  = cons_food.
        ASSIGN COMPONENT 'COLOR' OF STRUCTURE gt_bg[ gs_body-krow ] TO FIELD-SYMBOL().
         = VALUE lvc_t_scol( ( fname = 'C101' color = VALUE #( col = '1' int = '1' inv = '0' ) )
                                          ( fname = 'C121' color = VALUE #( col = '1' int = '1' inv = '0' ) ) ).

*      生成新的果实
        target_random( ).

*      增加尾巴长度
        DATA(lv_tail) = 'X'.
      ENDIF.
    ENDLOOP.

*   吃到果实蛇尾长度+1 ,没吃到 -1
    IF lv_tail = 'X'.

    ELSE.
      IF i_flag IS INITIAL.
        DATA(lv_tabix) = lines( gt_body ).
        DELETE gt_body INDEX lv_tabix.
      ENDIF.
    ENDIF.


*   删除旧蛇
    LOOP AT gt_bg INTO gs_bg.
      DO 21 TIMES.
        ASSIGN COMPONENT |C{ sy-index + 100 }| OF STRUCTURE gs_bg TO .
        IF  <> cons_food AND  <> cons_border.
           = ''.
        ENDIF.
      ENDDO.
      MODIFY gt_bg FROM gs_bg.
    ENDLOOP.

*   构造移动后的蛇的身体
    LOOP AT gt_body INTO gs_body.
      ASSIGN COMPONENT |C{ gs_body-xcol + 100 }| OF STRUCTURE gt_bg[ gs_body-krow ] TO .
      IF gs_body-ztop <> ''.
         = gs_body-ztop.
      ELSE.
         = cons_body.
      ENDIF.


    ENDLOOP.


*   刷新后强制双击表格,就可以看到修改的内表了
    CALL FUNCTION 'SAPGUI_SET_FUNCTIONCODE'
      EXPORTING
        functioncode           = '=ENT'
      EXCEPTIONS
        function_not_supported = 1
        OTHERS                 = 2.


    gc_st->refresh( ).

  ENDMETHOD.


ENDCLASS.






START-OF-SELECTION.

  DATA(gc_snake) = NEW zcl_snake( ).
  gc_snake->init_bg( ).
  gc_snake->run( ).


你可能感兴趣的:(贪吃蛇 BY ABAP)