Форум программистов
 
Контакты: о проблемах с регистрацией, почтой и по другим вопросам пишите сюда - alarforum@yandex.ru, проверяйте папку спам! Обязательно пройдите активизацию e-mail.

Вернуться   Форум программистов > C++ > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail


Донат для форума - использовать для поднятия настроения себе и модераторам

А ещё здесь можно купить рекламу за 25 тыс руб в месяц! ) пишите сюда - alarforum@yandex.ru

Ответ
 
Опции темы
Старый 14.08.2019, 00:09   #1
Alexey96
Новичок
 
Регистрация: 13.08.2019
Сообщений: 4
Репутация: 10
По умолчанию Реализация блоков тетриса на С (консольное приложение)

Реализовываю простой тетрис на С в консоли. "Стакан" делаю через двумерный массив фиксированной размерности, где цифрами обозначены стенки и дно, а пустое пространство заполнено 0. Фигуру загружаю также из двумерного массива размером поменьше(4х4). Управление осуществляется стрелками с клавиатуры, программа считывает шестнадцатеричный код нажатой клавиши.

Так вот, трудности возникли на этапе рализации движения блоков тетриса по "стакану". Грубо говоря, есть три возможных направления - вправо, влево и вниз (еще поворот блока, но его пока не учитываем).
Каким способом в обычном С можно реализовать "перемещение" одного массива по другому, с учетом необходимых ограничений (проверка на "стенки" и "пол")? И подходит ли такое решение вообще?
Пока что накидал простенький способ, который очевидно не подходит, но как шаблон пока оставил его. Согласно нему, программа проверяет, есть ли в массиве единицы (цифрами 1 обозначена падающая фигура), затем помещает в левый\правый\нижний от Arr[i][j] элемент единицу или ноль. Очевидно, что этот способ не работает, ну и плюс перемещает по одному элементу за нажатие клавиши, не всю фигуру.

В интернете лежит довольно много реализаций Тетриса на С++/С#, как правило, с использованием сторонних библиотек, но вот подходящего решения для С пока не нашел. Надеюсь на совет знающих людей.
Собственно, код:
Код:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void ShowGlass(int [16][10]);
void Controls(int [16][10],int [4][4]);
void main()
{int Fig[4][4]={0,0,1,0,
                0,1,1,1,
				0,0,0,0,
				0,0,0,0};
int i,j,k,l,s=0,Arr[16][10]={0};
for(i=0;i<16;i++) //Сперва загружаем основу-стакан с "полом" и "стенками"
 {for(j=0;j<10;j++)
   {if(i==15)
      Arr[i][j]=2;//Нижний ярус-пол обозначаем цифрой 2
    if(i!=0&&(j==0||j==9))
	  Arr[i][j]=3;//Левую и правую стенки обозначаем цифрой 3
	 }
 }

for(i=0;i<4;i++)
 {for(j=0;j<4;j++)
  {Arr[i][j+2]=Fig[i][j]; //Присваиваем большому массиву-стакану фигуру из маленького массива
	}
  }
while(1)//Игровой цикл
   {ShowGlass(Arr);
    Controls(Arr,Fig);
    system("cls");}//Стираем игровое поле, чтобы отрисовать его заного на следующем ходу цикла
system("pause"); 
}

void ShowGlass(int Arr[16][10])//Рисуем стакан с фигурой
{int i,j;
for(i=0;i<16;i++)
  {for(j=0;j<10;j++)
    {printf("%d ",Arr[i][j]);}
	putch('\n');
  }
}

