15 мая 2023 года "Исходники.РУ" отмечают своё 23-летие!
Поздравляем всех причастных и неравнодушных с этим событием!
И огромное спасибо всем, кто был и остаётся с нами все эти годы!

Главная Форум Журнал Wiki DRKB Discuz!ML Помощь проекту

"Tetris" - игра Тетрис для Win95/NT реализованная с использованием только функций WINAPI с открытым исходным кодом.

 

Соглашение

Это программное обеспечение не является коммерческим ни в какой из своих частей и предлагается Вам "как есть", без всяких гарантий, прямых или косвенных, без всяких ограничений на любые гарантии работоспособности или пригодности для Ваших конкретных применений. Ни в коем случае автор не несет ответственности перед Вами или кем-нибудь еще за любой прямой, случайный, косвенный ущерб или его последствия любого типа, включая любые, без исключений, потери или претензии третьих лиц.

Вы можете по своему усмотрению использовать или модифицировать данное программное обеспечение и его исходный код в любых целях.

 

Управление

Стрелка вправо - сдвиг фигуры вправо

Стрелка влево - сдвиг фигуры влево

Стрелка вверх - вращение фигуры

Стрелка вниз - опустить фигуру

Esc - выход из программы

 

Версии:

1.1a - первая рабочая версия программы

- опубликован исходный код

1.2b -добавлена таблица рекордов

-исправлены некоторые глюки

-размер программы уменьшился с 25kb до 12kb

1.3b - исправлен глюк с run-time ошибкой при отсутствии файла tetris.dat

    • в исходный код включен make-файл для компилятора LCC
    • добавлена инструкция по компиляции файла в среде LCC
  Листинг 1
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#include <string.h>
#include <shellapi.h>
#include <stdio.h>

#include "c:\lcc\project\tetris\tetrisres.h"
//---------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;
static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
void initscreen();
void newfigure();
void gameover();
void bind(int x,int y,int keys);
void delfull();
void unrotate();
void rotate();
void show();
//---------------------------------------------------------------------------------------
static char  szAppName[] = "Tetris" ;
HWND         hwnd ,hwndDlg=NULL;
MSG          msg ;
WNDCLASSEX   wndclass ;
HINSTANCE hinst;
static int screen[16][18];
static int oldscreen[16][18];
static int cup[16][18];
static int figure[4][4];
static int oldfigure[4][4];
static int deltax=3 , deltay=0;
static int speed,oldspeed;
static int idTimer = -1;
static int scores;
static char title[25];
static int cxClient, cyClient ;
BOOL endgame=FALSE;

//---------------------------------------------------------------------------------------

int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
	PSTR szCmdLine, int iCmdShow)
{

	wndclass.cbSize        = sizeof (wndclass) ;
	wndclass.style         = CS_HREDRAW | CS_VREDRAW;
	wndclass.lpfnWndProc   = WndProc ;
	wndclass.cbClsExtra    = 0 ;
	wndclass.cbWndExtra    = DLGWINDOWEXTRA ;
	wndclass.hInstance     = hInstance ;
	wndclass.hIcon         = LoadIcon (hInstance, "Tetris") ;
	wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW) ;
	wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
	wndclass.lpszMenuName  = NULL ;
	wndclass.lpszClassName = szAppName ;
	wndclass.hIconSm       = LoadIcon (hInstance, "Tetris") ;

	RegisterClassEx (&wndclass) ;

	hwnd = CreateDialog (hInstance, "Tetris", 0, NULL) ;

	ShowWindow (hwnd, iCmdShow) ;

	while (GetMessage (&msg, NULL, 0, 0))
	{
		TranslateMessage (&msg) ;
		DispatchMessage (&msg) ;
	}
	return msg.wParam ;
}


//----------------------------------------------------------------------------------------------


