Консультация № 182497
12.03.2011, 21:46
54.37 руб.
13.03.2011, 21:27
0 13 1
Здравствуйте, уважаемые эксперты! Прошу вас ответить на следующий вопрос: Помогите написать программу на С++. ОС Windows XP. Программа должна работать как на Borland Builder C++ 6,2006 так и на VS 2005. Код программы прокомментировать. Условие задачи: Написать тетрис на поле определенного размера, размер фигуры 4 клетки скорость падения управляется автоматически в зависимости от времени игры! Заранее спасибо!!!

Обсуждение

Неизвестный
13.03.2011, 21:41
общий
В каком смысле вопрос перенесен??? и куда???
Неизвестный
13.03.2011, 21:44
общий
Вы можете посмотреть здесь:

http://kladovka.net.ru/index.cgi?pid=dir&rid=30
Неизвестный
13.03.2011, 21:49
общий
а почему здесь ни кто программу не пишет????
Неизвестный
13.03.2011, 22:29
общий
Срок действия Вашего вопроса ещё не истёк, к тому же Ваш вопрос только недавно перенесли в правильную рассылку.
Уточните, это должно быть оконное приложение или консоль? Если оконное, то какими средствами?
Неизвестный
14.03.2011, 10:21
общий
Почему я перенёс Ваш вопрос - Вы немного ошиблись рассылкой. Такое бывает.

Вы задали вопрос в рассылку "1С для программиста", впрочем и на встроенном языке "1С:Предприятия" можно написать тетрис.
Вот реализация на платформе версии 7.7: infostart.ru или вот: infostart.ru.
А вот и для 1С 8 версии: infostart.ru.

Кстати, везде код открыт, если есть 1С - можете посмотреть код в конфигураторе 1С.
Успехов!
Неизвестный
17.03.2011, 00:01
общий
Извините что тороплю, ну как бы время истекает, а решение задачи еще нет.... как долго еще ждать???
Неизвестный
17.03.2011, 00:46
общий
Вы бы хотя бы ответили на мой вопрос:
Цитата: 24617
Уточните, это должно быть оконное приложение или консоль? Если оконное, то какими средствами?
Неизвестный
18.03.2011, 18:18
общий
Это должно быть оконное приложение. Должно работать в Borland Builder C++ 6
Неизвестный
18.03.2011, 18:36
общий
В Builder и в Visual Studio разные оконные библиотеки, Вам принципиально, чтобы работало в обеих средах (тогда нужно писать на WinApi)?
Неизвестный
18.03.2011, 18:50
общий
Я просто не очень соображаю в этом языке..... Мне главное чтобы работало в Builder. И к коду программы мне нужны пояснения....мне делать курсач по этой игре
Неизвестный
18.03.2011, 19:24
общий
Ну, вот такой, например, пойдёт?
Прикрепленные файлы:
48167861e7f81b3ac8c14cf1a811e667.rar
Неизвестный
18.03.2011, 19:36
общий
Ну в принципе Да. Но если можно, больше комментариев.... Я просто в нем вообще не соображаю))))) а так программа вполне нормальная.
Неизвестный
18.03.2011, 21:49
общий
это ответ
Здравствуйте, Артем Воробьев!
Вот программа под Builder 6, взята отсюда, я только добавила функцию увеличения скорости падения. В приложении - основной код, в архиве - весь проект.
Добавила некоторое количество комментариев к имевшимся, если что-то непонятно, спрашивайте.
Удачи!

Приложение:
#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
int PoleW,PoleH; //ширина и высота поля
Graphics::TBitmap *Buffer; //буфер для фигуры
Graphics::TBitmap *Block; //один блок
TPoint BlockPos; //позиция блока
int BlockType; //тип текущего блока
int NextBlock; //следующий блок
int Pole[10][18]; //само поле
int Score; //рейтинг
int speed; //скорость падения
int rtime; //время игры

//Тут мы закодировали матрицами сами фигуры. 1 - точка есть, 0 - точки нет.
int FiguraData[7][16]=
{
0,0,0,0,
1,1,1,0,
1,0,0,0,
0,0,0,0,

0,0,0,0,
0,1,1,1,
0,0,0,1,
0,0,0,0,

0,0,0,0,
0,1,1,0,
1,1,0,0,
0,0,0,0,

0,0,0,0,
1,1,0,0,
0,1,1,0,
0,0,0,0,

0,0,0,0,
0,1,0,0,
1,1,1,0,
0,0,0,0,

0,0,0,0,
0,0,0,0,
1,1,1,1,
0,0,0,0,

0,0,0,0,
0,1,1,0,
0,1,1,0,
0,0,0,0,
}; //масив содержащий фигуры

__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
//подготовка игры
Score=0;
randomize(); //инициализация генератора случайных чисел
//Размеры поля
PoleW=300;PoleH=540;
//обнулили поле
for(int j = 0; j< 18; j++)
for(int i = 0; i < 10; i++)
Pole[i][j]=0;
//Какой блок выпадет? Случайный
NextBlock = random(7);
speed = 500; //начальная скорость
rtime = time(NULL); //время начала игры
}

