SAP R/3 форум ABAP консультантов
Russian ABAP Developer's Club

Home - FAQ - Search - Memberlist - Usergroups - Profile - Log in to check your private messages - Register - Log in - English
Blogs - Weblogs News

Sokoban



 
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Programming Techniques | Приемы программирования -> Games
View previous topic :: View next topic  
Author Message
John Doe
Модератор
Модератор


Age: 46
Joined: 05 Nov 2007
Posts: 725
Location: КраснАдар

PostPosted: Wed Jun 11, 2008 4:14 pm    Post subject: Sokoban Reply with quote

Вот навеяло, вспомнил детство и Спекки...
Создаем программу, в ней делаем статус 'NEW', в статусе следующие кнопарики:
Quote:
F2 INFO ICON_INFORMATION
F9 UNDO ICON_SYSTEM_UNDO
F5 PF20 ICON_COLUMN_LEFT
F6 PF21 ICON_COLUMN_RIGHT
F7 PF23 ICON_PREVIOUS_VALUE
F8 PF24 ICON_NEXT_VALUE
Standard Toolbar: EXIT, CANCEL.
Application Toolbar: PF20, PF21, PF23, PF24, UNDO, INFO.

Код программы:
Code:
REPORT  ZSOKOBAN.

INCLUDE <LIST>.
TYPES: BEGIN OF POSITION,
         COUNT TYPE I,
         X TYPE I,
         Y TYPE I,
       END OF POSITION,
       POSTAB TYPE TABLE OF POSITION.
DATA: DIM_WALL TYPE TABLE OF POSITION,
      DIM_PLACE TYPE TABLE OF POSITION,
      DIM_CARGO TYPE TABLE OF POSITION,
      CURR_POS TYPE POSITION,
      OLD_POS TYPE POSITION,
      NEXT_POS TYPE POSITION,
      DOUB_POS TYPE POSITION,
      OBJECT_POS TYPE POSITION.

DATA: BEGIN OF HISTORY OCCURS 0 ,
        STEP TYPE COUNT,
        CURR_POS TYPE POSITION,
        DIM_CARGO TYPE POSTAB,
      END OF HISTORY.
DATA: INFORMATION TYPE TABLE OF TEXT132 WITH HEADER LINE.

DATA: CURR_LINE(132),
      NEXT_LINE(132),
      DOUB_LINE(132).

DATA: LEVEL_NUMBER TYPE I,
      COUNT_LINES TYPE I.
DATA: FACT_POSX TYPE I,
      STEP TYPE COUNT.

DATA: LEVEL TYPE TABLE OF TEXT132 WITH HEADER LINE.

CONSTANTS: WALL VALUE '#',
           CARGO VALUE '$',
           PLACE VALUE '.',
           SOKOBAN VALUE '@'.

INITIALIZATION.
  PERFORM CREATE_INFO.

START-OF-SELECTION.
  SET PF-STATUS 'NEW'.
  LEVEL_NUMBER = LEVEL_NUMBER + 1.
  PERFORM CREATE_LEVEL USING LEVEL_NUMBER.

* User-commands processing
AT USER-COMMAND.
  CASE SY-UCOMM.
    WHEN 'EXIT' OR 'CANCEL'.
      LEAVE PROGRAM.
    WHEN 'UNDO'.
      CHECK STEP > 0.
      READ TABLE HISTORY WITH KEY STEP = STEP.
      DIM_CARGO[] = HISTORY-DIM_CARGO.
      OLD_POS = CURR_POS.
      CURR_POS = HISTORY-CURR_POS.
      DELETE HISTORY WHERE STEP = STEP.
      STEP = STEP - 1.
      PERFORM REDRAW_LEVEL.
    WHEN 'INFO'.
      CALL FUNCTION 'POPUP_WITH_TABLE_DISPLAY'
        EXPORTING
          ENDPOS_COL   = 70
          ENDPOS_ROW   = 15
          STARTPOS_COL = 5
          STARTPOS_ROW = 5
          TITLETEXT    = 'What is Sokoban?'
        TABLES
          VALUETAB     = INFORMATION
        EXCEPTIONS
          BREAK_OFF    = 1.
      IF SY-SUBRC <> 0.
      ENDIF.
      .
  ENDCASE.

