Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
6
Добавлен:
30.05.2020
Размер:
9.27 Кб
Скачать
#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;			//рейтинг

//Тут мы закодировали матрицами сами фигуры.  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< 1 8; j++)
        for(int i = 0; i < 10; i++)
			Pole[i][j]=0;
//Какой блок выпадет? Случайный
	NextBlock = random(7);
}

//Обнуляем поле по нажатию на кнопку
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;
}

//Главный цикл игры
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);
	CreateFig ura();
	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 = 500;
}
//---------------------------------------------------------------------------
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);
	if(HitTest(BlockPos.x, BlockPos.y, BlockType) == 1)
		return false;
	else
		return true;
}
//Пытаемся повернуть фигуру. Если нельзя, то мы её доворачивае до исходного состояния
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;
	}
}
//Просто проверяем линии массива "мусора" на заполненность, если заполнена, то коллапсим её.
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();
}
//---------------------------------------------------------------------------
Соседние файлы в папке tetris