//Обнуляем поле по нажатию на кнопку
void __fastcall TForm1::SpeedButton1Click(TObject *Sender)
{
//обрабатывание клика SpeedButton1 (Начать)
Score = 0; //счёт
randomize();
PoleW = 300;
PoleH = 540;
for(int j = 0; j < 18;j++)
for(int i = 0; i < 10;i++)
Pole[i][j] = 0;
//
NextBlock = random(7);
CreateFigura(); //создаём фигуру
Timer1 -> Interval = 500; //инициируем таймер
Timer1 -> Enabled = true;
speed = 500;
rtime = time(NULL);
}

//Главный цикл игры
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
//установка Таймера
//Очищаем экран
ClrScr();
//рисуем картинки на поле
DrawPole();
//Рисуем падающую фигуру
DrawFigura(BlockPos.x, BlockPos.y, BlockType);
//Флип с бэк буффера во фронт
CopyToScreen();
int Tx = BlockPos.x, Ty = BlockPos.y;
Ty++;
//Если падающая фигура коснулась остальных блоков, то...
if(HitTest(Tx,Ty,BlockType))
{
//Выполняем слияние фигуры со все остальным "мусором"
AddFiguraToPole(BlockPos.x,BlockPos.y,BlockType);
//Создаем новую фигуру, если еще есть место
if(!CreateFigura())
{
Timer1 -> Enabled = false;
ShowMessage("Игра окончена");
}
}
else
{
BlockPos = Point(Tx,Ty);
}
//Смотрим, можно ли нам удалять линии с мусора
TestCompliteLine();
}
//---------------------------------------------------------------------------

