*&---------------------------------------------------------------------*
*& 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)