Это программа в общее пользование
Code:
REPORT ZTETRIS NO STANDARD PAGE HEADING.
  include <icon>.
* логический тип
  types:
    TBool type c.
  constants:
    true type TBool value 'X',
    false type TBool value space.
* поле
  data:
    C_FIELD_WIDTH type i,
    C_FIELD_HEIGHT type i.
  C_FIELD_WIDTH = 15.
  C_FIELD_HEIGHT = sy-srows / 2.
  types:
    begin of TCell,
      X type i,
      Y type i,
      content(4) type c,
    end of TCell.
  data:
    g_t_cell type hashed table of TCell
    with unique key Y X.
* поле для сброса
  types:
    TTCell type table of TCell with default key,
    TTRow type table of TTCell.
* фигуры
  constants:
    C_NUM_FIGURES type i value 7.
  types:
    begin of TPos,
      X type i,
      Y type i,
    end of TPos,
    TTPos type table of TPos with default key,
    begin of TFigure,
      fig_num type i,
      rot_num type i,
      t_pos type TTPos,
    end of TFigure,
    TTFigure type hashed table of TFigure
    with unique key fig_num rot_num.
  data:
    g_t_figure type TTFigure,
    begin of g_act_figure,
      fig_num type i,
      rot_num type i,
      X type i,
      Y type i,
    end of g_act_figure.
* заствака
  perform show_top_users.
  return.
* очки
  data:
    g_score type i,
    g_speed type i,
    g_is_game_over type TBool.
*ЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖ
*
* процесс...
*
*ЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖ
form process.
  g_speed = 500.
  perform init_figures.
  perform init_field.
  perform init_field_figure.
  perform redraw.
  call function 'ZDELAY'
  starting new task 'TETRIS'
  performing return_info on end of task
  exporting
    p_milsec = g_speed
  exceptions
    others = 1.
endform.
*ЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖ
*
* движение...
*
*ЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖ
* асинхронный вызов
form return_info using taskname.
  receive results from function 'ZDELAY'
  exceptions
    others = 1.
  set user-command 'MOVE'.
endform.
* движение
at user-command.
  if sy-ucomm = 'MOVE'.
    data:
      v_old_figure like g_act_figure,
      v_new_figure like g_act_figure.
    v_old_figure = v_new_figure = g_act_figure.
    v_new_figure-Y = v_new_figure-Y + 1.
    perform move_figure
    using
      v_old_figure
      v_new_figure
      true.
    if sy-subrc <> 0.
      perform check_field.
      perform init_field_figure.
      if sy-subrc <> 0.
        perform game_over.
      else.
        perform redraw.
        call function 'ZDELAY'
        starting new task 'TETRIS'
        performing return_info on end of task
        exporting
          p_milsec = g_speed
        exceptions
          others = 1.
      endif.
    endif.
  endif.
* перевернуть фигуру
at pf7.
  if g_is_game_over = true or g_speed = 0.
    exit.
  endif.
  v_old_figure = v_new_figure = g_act_figure.
  if v_new_figure-rot_num = 4.
    clear v_new_figure-rot_num.
  endif.
  v_new_figure-rot_num = v_new_figure-rot_num + 1.
  perform move_figure
  using
    v_old_figure
    v_new_figure
    false.
* сдвинуть фигуру влево
at pf6.
  if g_is_game_over = true or g_speed = 0.
    exit.
  endif.
  v_old_figure = v_new_figure = g_act_figure.
  v_new_figure-X = v_new_figure-X - 1.
  perform move_figure
  using
    v_old_figure
    v_new_figure
    false.
* сдвинуть фигуру вправо
at pf8.
  if g_is_game_over = true or g_speed = 0.
    exit.
  endif.
  v_old_figure = v_new_figure = g_act_figure.
  v_new_figure-X = v_new_figure-X + 1.
  perform move_figure
  using
    v_old_figure
    v_new_figure
    false.
* бросить вниз
at pf5.
  if g_is_game_over = true or g_speed = 0.
    exit.
  endif.
  do.
    v_old_figure = v_new_figure = g_act_figure.
    v_new_figure-Y = v_new_figure-Y + 1.
    perform move_figure
    using
      v_old_figure
      v_new_figure
      false.
    if sy-subrc <> 0.
      perform check_field.
      perform init_field_figure.
      perform redraw.
      call function 'ZDELAY'
      starting new task 'TETRIS'
      performing return_info on end of task
      exporting
        p_milsec = g_speed
      exceptions
        others = 1.
      exit.
    endif.
  enddo.