LRESULT CALLBACK WndProc (HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam)
{
	int countx,county;
	HDC    hdc ;
	PAINTSTRUCT  ps ;
	COLORREF colorbrick;
	HBRUSH hBrush ;
	RECT   rect ;

	switch (iMsg)
	{

	case WM_COMMAND :
		switch (LOWORD(wParam))
		{
		case ID_EXIT:
			SendMessage(hwnd,WM_CLOSE,0,0L);
			break;
		case ID_NEW:
			scores=0;
			speed=300;
			endgame=FALSE;
			oldspeed=speed;
			SetTimer(hwnd, idTimer = 1, speed, NULL);
			SetWindowText(hwnd,"Tetris");
			initscreen();
			newfigure();
			bind(deltax,deltay,0);
			break;

		case ID_HI:
			KillTimer(hwnd, 1);
			DialogBox(hinst, MAKEINTRESOURCE(IDD_SCOREDIALOG), hwnd, (DLGPROC) DialogFunc);
			SetTimer(hwnd, idTimer = 1, speed, NULL);
			break;

		case ID_ABOUT:
			KillTimer(hwnd, 1);
			ShellAbout(hwnd,"Tetris(ver. 1.3b)","WebSite: htpp:\\\\freecpp.newmail.ru",NULL);
			SetTimer(hwnd, idTimer = 1, speed, NULL);
			break;
		}
		return 0;

	case WM_SIZE:
		cxClient=LOWORD (lParam)/10;
		cyClient=HIWORD (lParam)/16;
		return 0;

	case WM_PAINT:

		hdc = BeginPaint (hwnd, &ps) ;

		for (countx=0;countx<10;countx++)
		{
			for (county=0;county<16;county++)
			{
				if(screen[countx][county]!=0)
				{
					switch(screen[countx][county])
					{
					case 0:
						colorbrick=RGB(0,0,0);
						break;
					case 1:
						colorbrick=RGB(255,0,0);
						break;
					case 2:
						colorbrick=RGB(0,255,0);
						break;
					case 3:
						colorbrick=RGB(0,0,255);
						break;
					case 4:
						colorbrick=RGB(0,255,255);
						break;
					case 5:
						colorbrick=RGB(255,0,255);
						break;
					case 6:
						colorbrick=RGB(255,255,0);
						break;
						break;
					}
					SetRect (&rect, countx*cxClient,county*cyClient,
						countx*cxClient+cxClient,county*cyClient+cyClient) ;
					hBrush = CreateSolidBrush (colorbrick);

					hBrush = CreateSolidBrush (colorbrick);
					FillRect (hdc, &rect, hBrush) ;
					DeleteObject (hBrush) ;
				}
			}
		}
		EndPaint (hwnd, &ps) ;
		return 0 ;

	case WM_KEYDOWN:
		switch (LOWORD(wParam))
		{
		case VK_ESCAPE:
			SendMessage(hwnd,WM_CLOSE,0,0L);
			break;

		case VK_LEFT:
			deltax=deltax-1;
			bind(deltax,deltay,4);
			break;

		case VK_RIGHT:
			deltax=deltax+1;
			bind(deltax,deltay,6);
			break;

		case VK_UP:
			rotate();
			bind(deltax,deltay,5);
			break;

		case VK_DOWN:
			oldspeed=speed;
			speed=100;
			SetTimer(hwnd, idTimer = 1, speed, NULL);
			break;
		}
		return 0;

	case WM_TIMER:
		deltay=deltay+1;
		bind(deltax,deltay,2);
		return 0;

	case WM_DESTROY :
		KillTimer(hwnd, 1);
		PostQuitMessage (0) ;
		return 0 ;
	}
	return DefWindowProc (hwnd, iMsg, wParam, lParam) ;
}


//--------------------------------------------------------------------------------------

void initscreen()
{
	int countx,county;
	for (countx=0;countx<10;countx++)
	{
		for (county=0;county<16;county++)
		{
			cup[countx][county]=0;
		}
	}
}

//---------------------------------------------------------------------------------------