AT PF20.  " Left
  PERFORM MOVEMENT USING 'LEFT'.

AT PF21.  " Right
  PERFORM MOVEMENT USING 'RIGHT'.

AT PF23.  " Down
  PERFORM MOVEMENT USING 'DOWN'.

AT PF24.  " Up
  PERFORM MOVEMENT USING 'UP'.


*&---------------------------------------------------------------------*
*&      Form  CREATE_LEVEL
*&---------------------------------------------------------------------*
FORM CREATE_LEVEL  USING    P_NUMBER.
  DATA: X_NEW TYPE I,
       Y_NEW TYPE I.

  DATA: LENGTH TYPE I,
        TEMP_X TYPE I,
        TEMP_Y TYPE I,
        N TYPE I,
        FIELD.

  FREE: HISTORY, LEVEL, DIM_WALL, DIM_PLACE, DIM_CARGO.
  CLEAR: LEVEL, STEP.

  SET TITLEBAR 'NEW' WITH P_NUMBER.

  CASE P_NUMBER.
    WHEN 1.
      APPEND '    ########' TO LEVEL.
      APPEND '  ###     .#' TO LEVEL.
      APPEND '  #.  #### #' TO LEVEL.
      APPEND '###        #' TO LEVEL.
      APPEND '# . @   .# #' TO LEVEL.
      APPEND '# #### ### #' TO LEVEL.
      APPEND '#        # #' TO LEVEL.
      APPEND '#####    # #' TO LEVEL.
      APPEND '    #      #' TO LEVEL.
      APPEND '    # $$$$ #' TO LEVEL.
      APPEND '    #    ###' TO LEVEL.
      APPEND '    ######  ' TO LEVEL.
    WHEN 2.
      APPEND '######## #####' TO LEVEL.
      APPEND '#  #   ###   #' TO LEVEL.
      APPEND '#      ## $  #' TO LEVEL.
      APPEND '#.# @ ## $  ##' TO LEVEL.
      APPEND '#.#   # $  ## ' TO LEVEL.
      APPEND '#.#    $  ##  ' TO LEVEL.
      APPEND '#. ## #####   ' TO LEVEL.
      APPEND '##    #       ' TO LEVEL.
      APPEND ' ######       ' TO LEVEL.
    WHEN 3.
      APPEND '       ####  ' TO LEVEL.
      APPEND '      ##  ###' TO LEVEL.
      APPEND '####  #  $  #' TO LEVEL.
      APPEND '#  #### $ $ #' TO LEVEL.
      APPEND '#   ..# #$  #' TO LEVEL.
      APPEND '#  #   @  ###' TO LEVEL.
      APPEND '## #..# ###  ' TO LEVEL.
      APPEND ' # ## # #    ' TO LEVEL.
      APPEND ' #      #    ' TO LEVEL.
      APPEND ' ########    ' TO LEVEL.
    WHEN 4.
      APPEND '   ###     ' TO LEVEL.
      APPEND '  ## # ####' TO LEVEL.
      APPEND ' ##  ###  #' TO LEVEL.
      APPEND '## $      #' TO LEVEL.
      APPEND '#   @$ #  #' TO LEVEL.
      APPEND '### $###  #' TO LEVEL.
      APPEND '  #  #..  #' TO LEVEL.
      APPEND ' ## ##.# ##' TO LEVEL.
      APPEND ' #      ## ' TO LEVEL.
      APPEND ' #     ##  ' TO LEVEL.
      APPEND ' #######   ' TO LEVEL.
    WHEN 5.
      APPEND '####                  ' TO LEVEL.
      APPEND '#  #              ####' TO LEVEL.
      APPEND '#  ######## #######  #' TO LEVEL.
      APPEND '#         ###  ##  $ #' TO LEVEL.
      APPEND '##.###### ...     #. #' TO LEVEL.
      APPEND ' #.#      # .#   # $ #' TO LEVEL.
      APPEND ' #$$$$#$$$ #.#   ##. #' TO LEVEL.
      APPEND ' #.# $   $ #..      ##' TO LEVEL.
      APPEND ' #.#  $  $   # #   ## ' TO LEVEL.
      APPEND ' #  #   $$ #   #####  ' TO LEVEL.
      APPEND ' #.  ##$  ######      ' TO LEVEL.
      APPEND ' #.   #  $.  #        ' TO LEVEL.
      APPEND '##. @ ###.#$ #        ' TO LEVEL.
      APPEND '#     # #    #        ' TO LEVEL.
      APPEND '#    ## ######        ' TO LEVEL.
      APPEND '######                ' TO LEVEL.

  ENDCASE.

  LOOP AT LEVEL.
    TEMP_X = LENGTH = STRLEN( LEVEL ).
    N = N + 1.
    WHILE LENGTH > 0.
      CLEAR: COUNT_LINES, CURR_POS-COUNT.
      LENGTH = LENGTH - 1.
      FIELD = LEVEL.
      SHIFT LEVEL.
      OBJECT_POS-X = TEMP_X - LENGTH.
      CASE FIELD.
        WHEN WALL.
          WRITE AT OBJECT_POS-X FIELD COLOR COL_NEGATIVE.
          DESCRIBE TABLE DIM_WALL LINES COUNT_LINES.
          CURR_POS-COUNT = COUNT_LINES + 1.
          CURR_POS-X = OBJECT_POS-X. CURR_POS-Y = N.
          APPEND CURR_POS TO DIM_WALL.
        WHEN SOKOBAN.
          WRITE AT OBJECT_POS-X FIELD.
          X_NEW = OBJECT_POS-X - 1.
          Y_NEW = N.
        WHEN CARGO.
          WRITE AT OBJECT_POS-X FIELD.
          DESCRIBE TABLE DIM_CARGO LINES COUNT_LINES.
          CURR_POS-COUNT = COUNT_LINES + 1.
          CURR_POS-X = OBJECT_POS-X. CURR_POS-Y = N.
          APPEND CURR_POS TO DIM_CARGO.
        WHEN PLACE.
          WRITE AT OBJECT_POS-X FIELD COLOR 2.
          DESCRIBE TABLE DIM_PLACE LINES COUNT_LINES.
          CURR_POS-COUNT = COUNT_LINES + 1.
          CURR_POS-X = OBJECT_POS-X. CURR_POS-Y = N.
          APPEND CURR_POS TO DIM_PLACE.
      ENDCASE.
    ENDWHILE.
    NEW-LINE.
  ENDLOOP.

  PERFORM PRINT_LEGEND.

  CURR_POS-X = X_NEW. CURR_POS-Y = Y_NEW. " Start human position