* сдвинуть фигуру
* {
*   sy-subrc = 0 - успешно
* }
form move_figure
using
  p_old_figure like g_act_figure
  p_new_figure like g_act_figure
  p_do_more type TBool.
  clear sy-lsind.
  perform set_field_figure
  using
    space
    false.
  g_act_figure = p_new_figure.
  perform set_field_figure
  using
    ICON_STATUS_BEST
    true.
  if sy-subrc = 0.
    perform set_field_figure
    using
      ICON_STATUS_BEST
      false.
    perform redraw.
    if p_do_more = true.
      call function 'ZDELAY'
      starting new task 'TETRIS'
      performing return_info on end of task
      exporting
        p_milsec = g_speed
      exceptions
        others = 1.
    endif.
    clear sy-subrc.
  else.
    g_act_figure = p_old_figure.
    perform set_field_figure
    using
      ICON_STATUS_BEST
      false.
    sy-subrc = 1.
  endif.
endform.
* проверить поле и сбросить строки
form check_field.
* копируем во временную таблицу
  data:
    v_t_row type TTRow,
    v_cell like line of g_t_cell[].
  do C_FIELD_HEIGHT times.
    v_cell-Y = sy-index.
    field-symbols:
      <row> like line of v_t_row[].
    append initial line to v_t_row assigning <row>.
    do C_FIELD_WIDTH times.
      v_cell-X = sy-index.
      field-symbols:
        <cell> like line of g_t_cell[].
      read table g_t_cell
      with table key
        Y = v_cell-Y
        X = v_cell-X
      assigning
        <cell>.
      append <cell> to <row>.
    enddo.
  enddo.
* удаляем заполненные строки
  loop at v_t_row assigning <row>.
    data:
      v_row_num type i.
    v_row_num = sy-tabix.
    loop at <row> assigning <cell>.
      if sy-tabix = 1.
        continue.
      endif.
      if <cell>-content <> ICON_STATUS_BEST.
        exit.
      endif.
    endloop.
    if <cell>-X = C_FIELD_WIDTH.
      delete v_t_row index v_row_num.
    endif.
  endloop.
* удаляем заполненные строки
  v_row_num = C_FIELD_HEIGHT - lines( v_t_row ).
  data:
    v_row like <row>.
  do C_FIELD_WIDTH times.
    v_cell-X = sy-index.
    if v_cell-X = 1 or v_cell-X = C_FIELD_WIDTH.
      v_cell-content = ICON_OO_CLASS.
    else.
      v_cell-content = space.
    endif.
    append v_cell to v_row.
  enddo.
  do v_row_num times.
    insert v_row into v_t_row index 1.
    g_score = g_score + 100.
    g_speed = g_speed - 2.
  enddo.
* переписываем строки в хэш таблицу
  loop at v_t_row assigning <row>.
    v_row_num = sy-tabix.
    loop at <row> assigning <cell>.
      field-symbols:
        <cell2> like line of g_t_cell[].
      read table g_t_cell
      with table key
        Y = v_row_num
        X = sy-tabix
      assigning
        <cell2>.
      <cell2>-content = <cell>-content.
    endloop.
  endloop.
endform.
*ЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖ
*
* подпрограммы...
*
*ЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖЖ
* подготовить фигуры
form init_figures.
  data:
    v_figures type string.
  define DEF_FIGURE.
    concatenate v_figures &1 into v_figures.
  end-of-definition.
  DEF_FIGURE `0 0 0 -1 0 1 1 1 0 0 -1 0 1 0 1 -1 0 0 0 -1 -1 -1 0 1 0 0 -1 0 1 0 -1 1`.
  DEF_FIGURE ` 0 0 0 -1 1 -1 1 0 0 0 0 -1 1 -1 1 0 0 0 0 -1 1 -1 1 0 0 0 0 -1 1 -1 1 0`.
  DEF_FIGURE ` 0 0 0 -1 1 0 1 1 0 0 -1 0 0 -1 1 -1 0 0 0 -1 1 0 1 1 0 0 -1 0 0 -1 1 -1`.
  DEF_FIGURE ` 0 0 0 -1 0 1 0 2 0 0 -1 0 1 0 2 0 0 0 0 -1 0 1 0 2 0 0 -1 0 1 0 2 0`.
  DEF_FIGURE ` 0 0 0 -1 0 1 -1 1 0 0 1 0 -1 0 -1 -1 0 0 0 -1 1 -1 0 1 0 0 -1 0 1 0 1 1`.
  DEF_FIGURE ` 0 0 1 0 1 -1 0 1 0 0 -1 0 0 1 1 1 0 0 1 0 1 -1 0 1 0 0 -1 0 0 1 1 1`.
  DEF_FIGURE ` 0 0 -1 0 1 0 0 1 0 0 0 -1 0 1 1 0 0 0 -1 0 1 0 0 -1 0 0 0 -1 0 1 -1 0`.
  data:
    v_t_figure_str type table of string with header line.
  split v_figures at space into table v_t_figure_str.
  data:
    v_figure like line of g_t_figure[],
    v_index type i.
  field-symbols:
    <pos> like line of v_figure-t_pos[].
  do C_NUM_FIGURES times.
    v_figure-fig_num = sy-index.
    clear v_figure-rot_num.
    do 4 times.
      v_figure-rot_num = sy-index.
      refresh v_figure-t_pos[].
      do 4 times.
        append initial line to v_figure-t_pos assigning <pos>.
        v_index = v_index + 1.
        read table v_t_figure_str index v_index.
        <pos>-X = v_t_figure_str.
        v_index = v_index + 1.
        read table v_t_figure_str index v_index.
        <pos>-Y = v_t_figure_str.
      enddo.
      insert v_figure into table g_t_figure.
    enddo.
  enddo.