void newfigure()
{
	int i,numfigure;
	if(endgame)return;
	speed=oldspeed;
	SetTimer(hwnd, idTimer = 1, speed, NULL);
	for(i = 2;i<9;i++)
	{
		if(cup[i][3]>0) gameover();
	}

	deltax = 3;
	deltay = 0;
	srand(rand()%100);
	numfigure = rand ()%6+1;

	switch (numfigure)
	{

	case 1:
		figure[0][0] = 0;
		figure[1][0] = 0;
		figure[2][0] = 0;
		figure[3][0] = 0;
		figure[0][1] = 0;
		figure[1][1] = numfigure;
		figure[2][1] = numfigure;
		figure[3][1] = 0;
		figure[0][2] = 0;
		figure[1][2] = 0;
		figure[2][2] = numfigure;
		figure[3][2] = 0;
		figure[0][3] = 0;
		figure[1][3] = 0;
		figure[2][3] = numfigure;
		figure[3][3] = 0;
		break;

	case 2:
		figure[0][0] = 0;
		figure[1][0] = 0;
		figure[2][0] = 0;
		figure[3][0] = 0;
		figure[0][1] = 0;
		figure[1][1] = numfigure;
		figure[2][1] = numfigure;
		figure[3][1] = 0;
		figure[0][2] = 0;
		figure[1][2] = numfigure;
		figure[2][2] = 0;
		figure[3][2] = 0;
		figure[0][3] = 0;
		figure[1][3] = numfigure;
		figure[2][3] = 0;
		figure[3][3] = 0;
		break;

	case 3:
		figure[0][0] = 0;
		figure[1][0] = numfigure;
		figure[2][0] = 0;
		figure[3][0] = 0;
		figure[0][1] = 0;
		figure[1][1] = numfigure;
		figure[2][1] = numfigure;
		figure[3][1] = 0;
		figure[0][2] = 0;
		figure[1][2] = 0;
		figure[2][2] = numfigure;
		figure[3][2] = 0;
		figure[0][3] = 0;
		figure[1][3] = 0;
		figure[2][3] = 0;
		figure[3][3] = 0;
		break;

	case 4:
		figure[0][0] = 0;
		figure[1][0] = 0;
		figure[2][0] = numfigure;
		figure[3][0] = 0;
		figure[0][1] = 0;
		figure[1][1] = numfigure;
		figure[2][1] = numfigure;
		figure[3][1] = 0;
		figure[0][2] = 0;
		figure[1][2] = numfigure;
		figure[2][2] = 0;
		figure[3][2] = 0;
		figure[0][3] = 0;
		figure[1][3] = 0;
		figure[2][3] = 0;
		figure[3][3] = 0;
		break;

	case 5:
		figure[0][0] = 0;
		figure[1][0] = 0;
		figure[2][0] = 0;
		figure[3][0] = 0;
		figure[0][1] = 0;
		figure[1][1] = numfigure;
		figure[2][1] = numfigure;
		figure[3][1] = 0;
		figure[0][2] = 0;
		figure[1][2] = numfigure;
		figure[2][2] = numfigure;
		figure[3][2] = 0;
		figure[0][3] = 0;
		figure[1][3] = 0;
		figure[2][3] = 0;
		figure[3][3] = 0;
		break;

	case 6:
		figure[0][0] = 0;
		figure[1][0] = numfigure;
		figure[2][0] = 0;
		figure[3][0] = 0;
		figure[0][1] = 0;
		figure[1][1] = numfigure;
		figure[2][1] = 0;
		figure[3][1] = 0;
		figure[0][2] = 0;
		figure[1][2] = numfigure;
		figure[2][2] = 0;
		figure[3][2] = 0;
		figure[0][3] = 0;
		figure[1][3] = numfigure;
		figure[2][3] = 0;
		figure[3][3] = 0;
		break;
	}
	scores=scores+numfigure;
	wsprintf (title, "%s - %i", szAppName,scores) ;

	SetWindowText(hwnd,title);
}

//---------------------------------------------------------------------------------------

void gameover()
{
	char result[30]="You score: ";
	KillTimer(hwnd, 1);
	endgame=TRUE;
	DialogBox(hinst, MAKEINTRESOURCE(IDD_SCOREDIALOG), hwnd, (DLGPROC) DialogFunc);

}

//---------------------------------------------------------------------------------------

void bind(int x,int y,int keys)
{
	int i,j,i1,j1;

	for(j=0;j<16;j++)
	{
		for(i=0;i<10;i++)
		{
			oldscreen[i][j]= screen[i][j];
		}
	}

	for(j=0;j<16;j++)
	{
		for(i=0;i<10;i++)
		{
			screen[i][j]= cup[i][j];
		}
	}

	for(j=0;j<4;j++)
	{
		for(i=0;i<4;i++)
		{
			if((figure[i][j]>0)&&((screen[i+x][j+y]>0)||(i+x+1==0)||(j+y==16)||(i+x==10)))
			{
				switch(keys)
				{
				case 4:
					deltax = deltax + 1;
					break;

				case 6:
					deltax = deltax - 1;
					break;

				case 2:
					for(j1 = 0;j1<4;j1++)
					{
						for (i1 = 0;i1<4;i1++)
						{
							if(figure[i1][j1] > 0)
							{
								cup[i1 + x][j1 + y - 1] = figure[i1][j1];
							}
						}
					}
					for (j1=0;j1<16;j1++)
					{
						for(i1=0;i1<10;i1++)
						{
							screen[i1][j1] = cup[i1][j1];
						}
					}
					delfull();
					newfigure();
					break;

				case  5:
					unrotate();
				}
				x = deltax;
				y = deltay;
			}
		}
	}
	for(j=0;j<4;j++)
	{
		for(i = 0;i<4;i++)
		{
			if(figure[i][j]>0)
			{
				screen[i + x][j + y] = figure[i][j];
			}
			else
			    {
				screen[i + x][j + y] = cup[i + x][j + y];
			}
		}
	}
	show();
}

//---------------------------------------------------------------------------------------