ENDFORM.                    " CREATE_LEVEL


*&---------------------------------------------------------------------*
*&      Form  MOVEMENT
*&---------------------------------------------------------------------*
FORM MOVEMENT  USING    DIRECTION TYPE CHAR10.
  CLEAR: FACT_POSX.
  PERFORM SAVE_HISTORY.

  CASE DIRECTION.
    WHEN 'LEFT' OR 'RIGHT'.
      IF DIRECTION EQ 'LEFT'.
        NEXT_POS-X = CURR_POS-X - 1.
        DOUB_POS-X = CURR_POS-X - 2.
      ELSE.
        NEXT_POS-X = CURR_POS-X + 1.
        DOUB_POS-X = CURR_POS-X + 2.
      ENDIF.

      READ LINE CURR_POS-Y LINE VALUE INTO CURR_LINE.
      CASE CURR_LINE+NEXT_POS-X(1).
        WHEN SPACE OR PLACE.
          CURR_LINE+NEXT_POS-X(1) = CURR_LINE+CURR_POS-X(1).
          CURR_LINE+CURR_POS-X(1) = SPACE.
          CURR_POS-X = NEXT_POS-X.
        WHEN WALL.
          CLEAR: NEXT_POS, DOUB_POS.
          EXIT.
        WHEN CARGO.
          CASE CURR_LINE+DOUB_POS-X(1).
            WHEN SPACE OR PLACE.
              FACT_POSX = NEXT_POS-X + 1.
              READ TABLE DIM_CARGO INTO OBJECT_POS
                WITH KEY X = FACT_POSX
                         Y = CURR_POS-Y.
              FACT_POSX = FACT_POSX + 1.
              IF DIRECTION EQ 'LEFT'.
                OBJECT_POS-X = NEXT_POS-X.
              ELSE.
                OBJECT_POS-X = DOUB_POS-X + 1.
              ENDIF.
              MODIFY DIM_CARGO FROM OBJECT_POS INDEX OBJECT_POS-COUNT.

              CURR_LINE+NEXT_POS-X(1) = CURR_LINE+CURR_POS-X(1).
              CURR_LINE+CURR_POS-X(1) = SPACE.
              CURR_POS-X = NEXT_POS-X.
            WHEN WALL OR CARGO.
              CLEAR: NEXT_POS, DOUB_POS.
              EXIT.
          ENDCASE.
      ENDCASE.
      CLEAR: NEXT_POS, DOUB_POS.
      MODIFY LINE CURR_POS-Y LINE VALUE FROM CURR_LINE.

    WHEN 'DOWN' OR 'UP'.
      IF DIRECTION EQ 'DOWN'.
        NEXT_POS-Y = CURR_POS-Y + 1.
        DOUB_POS-Y = CURR_POS-Y + 2.
      ELSE.
        NEXT_POS-Y = CURR_POS-Y - 1.
        DOUB_POS-Y = CURR_POS-Y - 2.
      ENDIF.

      READ LINE CURR_POS-Y LINE VALUE INTO CURR_LINE.
      READ LINE NEXT_POS-Y LINE VALUE INTO NEXT_LINE.
      READ LINE DOUB_POS-Y LINE VALUE INTO DOUB_LINE.
      CASE NEXT_LINE+CURR_POS-X(1).
        WHEN SPACE OR PLACE.
          NEXT_LINE+CURR_POS-X(1) = CURR_LINE+CURR_POS-X(1).
          CURR_LINE+CURR_POS-X(1) = SPACE.
        WHEN WALL.
          CLEAR: NEXT_POS, DOUB_POS.
          EXIT.
        WHEN CARGO.
          CASE DOUB_LINE+CURR_POS-X(1).
            WHEN SPACE OR PLACE.
              FACT_POSX = CURR_POS-X + 1.
              READ TABLE DIM_CARGO INTO OBJECT_POS
                WITH KEY X = FACT_POSX
                         Y = NEXT_POS-Y.
              OBJECT_POS-Y = DOUB_POS-Y.
              MODIFY DIM_CARGO FROM OBJECT_POS INDEX OBJECT_POS-COUNT.

              NEXT_LINE+CURR_POS-X(1) = CURR_LINE+CURR_POS-X(1).
              CURR_LINE+CURR_POS-X(1) = SPACE.
            WHEN WALL OR CARGO.
              CLEAR: NEXT_POS, DOUB_POS.
              EXIT.
          ENDCASE.
      ENDCASE.
      MODIFY LINE CURR_POS-Y LINE VALUE FROM CURR_LINE.
      MODIFY LINE NEXT_POS-Y LINE VALUE FROM NEXT_LINE.
      MODIFY LINE DOUB_POS-Y LINE VALUE FROM DOUB_LINE.
      CURR_POS-Y = NEXT_POS-Y.
      CLEAR: NEXT_POS, DOUB_POS.

  ENDCASE.

  PERFORM REDRAW_LEVEL.
  PERFORM CHECK_COMPLETE.
  PERFORM PRINT_LEGEND.