endform.
* инициировать поле
form init_field.
  data:
    v_cell like line of g_t_cell[].
  do C_FIELD_HEIGHT times.
    v_cell-Y = sy-index.
    do C_FIELD_WIDTH times.
      v_cell-X = sy-index.
      if v_cell-X = 1 or v_cell-X = C_FIELD_WIDTH or v_cell-Y = C_FIELD_HEIGHT.
        v_cell-content = ICON_OO_CLASS.
      else.
        v_cell-content = space.
      endif.
      insert v_cell into table g_t_cell.
    enddo.
  enddo.
endform.
* разместить фигуру на поле
* {
*   sy-subrc = 0 - успешно
* }
form init_field_figure.
  data:
    v_value type f.
  perform get_random_value
  changing
    v_value.
  g_act_figure-fig_num = trunc( v_value * 100 / ( 100 / C_NUM_FIGURES ) ) + 1.
  g_act_figure-rot_num = 1.
  g_act_figure-X = 7.
  g_act_figure-Y = 2.
  perform set_field_figure
  using
    ICON_STATUS_BEST
    true.
  if sy-subrc = 0.
    perform set_field_figure
    using
      ICON_STATUS_BEST
      false.
    g_score = g_score + 10.
  endif.
endform.
* установить фигуру на поле
* {
*   sy-subrc = 0 - успешно
* }
form set_field_figure
using
  p_content type TCell-content
  p_check type TBool.
  field-symbols:
    <figure> like line of g_t_figure[].
  read table g_t_figure
  with table key
    fig_num = g_act_figure-fig_num
    rot_num = g_act_figure-rot_num
  assigning
    <figure>.
  field-symbols:
    <pos> like line of <figure>-t_pos[].
  loop at <figure>-t_pos assigning <pos>.
    perform set_field_cell
    using
      g_act_figure-X
      g_act_figure-Y
      <pos>-X
      <pos>-Y
      p_content
      p_check.
    if sy-subrc <> 0.
      return.
    endif.
  endloop.
  clear sy-subrc.
endform.
* установить ячейку поля
* {
*   sy-subrc = 0 - успешно
* }
form set_field_cell
using
  value(p_X) type TCell-X
  value(p_Y) type TCell-Y
  p_X_offs type TPos-X
  p_Y_offs type TPos-Y
  p_content type TCell-content
  p_check type TBool.
  p_X = p_X + p_X_offs.
  p_Y = p_Y + p_Y_offs.
  field-symbols:
    <cell> like line of g_t_cell[].
  read table g_t_cell
  with table key
    Y = p_Y
    X = p_X
  assigning
    <cell>.
  if not <cell>-content is initial and not p_content is initial.
    sy-subrc = 1.
  else.
    if p_check = false.
      <cell>-content = p_content.
    endif.
    clear sy-subrc.
  endif.
endform.
* перерисовать поле
form redraw.
  sy-linno = 1.
  data:
    v_X type i,
    v_Y type i,
    v_score_Y type i.
  v_score_Y = C_FIELD_HEIGHT / 2 - 1.
  do C_FIELD_HEIGHT times.
    v_Y = sy-index.
    do C_FIELD_WIDTH times.
      v_X = sy-index.
      field-symbols:
        <cell> like line of g_t_cell[].
      read table g_t_cell
      with table key
        Y = v_Y
        X = v_X
      assigning
        <cell>.
      if sy-subrc = 0.
        data:
          v_show_X type i.
        v_show_X = v_X * 4.
        write at v_show_X <cell>-content.
      endif.
    enddo.
    if v_score_Y = v_Y.
      data:
        v_score_str type string.
      v_score_str = g_score.
      condense v_score_str.
      concatenate `Очки: ` v_score_str into v_score_str.
      data:
        v_score_X type i.
      v_score_X = C_FIELD_WIDTH * 4 + ( sy-scols - C_FIELD_WIDTH * 4 - ( strlen( ICON_READ_FILE ) + 8 ) ) / 2.
      if v_score_X <= C_FIELD_WIDTH.
        v_score_X = C_FIELD_WIDTH * 4 + 5.
      endif.
      write: at v_score_X ICON_READ_FILE as icon, v_score_str.
    endif.
    write /.
  enddo.