void delfull()
{
	int i,j,row,col;
	BOOL flag;
	for(j=0;j<16;j++)
	{
		flag = TRUE;
		for(i=0;i<10;i++)
		{
			if(cup[i][j]==0) flag=FALSE;

		}
		if(flag)
		{
			scores=scores+25;
			wsprintf (title, "%s - %i", szAppName,scores) ;
			SetWindowText(hwnd,title);
			speed=speed-2;
			SetTimer(hwnd, idTimer = 1, speed, NULL);
			for(row=j;row>1;row--)
			{
				for(col=0;col<10;col++)
				{
					cup[col][row] = cup[col][row - 1];
				}
			}
		}
		flag = TRUE;
	}
}

//---------------------------------------------------------------------------------------

void unrotate()
{
	int i,j;
	for(j=0;j<4;j++)
	{
		for(i=0;i<4;i++)
		{
			figure[i][j] = oldfigure[i][j];
		}
	}
}

//---------------------------------------------------------------------------------------

void rotate()
{
	int i,j;
	for(j = 0;j<4;j++)
	{
		for(i=0;i<4;i++)
		{
			oldfigure[i][j]=figure[i][j];
		}
	}
	for(j = 0;j<4;j++)
	{
		for(i=0;i<4;i++)
		{
			figure[i][j]=oldfigure[3-j][i];
		}
	}
}

//---------------------------------------------------------------------------------------

void show()
{
	HDC hdc;
	int countx,county;
	COLORREF colorbrick;
	HBRUSH hBrush ;
	RECT   rect ;
	hdc = GetDC (hwnd) ;


	for (countx=0;countx<10;countx++)
	{
		for (county=0;county<16;county++)
		{
			if(screen[countx][county]!=oldscreen[countx][county])
			{
				switch(screen[countx][county])
				{
				case 0:
					colorbrick=RGB(0,0,0);
					break;
				case 1:
					colorbrick=RGB(255,0,0);
					break;
				case 2:
					colorbrick=RGB(0,255,0);
					break;
				case 3:
					colorbrick=RGB(0,0,255);
					break;
				case 4:
					colorbrick=RGB(0,255,255);
					break;
				case 5:
					colorbrick=RGB(255,0,255);
					break;
				case 6:
					colorbrick=RGB(255,255,0);
					break;
					break;
				}
				SetRect (&rect, countx*cxClient,county*cyClient,
					countx*cxClient+cxClient,county*cyClient+cyClient) ;
				hBrush = CreateSolidBrush (colorbrick);
				FillRect (hdc, &rect, hBrush) ;
				DeleteObject (hBrush) ;
			}
		}
	}
	ReleaseDC (hwnd, hdc) ;
}

static BOOL CALLBACK DialogFunc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam)
{
	FILE *f;
	char name[5][25];
	char score[5][10];
	int maxscore[5];
	int i;
	switch (msg) {
		case WM_INITDIALOG:
		f=fopen("tetris.dat","rb");
		if(f==NULL)	break;
		for(i=0;i<5;i++)
			{
			fread(name[i],1,25,f);
			fread(score[i],1,10,f);
			maxscore[i]=atoi(score[i]);
			}
		fclose(f);
	for(i=0;i<5;i++)
		{
			if(scores>maxscore[i]&&endgame)
				{
					itoa(scores,score[i],10);
					SendDlgItemMessage(hwndDlg,102+i,EM_SETREADONLY,(WPARAM)FALSE,(LPARAM)0);
					i=5;
					scores=0;
				}
		}
	for(i=0;i<5;i++)
		{
		SendDlgItemMessage(hwndDlg,102+i,WM_SETTEXT,(WPARAM)0,(LPARAM)name[i]);
		SendDlgItemMessage(hwndDlg,107+i,WM_SETTEXT,(WPARAM)0,(LPARAM)score[i]);
		}
		return TRUE;
	case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			for(i=0;i<5;i++)
			{
				SendDlgItemMessage(hwndDlg,102+i,WM_GETTEXT,(WPARAM)25,(LPARAM)name[i]);
				SendDlgItemMessage(hwndDlg,107+i,WM_GETTEXT,(WPARAM)10,(LPARAM)score[i]);
			}
		f=fopen("tetris.dat","wb");
		for(i=0;i<5;i++)
			{
			fwrite(name[i],1,25,f);
			fwrite(score[i],1,10,f);
			}
		fclose(f);
			EndDialog(hwndDlg,1);
			return 1;

		}
		break;
	case WM_CLOSE:
		EndDialog(hwndDlg,0);
		return TRUE;

	}
	return FALSE;

}