ENDFORM.                    " MOVEMENT


*&---------------------------------------------------------------------*
*&      Form  REDRAW_LEVEL
*&---------------------------------------------------------------------*
FORM REDRAW_LEVEL .
  DATA: POSX TYPE I.
* Clear level
  PERFORM CLEAR_LEVEL.

* Restore soko-ban
  READ LINE CURR_POS-Y LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+CURR_POS-X(1) = SOKOBAN.
  MODIFY LINE CURR_POS-Y LINE VALUE FROM NEXT_LINE.

* Restore wall
  LOOP AT DIM_WALL INTO OBJECT_POS.
    READ LINE OBJECT_POS-Y LINE VALUE INTO NEXT_LINE.
    POSX = OBJECT_POS-X - 1.
    IF NEXT_LINE+POSX(1) IS INITIAL.
      NEXT_LINE+POSX(1) = WALL.
    ENDIF.
    MODIFY LINE OBJECT_POS-Y LINE VALUE FROM NEXT_LINE.
    CLEAR NEXT_LINE.
  ENDLOOP.

* Restore placement
  LOOP AT DIM_PLACE INTO OBJECT_POS.
    READ LINE OBJECT_POS-Y LINE VALUE INTO NEXT_LINE.
    POSX = OBJECT_POS-X - 1.
    IF NEXT_LINE+POSX(1) IS INITIAL.
      NEXT_LINE+POSX(1) = PLACE.
    ENDIF.
    MODIFY LINE OBJECT_POS-Y LINE VALUE FROM NEXT_LINE.
    CLEAR NEXT_LINE.
  ENDLOOP.