endform.
* получить случайное число в диапазоне от 0..1
form get_random_value
changing
  p_value type f.
  statics:
    v_random_seed type i.
  constants:
    v_s type i value 16807,
    v_m(6) type p value 2147483648.
  data:
    v_ks type string.
  if v_random_seed is initial.
    v_ks = sy-uzeit.
    shift v_ks circular.
    shift v_ks circular.
    shift v_ks circular.
    shift v_ks circular.
    v_random_seed = v_ks * v_ks mod ( v_m - 1 ).
  endif.
  v_random_seed = ( v_random_seed * v_s ) mod ( v_m - 1 ).
  p_value = v_random_seed / v_m.
endform.
* показать чемпионов
form show_top_users.
  data:
    v_t_user type table of ztetuser with header line.
  select
    *
  into table
    v_t_user
  from
    ztetuser.
  sort v_t_user by score descending.
  loop at v_t_user.
    if sy-tabix > 10.
      delete v_t_user index sy-tabix.
    endif.
  endloop.
  data:
    v_col type i,
    v_row type i.
  v_row = ( sy-srows - ( lines( v_t_user ) + 14 ) * 2 ) / 2.
  do v_row times.
    write /.
  enddo.
  v_col = ( sy-scols - 68 ) / 2 + 33.
  write: /, at v_col 'ТЕТРИС', /, /.
  v_col = v_col - 33.
  v_col = v_col + 17.
  write: /,
    at v_col ICON_COLUMN_LEFT as icon, '- (F6)',
    ICON_MODIFY as icon, '- (F7)',
    ICON_COLUMN_RIGHT as icon, '- (F8)',
    ICON_PREVIOUS_VALUE as icon, '- (F5)', /, /.
  v_col = v_col - 17.
  v_col = v_col + 25.
  write: /, at v_col 'Список бездельников!'.
  write: /, at v_col '--------------------', /.
  v_col = v_col - 25.
  loop at v_t_user.
    data:
      v_user type USR03,
      v_full_name type string.
    v_full_name = sy-tabix.
    clear v_user.
    CALL FUNCTION 'SUSR_SHOW_USER_DETAILS'
    EXPORTING
      BNAME = v_t_user-username
      NO_DISPLAY = 'X'
    CHANGING
      USER_USR03 = v_user.
    concatenate
      v_full_name ` ` v_t_user-username ` (` v_user-name1 ` ` v_user-name2 `)`
    into
      v_full_name.
    write: /, at v_col v_full_name.
    v_col = v_col + 60.
    write at v_col v_t_user-score.
    v_col = v_col - 60.
  endloop.
  call function 'ZDELAY'
  starting new task 'TETRIS0'
  performing return_info0 on end of task
    exporting
  p_milsec = 5000
    exceptions
  others = 1.
endform.
* задержка
form return_info0 using taskname.
  receive results from function 'ZDELAY'
  exceptions
    others = 1.
  perform process.
endform.
* конец игры
form game_over.
  g_is_game_over = true.
  constants:
    C_GAME_OVER type string value 'Конец игры!'.
  sy-linno = 1.
  data:
    v_cnt type i.
  v_cnt = sy-srows / 2 - 1.
  do v_cnt times.
    write /.
  enddo.
  v_cnt = ( sy-scols - strlen( C_GAME_OVER ) ) / 2.
  write at v_cnt C_GAME_OVER.
  data:
    v_user type ztetuser.
  select single
    *
  into
    v_user
  from
    ztetuser
  where
    username = sy-uname.
  if sy-subrc = 0.
    if v_user-score >= g_score.
      exit.
    endif.
  endif.
  v_user-username = sy-uname.
  v_user-score = g_score.
  modify ztetuser from v_user.
endform.
FUNCTION ZDELAY.
*"----------------------------------------------------------------------
*"*"Локальный интерфейс:
*"  IMPORTING
*"     VALUE(P_MILSEC) TYPE  I
*"----------------------------------------------------------------------
  data:
    v_ts type timestampl,
    v_ts_new type timestampl,
    v_delta type i.
  get time stamp field v_ts.
  while v_delta <= p_milsec.
    get time stamp field v_ts_new.
    v_delta = ( v_ts_new - v_ts ) * 1000.
  endwhile.
ENDFUNCTION.