void __fastcall TForm1::FormCreate(TObject *Sender)
{
//создание формы
//и инициализация базовых значений
Buffer = new Graphics::TBitmap(); //создаём битмап для фигуры
Buffer -> Width = PoleW;
Buffer -> Height = PoleH;
Block = new Graphics::TBitmap(); //создаём битмап для одного блока
Block -> Width = 30;
Block -> Height = 30;
Block -> LoadFromResourceID((int)HInstance, 101); //грузим картинку блока из ресурсов
CreateFigura(); //создаём фигуру
Timer1 -> Enabled=true; //запускаем таймер
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key,
TShiftState Shift)
{
//обработка нажатия клавиш
if(Key == VK_DOWN) //нажата стрелка вниз
Timer1 -> Interval = 50; //ускоряем падение
if(Key == VK_UP) //стрелка вверх
//Выполняем поворот фигуры
TurnFiguraNaPole(BlockPos.x, BlockPos.y, BlockType);
if((Key == VK_RIGHT) || Key == VK_LEFT) //стрелки влево и вправо
//Выполням сдвиг фигуры в стороны
MoveFigura(Key);
//Рисуем...
ClrScr(); //очищаем рисунок
DrawPole(); //перерисовываем поле
DrawFigura(BlockPos.x,BlockPos.y,BlockType); //перерисовываем фигуру в буфере
CopyToScreen(); //отрисовываем буфер на экран
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormKeyUp(TObject *Sender, WORD &Key,
TShiftState Shift)
{
//обработка отпускания клавиш
if(Key == VK_DOWN) //отпущена стрелка вниз
Timer1 -> Interval = speed;
}
//---------------------------------------------------------------------------
void TForm1::CopyToScreen()
{
//Флип
Canvas -> Draw(0, 0, Buffer); //рисуем буфер на экран
}

void __fastcall TForm1::DrawFigura(int x,int y,int tip)
{
//В цикле рисуем матрицу фигуры на экран с учетом базового смещения
for(int j = 0; j < 4; j++)
for(int i = 0; i< 4 ; i++)
{
if(FiguraData[tip][j*4+i] != 0)
Buffer -> Canvas -> Draw(x*30 + i*30, y*30 + j*30, Block);
}
}

//Поворот фигуры
void __fastcall TForm1::RotateFigura(int Tip)
{
//поворот фигуры (по сути - поворот матрицы через временный массив)
int PosX = 3;
int PosY = 0;
int Temp[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
for(int j = 0; j < 4; j++, PosX--, PosY = 0)
for(int i = 0; i < 4; i++, PosY++)
{
Temp[PosY*4 + PosX] = FiguraData[Tip][j*4+i];
}
for(int i = 0; i < 16; i++)
FiguraData[Tip][i] = Temp[i];

}

void __fastcall TForm1::ClrScr()
{
//отчистка поля
Buffer -> Canvas -> FillRect(Rect(0, 0, PoleW, PoleH));
}

//Проверяем, касается ли падающая фигура "мусора", если да - true иначе false
int __fastcall TForm1::HitTest(int X, int Y, int Tip)
{
for(int j=0;j<4;j++)
for(int i=0;i<4;i++)
{
if((FiguraData[Tip][j*4+i]!=0)&&(Pole[X+i][Y+j]!=0))
return 1;

if(FiguraData[Tip][j*4+i]!=0)
if((Y+j)>=18)
return 2;
}
return 0;
}

//Рисуем "мусор" на экране
void __fastcall TForm1::DrawPole()
{
//отрисовка поля
for(int j = 0; j < 18; j++)
for(int i = 0; i < 10; i++)
if(Pole[i][j] != 0)
Buffer -> Canvas -> Draw(30*i, 30*j, Block);

Canvas -> FillRect(Rect(320, 20, 320 + (4*30), 20 + (4*30)));
for(int j=0;j<4;j++)
for(int i=0;i<4;i++)
{
if(FiguraData[NextBlock][j*4+i] != 0)
Canvas -> Draw(320 + i*30, 20 + j*30, Block);
}
}

//Выполняем слияние фигуры с "мусором"
void __fastcall TForm1::AddFiguraToPole(int X, int Y, int Tip)
{
//добавление новой фигуры
for(int j = 0; j < 4;j++)
for(int i = 0; i < 4; i++)
if(FiguraData[Tip][j*4 + i] != 0)
Pole[X + i][Y + j] = FiguraData[Tip][j*4 + i];
}

//Пытаемся оздать новую фигуру
bool __fastcall TForm1::CreateFigura()
{

BlockPos = Point(3,0);
BlockType = NextBlock;
NextBlock = random(7);
int curs = time(NULL);
if (speed>50 && curs-rtime>=30) {
speed-=50;
Timer1->Interval = speed;
rtime = curs;
}
if(HitTest(BlockPos.x, BlockPos.y, BlockType) == 1)
return false;
else
return true;
}
//Пытаемся повернуть фигуру. Если нельзя, то мы её доворачивае до исходного состояния
int TForm1::TurnFiguraNaPole(int X, int Y, int Tip)
{
//повернуть фигуру на поле
RotateFigura(Tip);

int LeftLimit=0,RightLimit=0;
int err=0;
for(int i = 0; i < 4 ; i++, err = 0)
{
for(int j = 0; j < 4; j++)
{
if(FiguraData[BlockType][j*4+i] != 0)
err = 1;
}
if(err != 1)
LeftLimit++;
else
break;
}
err=0;
for(int i =3;i>=0;i--,err=0)
{
for(int j=0;j<4;j++)
{
if(FiguraData[BlockType][j*4+i] != 0)
err=1;
}
if(err != 1)
RightLimit++;
else
break;
}
if(!HitTest(X,Y,Tip))
{
if((BlockPos.x - RightLimit + 4) > 9)
BlockPos.x -= (BlockPos.x-RightLimit+4) - 10;
if((BlockPos.x + LeftLimit) < 0)
BlockPos.x += 0 - (BlockPos.x + LeftLimit);
}
if(HitTest(X, Y, Tip))
{
//Доворачиваем
RotateFigura(Tip);
RotateFigura(Tip);
RotateFigura(Tip);
}
return 0;
}

//Тут мы просто смещаем фигуру.
void __fastcall TForm1::MoveFigura(int Key)
{
//двигаем фигуру
int LeftLimit=0,RightLimit=0;
int err=0;
for(int i=0;i<4;i++,err=0)
{
for(int j=0;j<4;j++)
{
if(FiguraData[BlockType][j*4+i] != 0)
err = 1;
}
if(err != 1)
LeftLimit++;
else
break;
}
err=0;
for(int i = 3; i >= 0; i--, err = 0)
{
for(int j=0;j<4;j++)
{
if(FiguraData[BlockType][j*4+i] != 0)
err=1;
}
if(err != 1)
RightLimit++;
else
break;
}
if(Key == VK_LEFT)
{
int x = BlockPos.x;
x--;
if(x + LeftLimit >= 0)
if(!HitTest(x, BlockPos.y, BlockType))
BlockPos.x = x;
}
if(Key == VK_RIGHT)
{
int x = BlockPos.x;
x++;
if(x - RightLimit < 7)
if(!HitTest(x, BlockPos.y, BlockType))
BlockPos.x = x;
}
}
//Просто проверяем линии массива "мусора" на заполненность, если заполнена, то коллапсим её.
int TForm1::TestCompliteLine()
{
//проверка на заполненные линии
TList *ComplitedLine = new TList();
bool err = false;
for(int j =17; j >= 0; j--, err = false)
{
for(int i = 0; i < 10; i++)
if(Pole[i][j] == 0)
err = true;
if(err == false)
ComplitedLine -> Add( (void*)j);
}
for(int i = 0; i < ComplitedLine -> Count; i++)
{
//Коллапсим
CollapseDown((int)ComplitedLine -> Items[i]);
}
Score += ComplitedLine -> Count * ComplitedLine -> Count;
Label1->Caption = "Очки:" + IntToStr(Score);
delete ComplitedLine;
return 0;
}
//Функция коллапсинья
void __fastcall TForm1::CollapseDown(int row)
{
for(int i = 0; i < 10; i++)
Pole[i][row] = 0;
for(int i = 0; i < 10; i++)
for(int j = row - 1; j >= 0; j--)
if(j > 0)
Pole[i][j+1] = Pole[i][j];
else
Pole[i][j+1] = 0;
}
//Выходим из проги
void __fastcall TForm1::SpeedButton2Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------






Прикрепленные файлы:
Форма ответа