|  | 
| ABAP乱搞_贪吃蛇 收藏 *&---------------------------------------------------------------------*
 *& Report  ZSNAKE
 *&
 *&---------------------------------------------------------------------*
 *&
 *& Just for fun
 *&---------------------------------------------------------------------*
 
 REPORT  zsnake.
 
 DATA: rf_gui_timer TYPE REF TO cl_gui_timer.
 
 CONSTANTS: c_up TYPE i VALUE 2,
 c_down TYPE i VALUE 4,
 c_left TYPE i VALUE 6,
 c_right TYPE i VALUE 8.
 
 DATA: BEGIN OF i_snake OCCURS 0,
 x TYPE i,
 y TYPE i,
 END OF i_snake.
 
 DATA: v_direction TYPE i VALUE c_right,
 v_isfood TYPE c,
 w_food LIKE LINE OF i_snake.
 
 
 *----------------------------------------------------------------------*
 *       CLASS lcl_event_handler DEFINITION
 *----------------------------------------------------------------------*
 *
 *----------------------------------------------------------------------*
 CLASS lcl_event_handler DEFINITION.
 PUBLIC SECTION.
 CLASS-METHODS: on_finished FOR EVENT finished OF cl_gui_timer
 IMPORTING sender.
 
 ENDCLASS. "lcl_event_handler DEFINITION
 *---------------------------------------------------------------------*
 *CLASS lcl_event_handler IMPLEMENTATION
 *---------------------------------------------------------------------*
 
 CLASS lcl_event_handler IMPLEMENTATION.
 METHOD on_finished.
 
 PERFORM frm_list_clear.
 PERFORM frm_snake_move.
 IF v_isfood IS INITIAL.
 PERFORM frm_food_add.
 v_isfood = 'X'.
 ENDIF.
 PERFORM frm_snake_out.
 
 * Start timer again
 sender->run( ).
 
 ENDMETHOD.                    "on_finished
 ENDCLASS.                    "lcl_event_handler IMPLEMENTATION
 
 PARAMETERS: seconds TYPE i DEFAULT 1.
 
 AT USER-COMMAND.
 CASE sy-ucomm.
 WHEN 'BACK' OR 'UP' OR 'EXIT'.
 LEAVE PROGRAM.
 WHEN 'DOUP'.
 CHECK v_direction NE c_down.
 v_direction = c_up.
 WHEN 'DODOWN'.
 CHECK v_direction NE c_up.
 v_direction = c_down.
 WHEN 'DOLEFT'.
 CHECK v_direction NE c_right.
 v_direction = c_left.
 WHEN 'DORIGHT'.
 CHECK v_direction NE c_left.
 v_direction = c_right.
 ENDCASE.
 
 START-OF-SELECTION.
 
 SET PF-STATUS 'STATUS_0'.
 
 PERFORM frm_build_verge.
 PERFORM frm_list_clear.
 PERFORM frm_snake_init.
 
 CREATE OBJECT rf_gui_timer.
 SET HANDLER lcl_event_handler=>on_finished FOR rf_gui_timer.
 rf_gui_timer->interval = seconds.
 CALL METHOD rf_gui_timer->run.
 
 PERFORM frm_snake_out.
 
 
 *&---------------------------------------------------------------------*
 *&      Form  frm_random_food
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 FORM frm_random_food CHANGING lw_food LIKE LINE OF i_snake.
 DATA: lv_random TYPE i.
 CALL FUNCTION 'QF05_RANDOM_INTEGER'
 EXPORTING
 ran_int_max   = 60
 ran_int_min   = 2
 IMPORTING
 ran_int       = lv_random
 EXCEPTIONS
 invalid_input = 1
 OTHERS        = 2.
 
 lw_food-x = lv_random.
 CALL FUNCTION 'QF05_RANDOM_INTEGER'
 EXPORTING
 ran_int_max   = 20
 ran_int_min   = 4
 IMPORTING
 ran_int       = lv_random
 EXCEPTIONS
 invalid_input = 1
 OTHERS        = 2.
 
 lw_food-y = lv_random.
 
 ENDFORM.                    "frm_random_food
 
 *&---------------------------------------------------------------------*
 *&      Form  frm_food_add
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 FORM frm_food_add.
 DATA: lw_food LIKE LINE OF i_snake.
 DO.
 PERFORM frm_random_food CHANGING lw_food.
 LOOP AT i_snake WHERE x = lw_food-x AND y = lw_food-y.
 EXIT.
 ENDLOOP.
 IF sy-subrc NE 0.
 EXIT.
 ENDIF.
 ENDDO.
 w_food = lw_food.
 ENDFORM.                    "frm_food_add
 
 *&---------------------------------------------------------------------*
 *&      Form  frm_snake_out
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 FORM frm_snake_out.
 DATA: lv_size TYPE i.
 DESCRIBE TABLE i_snake LINES lv_size.
 LOOP AT i_snake.
 SKIP TO LINE i_snake-y.
 IF sy-tabix NE lv_size.
 WRITE AT i_snake-x 'o'.
 ELSE.
 WRITE AT i_snake-x 'O'.
 ENDIF.
 ENDLOOP.
 IF NOT w_food IS INITIAL.
 SKIP TO LINE w_food-y.
 WRITE AT w_food-x '@'.
 ENDIF.
 ENDFORM.                    "frm_snake_out
 
 *&---------------------------------------------------------------------*
 *&      Form  frm_snake_dead_check
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 *      -->LW_SNAKE   text
 *----------------------------------------------------------------------*
 FORM frm_snake_dead_check USING lw_snake LIKE LINE OF i_snake.
 LOOP AT i_snake WHERE x = lw_snake-x AND y = lw_snake-y.
 EXIT.
 ENDLOOP.
 IF sy-subrc EQ 0.
 MESSAGE 'Game over' TYPE 'I' DISPLAY LIKE 'E'.
 LEAVE TO SCREEN 0.
 ENDIF.
 IF lw_snake-y LE 3 OR lw_snake-y GE 24 OR lw_snake-x LE 1 OR lw_snake-x GE 60.
 MESSAGE 'Game over' TYPE 'I' DISPLAY LIKE 'E'.
 LEAVE TO SCREEN 0.
 ENDIF.
 ENDFORM.                    "frm_snake_dead_check
 *&---------------------------------------------------------------------*
 *&      Form  frm_snake_move
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 FORM frm_snake_move.
 DATA: lv_size TYPE i,
 lv_direction TYPE i,
 lw_snake LIKE LINE OF i_snake.
 
 DESCRIBE TABLE i_snake LINES lv_size.
 
 lv_direction = v_direction.
 CASE lv_direction.
 WHEN c_up.
 READ TABLE i_snake INTO lw_snake INDEX lv_size.
 lw_snake-y = lw_snake-y - 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 DELETE i_snake INDEX 1.
 WHEN c_down.
 READ TABLE i_snake INTO lw_snake INDEX lv_size.
 lw_snake-y = lw_snake-y + 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 DELETE i_snake INDEX 1.
 WHEN c_left.
 READ TABLE i_snake INTO lw_snake INDEX lv_size.
 lw_snake-x = lw_snake-x - 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 DELETE i_snake INDEX 1.
 WHEN c_right.
 READ TABLE i_snake INTO lw_snake INDEX lv_size.
 lw_snake-x = lw_snake-x + 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 DELETE i_snake INDEX 1.
 ENDCASE.
 
 IF lw_snake EQ w_food.
 CLEAR v_isfood.
 CASE lv_direction.
 WHEN c_up.
 lw_snake-y = lw_snake-y - 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 WHEN c_down.
 lw_snake-y = lw_snake-y + 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 WHEN c_left.
 lw_snake-x = lw_snake-x - 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 WHEN c_right.
 lw_snake-x = lw_snake-x + 1.
 PERFORM frm_snake_dead_check USING lw_snake.
 APPEND lw_snake TO i_snake.
 ENDCASE.
 ENDIF.
 ENDFORM.                    "frm_snake_move
 
 *&---------------------------------------------------------------------*
 *&      Form  frm_init_snake
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 FORM frm_snake_init.
 DATA lv_x TYPE i VALUE 5.
 DO 40 TIMES.
 i_snake-x = lv_x.
 i_snake-y = 5.
 APPEND i_snake.
 lv_x = lv_x + 1.
 ENDDO.
 ENDFORM.                    "frm_init_snake
 
 *&---------------------------------------------------------------------*
 *&      Form  frm_build_verge
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 FORM frm_build_verge.
 WRITE:/ '############################################################'.
 DO 21 TIMES.
 WRITE AT: 1 '#', 60 '#'.
 NEW-LINE.
 ENDDO.
 WRITE:/ '############################################################'.
 ENDFORM.                    "frm_build_verge
 
 *&---------------------------------------------------------------------*
 *&      Form  frm_list_clear
 *&---------------------------------------------------------------------*
 *       text
 *----------------------------------------------------------------------*
 FORM frm_list_clear.
 DATA: lv_index TYPE i,
 lv_clear TYPE string,
 lv_temp TYPE string VALUE '#                                                          #'.
 lv_index = 4.
 DO 20 TIMES.
 CLEAR: lv_clear.
 READ LINE lv_index LINE VALUE INTO lv_clear.
 IF lv_clear IS NOT INITIAL.
 MODIFY LINE lv_index LINE VALUE FROM lv_temp.
 ENDIF.
 lv_index = lv_index + 1.
 ENDDO.
 ENDFORM.                    "frm_list_clear
 
 
 STATUS_0的定义:
 
 DOUP(F6)       DODOWN(F7)     DOLEFT(F5)     DORIGHT(F8)
 | 
 |