* Restore cargo
  LOOP AT DIM_CARGO INTO OBJECT_POS.
    READ LINE OBJECT_POS-Y LINE VALUE INTO NEXT_LINE.
    POSX = OBJECT_POS-X - 1.
    IF NEXT_LINE+POSX(1) IS INITIAL OR NEXT_LINE+POSX(1) EQ PLACE.
      NEXT_LINE+POSX(1) = CARGO.
    ENDIF.
    MODIFY LINE OBJECT_POS-Y LINE VALUE FROM NEXT_LINE.
    CLEAR NEXT_LINE.
  ENDLOOP.

ENDFORM.                    " REDRAW_LEVEL


*&---------------------------------------------------------------------*
*&      Form  CHECK_COMPLETE
*&---------------------------------------------------------------------*
FORM CHECK_COMPLETE .
  DATA: FOUND,
        CARGO_POS TYPE POSITION.

  LOOP AT DIM_PLACE INTO OBJECT_POS.
    READ TABLE DIM_CARGO
      WITH KEY X = OBJECT_POS-X
               Y = OBJECT_POS-Y
      TRANSPORTING NO FIELDS.
    IF SY-SUBRC <> 0.
      FOUND = 'X'.
      EXIT.
    ENDIF.
  ENDLOOP.

  IF FOUND IS INITIAL. " Complete
    MESSAGE 'Level complete' TYPE 'I'.
    LEVEL_NUMBER = LEVEL_NUMBER + 1.
    PERFORM CLEAR_LEVEL.
    PERFORM CREATE_LEVEL USING LEVEL_NUMBER.
  ENDIF.

ENDFORM.                    " CHECK_COMPLETE


*&---------------------------------------------------------------------*
*&      Form  SAVE_HISTORY
*&---------------------------------------------------------------------*
FORM SAVE_HISTORY .
  DESCRIBE TABLE HISTORY LINES COUNT_LINES.
  STEP = HISTORY-STEP = COUNT_LINES + 1.
  HISTORY-CURR_POS = CURR_POS.
  HISTORY-DIM_CARGO = DIM_CARGO[].
  APPEND HISTORY.