void Controls(int Arr[16][10],int Fig[4][4])
{int i,j,k,l,Fig2[4][4];
button:switch(getch())//Считываем кнопки управления
  {case 0x4b://Для кнопки влево
  	   	{for(i=0;i<16;i++)
         {for(j=1;j<10;j++)
          {while((Arr[i][j-1]!=3)&&(Arr[i][j]==1)&&Arr[i+1][j]!=2)
            if(Arr[i][j+1]==1)
             {Arr[i][j-1]=1;Arr[i][j]=1;goto button;}
            else
             {Arr[i][j-1]=1;Arr[i][j]=0;goto button;}
          }
         }
        }
   case 0x4d://Для кнопки вправо
    	{for(i=0;i<16;i++)
         {for(j=1;j<9;j++)
          {while((Arr[i][j+1]!=3)&&(Arr[i][j]==1)&&Arr[i+1][j]!=2)
            if(Arr[i][j-1]==1)
             {Arr[i][j+1]=1;Arr[i][j]=1;goto button;}
            else
             {Arr[i][j+1]=1;Arr[i][j]=0;goto button;}
          }
         }
        }
    case 0x50://Для кнопки вниз
    	{for(i=1;i<16;i++)
         {for(j=0;j<10;j++)
          {while((Arr[i][j]==1)&&Arr[i+1][j]!=2)
            if(Arr[i-1][j]==1)
             {Arr[i+1][j]=1;Arr[i][j]=1;goto button;}
            else
             {Arr[i+1][j]=1;Arr[i][j]=0;goto button;}
          }
         }
        }
    case 0x9://Для поворота по часовой стрелке
    	 {for(k=0;k<4;k++)
           {for(l=0;l<4;l++)
            Fig2[k][l]=Fig[4-l-1][k];
           }
         }
		 {for(k=0;k<4;k++)
           {for(l=0;l<4;l++)
            Fig[k][l]=Fig2[k][l];
           }
         };
    default:;
  }
}
Alexey96 вне форума   Ответить с цитированием
Старый 14.08.2019, 09:14   #2
WorldMaster
Профессионал
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Адрес: Россия, Мурманск
Сообщений: 2,306
Репутация: 705

icq: 359393755
По умолчанию

Чего то сложно в коде разбираться но суть то простая. Чтобы переместить фигуру надо проверить состояние клеток вокруг фигуры.

По коду у вас просто дикость какая то. Надо упрощать код тогда может быть станет понятнее. А вообще начать надо с листочка бумаги в клеточку. Нарисовать стакан и фигуру и там описать логику поведения.
__________________
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
Если помог - нажми на весы
WorldMaster вне форума   Ответить с цитированием
Старый 14.08.2019, 13:51   #3
Alexey96
Новичок
 
Регистрация: 13.08.2019
Сообщений: 4
Репутация: 10
По умолчанию

Цитата:
Сообщение от WorldMaster Посмотреть сообщение
Чего то сложно в коде разбираться но суть то простая. Чтобы переместить фигуру надо проверить состояние клеток вокруг фигуры.
Собственно, идея как раз в этом и состоит. По моему коду берутся клетки вокруг фигуры и происходит проверка. Если клетка - 0, тогда можно двигать в этом направлении. Если 3, то это стенка стакана и дальше двигаться нельзя. Если 2, то это дно стакана, в таком случае нужно забрать у игрока управление той фигурой, присвоить клеткам "упавшей" фигуры 2 вместо 1 и загрузить новую фигуру сверху стакана (модель с разными фигурами и загрузкой новой пока не реализовывал, у меня прототип чисто для того, чтобы разобраться с перемещением фигуры).

Проблема в том, что по одной клетке проверять-перемещать получается дичь, остается вариант двигать весь массив с фигурой в большом массиве стакана. Вот в этом и заключается мой вопрос. Я пытаюсь понять, как можно сделать так, чтобы "маленький" массив двигался по "большому". То есть сделать примерно так, как на картинке.

В моем коде для загрузки фигуры берется цикл по строкам и столбцам массива фигуры (т.е. 4 строки и 4 столбца), затем для этих i и j производится присваиваивание МассивСтакана[i][j]=МассивФигуры[i][j]. Тогда возникает ситуация, что для расположения фигуры посередине верхнего ряда стакана нужно добавить смещение элементов при присваивании, то есть: МассивСтакана[i][j+2]=МассивФигуры[i][j].
Я пробовал таким же смещением сделать движение фигуры, но тогда оно вообще не работает.
Изображения
 
Alexey96 вне форума   Ответить с цитированием
Старый 14.08.2019, 15:09   #4
WorldMaster
Профессионал
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Адрес: Россия, Мурманск
Сообщений: 2,306
Репутация: 705

icq: 359393755
По умолчанию

