贪吃蛇 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(<fs_bg_border>).
          <fs_bg_border> = 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(<fs_bg>) INDEX 13.
*    IF sy-subrc = 0.
*      <fs_bg>-m102 = 'GO'.
*      <fs_bg>-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(<fs_bg>) INDEX 17.
    IF sy-subrc = 0.
      <fs_bg>-m103 = icon_next_value.
      <fs_bg>-type = VALUE salv_t_int4_column( ( columnname = 'M103' value = if_salv_c_cell_type=>hotspot ) ).
    ENDIF.
    READ TABLE gt_bg ASSIGNING <fs_bg> INDEX 18.
    IF sy-subrc = 0.
      <fs_bg>-m102 = icon_column_left.
      <fs_bg>-m104 = icon_column_right.
      <fs_bg>-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 <fs_bg> INDEX 19.
    IF sy-subrc = 0.
      <fs_bg>-m103 = icon_previous_value.
      <fs_bg>-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(<fs_bg>) INDEX gv_random_row.
    IF sy-subrc = 0.
      <fs_bg>-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 <fs_bg> TO FIELD-SYMBOL(<fs_target>).
      <fs_target> = 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(<fs_bg>).
      IF gs_body-ztop = cons_up.
        <fs_bg> = cons_up.
      ELSE.
        <fs_bg> = 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(<fs_arrow>).

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



*       判断是否相同方向运行 同方向则不进行操作
        IF  <fs_arrow> = direction.
*       判断蛇头是否变更了方向
        ELSEIF ( <fs_arrow> = cons_up OR <fs_arrow> = cons_down OR <fs_arrow> = cons_left OR <fs_arrow> = cons_right )  AND direction IS NOT INITIAL.
          <fs_arrow> = direction.
        ENDIF.
*       移动蛇之后的蛇头坐标
        CASE <fs_arrow>.
          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.

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

*       将新坐标添加到内表
        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(<fs_body>) INDEX 2.
          IF sy-subrc = 0.
            <fs_body>-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(<fs_bg>).
*     检查是否撞墙 或者撞上自己
      IF <fs_bg> = cons_border OR <fs_bg> = cons_body.
        MESSAGE 'YOU LOST!' TYPE 'I'.

        LEAVE TO SCREEN 0.

      ENDIF.
*     检查是否吃到果实
      IF <fs_bg> = cons_food.
        ASSIGN COMPONENT 'COLOR' OF STRUCTURE gt_bg[ gs_body-krow ] TO FIELD-SYMBOL(<fs_bg_color>).
        <fs_bg_color> = 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 <fs_bg>.
        IF <fs_bg> <> cons_food AND <fs_bg> <> cons_border.
          <fs_bg> = ''.
        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 <fs_bg>.
      IF gs_body-ztop <> ''.
        <fs_bg> = gs_body-ztop.
      ELSE.
        <fs_bg> = 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( ).


©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,137评论 6 511
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,824评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,465评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,131评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,140评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,895评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,535评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,435评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,952评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,081评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,210评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,896评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,552评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,089评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,198评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,531评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,209评论 2 357

推荐阅读更多精彩内容