ENDFORM.                    " SAVE_HISTORY


*&---------------------------------------------------------------------*
*&      Form  CLEAR_LEVEL
*&---------------------------------------------------------------------*
FORM CLEAR_LEVEL .
  CLEAR NEXT_LINE.
  DO.
    MODIFY LINE SY-INDEX LINE VALUE FROM NEXT_LINE.
    IF SY-SUBRC <> 0.
      EXIT.
    ENDIF.
  ENDDO.
ENDFORM.                    " CLEAR_LEVEL


*&---------------------------------------------------------------------*
*&      Form  CREATE_INFO
*&---------------------------------------------------------------------*
FORM CREATE_INFO .
  APPEND:
  'Sokoban is a logic game consisting of sets of puzzles or "levels"' TO INFORMATION,
  'similar to the example shown above. It is not a video game and'  TO INFORMATION,
  'does not require quick reflexes nor does it involve blasting'  TO INFORMATION,
  'aliens to bits. Sokoban means warehouse keeper in Japanese.' TO INFORMATION,
  'The player pushes objects (balls, crates or money bags depending' TO INFORMATION,
  'on the version) to their correct destinations in a crowded' TO INFORMATION,
  '"warehouse". The puzzles range from very simple to extremely' TO INFORMATION,
  'difficult ones requiring many hours of brain work.' TO INFORMATION,
  INITIAL LINE TO INFORMATION,
  'The game was invented in Japan and won a computer game contest' TO INFORMATION,
  'there. The original program was written by Hiroyuki Imabayashi' TO INFORMATION,
  'and is Copyright (c) 1982 by THINKING RABBIT Inc. JAPAN. Since' TO INFORMATION,
  'then, many other versions of the program have been written and' TO INFORMATION,
  'additional sets of puzzles have been created. Many of these may' TO INFORMATION,
  'be found by searching the internet' TO INFORMATION.
ENDFORM.                    " CREATE_INFO

*&---------------------------------------------------------------------*
*&      Form  PRINT_LEGEND
*&---------------------------------------------------------------------*
FORM PRINT_LEGEND .
  READ LINE 1 LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+30 = '@ - warehause keeper (sokoban)'.
  MODIFY LINE 1 LINE VALUE FROM NEXT_LINE.
  READ LINE 2 LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+30 = '# - wall'.
  MODIFY LINE 2 LINE VALUE FROM NEXT_LINE.
  READ LINE 3 LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+30 = '. - warehause place'.
  MODIFY LINE 3 LINE VALUE FROM NEXT_LINE.
  READ LINE 4 LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+30 = '$ - good'.
  MODIFY LINE 4 LINE VALUE FROM NEXT_LINE.
  READ LINE 5 LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+30 = 'You must keep all goods at warehause places.'.
  MODIFY LINE 5 LINE VALUE FROM NEXT_LINE.
  READ LINE 6 LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+30 = 'You can push only one good at time.'.
  MODIFY LINE 6 LINE VALUE FROM NEXT_LINE.
  READ LINE 7 LINE VALUE INTO NEXT_LINE.
  NEXT_LINE+30 = 'Keys: F5 left; F6 right; F7 down; F8 up; F9 undo'.
  MODIFY LINE 7 LINE VALUE FROM NEXT_LINE.
ENDFORM.                    " PRINT_LEGEND
Back to top
View user's profile Send private message Blog
Display posts from previous:   
Post new topic   Reply to topic    Russian ABAP Developer's Club Forum Index -> Programming Techniques | Приемы программирования -> Games All times are GMT + 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


All product names are trademarks of their respective companies. SAPNET.RU websites are in no way affiliated with SAP AG.
SAP, SAP R/3, R/3 software, mySAP, ABAP, BAPI, xApps, SAP NetWeaver and any other are registered trademarks of SAP AG.
Every effort is made to ensure content integrity. Use information on this site at your own risk.