Ничего себе поле сделали ...
Ну вот короче пока обедал набросал рабочий вариант для одной фигуры.
)))
Не плюсы конечно но синтаксис очень похожий.
Вот так проверять надо можно ли двигаться в стороны.
Код:
enum Direction { Right, Left, Up, Down };

        bool TryMove(Direction dir)
        {
            for (int i = 0; i < figure.GetLength(0); i++)
                for (int j = 0; j < figure.GetLength(1); j++)
                {
                    if (figure[i, j] == 1)
                    {
                        switch (dir)
                        {
                            case Direction.Right:
                                if (i + xLoc + 1 >= playField.GetLength(0) || playField[i + xLoc + 1, j + yLoc] == 2)
                                {
                                    return false;
                                }
                                break;
                            case Direction.Left:
                                if (i + xLoc - 1 < 0 || playField[i + xLoc - 1, j + yLoc] == 2)
                                {
                                    return false;
                                }
                                break;

                            case Direction.Up:
                                if (j + yLoc - 1 < 0 || playField[i + xLoc, j + yLoc - 1] == 2)
                                {
                                    return false;
                                }
                                break;
                            case Direction.Down:
                                if (j + yLoc + 1 >= playField.GetLength(1) || playField[i + xLoc, j + yLoc + 1] == 2)
                                {
                                    return false;
                                }
                                break;
                        }
                    }
                }
            return true;
        }
Изображения
 
__________________
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
Если помог - нажми на весы

Последний раз редактировалось WorldMaster; 14.08.2019 в 15:12.
WorldMaster вне форума   Ответить с цитированием
Старый 14.08.2019, 18:40   #5
Alexey96
Новичок
 
Регистрация: 13.08.2019
Сообщений: 4
Репутация: 10
По умолчанию

Цитата:
Сообщение от WorldMaster Посмотреть сообщение
Ничего себе поле сделали ...
Ну вот короче пока обедал набросал рабочий вариант для одной фигуры.
)))
Не плюсы конечно но синтаксис очень похожий.
Вот так проверять надо можно ли двигаться в стороны.
Спасибо. Пока не понимаю принцип движения фигуры, но буду разбираться. Кстати, за что в вашем коде отвечают xLoc и yLoc?

А поле взято из гугл картинок для примера, оно мне такое большое в реальности не нужно.
Alexey96 вне форума   Ответить с цитированием
Старый 14.08.2019, 19:08   #6
WorldMaster
Профессионал
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Адрес: Россия, Мурманск
Сообщений: 2,306
Репутация: 705

icq: 359393755
По умолчанию

Это координаты фигуры
__________________
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
Если помог - нажми на весы
WorldMaster вне форума   Ответить с цитированием
Старый 14.08.2019, 19:11   #7
waleri
Профессионал
 
Регистрация: 13.07.2012
Адрес: Нижний Новгород
Сообщений: 5,896
Репутация: 1915
По умолчанию

Я бы сделал фигуру массивом из 4 координат, для каждого квадратика фигуры отдельно. Тогда проверка движения это просто проверить для каждого квадратика в отдельности.
waleri на форуме   Ответить с цитированием
Старый 14.08.2019, 19:51   #8
Alexey96
Новичок
 
Регистрация: 13.08.2019
Сообщений: 4
Репутация: 10
По умолчанию

Цитата:
Сообщение от WorldMaster Посмотреть сообщение
Это координаты фигуры
Тогда i и j - координаты массива-"стакана"?
Alexey96 вне форума   Ответить с цитированием
Старый 14.08.2019, 21:35   #9
WorldMaster
Профессионал
 
Аватар для WorldMaster
 
Регистрация: 25.08.2011
Адрес: Россия, Мурманск
Сообщений: 2,306
Репутация: 705

icq: 359393755
По умолчанию

Цитата:
Сообщение от Alexey96 Посмотреть сообщение
Тогда i и j - координаты массива-"стакана"?
Просто индексаторы. Проверяем точки из фигуры в отношени поля игрового
__________________
Skype - wmaster_s E-Mail - WorldMasters@gmail.com
Работаем по 3 критериям - быстро, качественно, недорого. Заказчик выбирает любые два.
Если помог - нажми на весы
WorldMaster вне форума   Ответить с цитированием
Ответ

Опции темы

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Консольное приложение.. C# Serg94 Фриланс 3 21.04.2012 19:45
консольное приложение на С++ Kingstоn Помощь студентам 1 20.06.2011 21:00
Консольное приложение shock-in Общие вопросы Delphi 2 19.12.2009 23:03
Консольное приложение __Demon__ Общие вопросы C/C++ 8 23.10.2009 10:08
Консольное приложение eks-s Общие вопросы Delphi 17 25.01.2008 04:12


22:17.


Powered by vBulletin® Version 3.8.11
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd.