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.

DATABEGIN 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 AT1 '#'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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章