基於DOS的簡易俄羅斯方塊製作

製作一個簡易的俄羅斯方塊,未調用graphics庫(裝了半天不成功),完全的黑框操作
基本思路:
1.利二維數組表示地圖(也可以利用一維數組,此處利用的是一維數組) 0.表示沒有方格,1.表示正在下落的方格 2.表示牆壁
2.共有七種俄羅斯方塊,但是有19種狀態 (繪製方塊處,總共有7種俄羅斯方塊,旋轉之後可以形成19種方塊)
3.每個方塊需設置一箇中心方塊 ,儘量與其他的方塊有聯繫。中心方塊用B[0]表示,其他的方塊由1,2,3表示

必要的幾個實用的函數
1.定位光標函數

 #include <stdio.h>
#include <windows.h> 
#include <conio.h>
#include <time.h>
using namespace std;
//設置文字的顯示位置  方法一:空格  \t   \n
//可以利用座標  x axis y axis
//控制文字顯示位置
void gotoxy(int x,int y)
{
	COORD pos;//COORD結構體 
	pos.X=x;
	pos.Y=y;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),pos);	
 } 
int main()
{
	gotoxy(30,10);//橫座標30,縱座標10 
	printf("this is a test");
	return 0; 
} 

2.顏色調用函數

 #include <stdio.h>
#include<windows.h> 
#include <conio.h>
#include<time.h>
using namespace std;

//HANDLE hOut;//控制檯的句柄 
//color
int color(int c)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
	//只能用在windows系統,且不能改變控制檯的顏色 
	return 0;
}
int main()
{
	color(14);//0-15號色 ,超過15之後就是改變文本的背景色 
 //	14號黃色 13號粉色  10號綠色 15白色 6棕色 12紅色 11 亮藍色 2綠色 
	printf("this is a test\n"); //改變了一次之後下面所有的文字都是此種顏色
	                    //要每種顏色則只需要在每個字體前加上相應的顏色代碼即可 
	
return 0;	
}

3._getch()函數 用於讀入按鍵進行操作
4.函數名:kbhit()
//功能及返回值: 檢查當前是否有鍵盤輸入,若有則返回一個非0值,否則返回0。

完整的程序:

#include <stdio.h>
#include<windows.h> 
#include <conio.h>
#include<time.h>
using namespace std;
int map[250];//地圖數組
int nextblock[2];//下一個方塊
int endgame;//遊戲結束標誌 1爲遊戲進行中,0爲遊戲失敗
int xblock[2];//記錄行進中方塊形狀和位置,xblock[0]記錄形狀,0爲I型,1爲其他型,2爲O型   xblock[1]爲位置 
int score;//計分
int speed=20000;//當前速度 
//7種俄羅斯方塊 
int blockI[4] = { 1,1,1,1};//I型方塊           xblock[0]   =   0
int blockO[9] = { 0,0,0,0,1,1,0,1,1 };//O型方塊                2
int blockT[9] = { 0,0,0,1,1,1,0,1,0 };//T型方塊                1
int blockL[9] = { 0,1,0,0,1,0,0,1,1 };//L型方塊                1
int blockS[9] = { 0,0,0,0,1,1,1,1,0};//S型方塊                 1
int blockZ[9] = { 0,0,0,1,1,0,0,1,1};//Z型方塊                 1
int blockJ[9] = { 0,1,0,0,1,0,1,1,0 };//J型方塊                1

int color(int c);//顏色
void init();//初始化數據
void gotoxy(int x, int y);//將光標移動到指定位置
void drawborder();//繪製邊框
void drawmap();//繪製地圖
int  ranblock();//方塊生成
void drawblock(int block[9]);//繪製方塊
void drawnextblock(int x);//繪製下一個方塊
void drawmapblock(int block[9]);//向地圖上繪製方塊
void downblock();//方塊下落
void run();//核心邏輯
void heart();//畫心形
void welcom();//歡迎界面 
void title();//
void regulation();
void me();
void regulation()
{
	color(13);
	printf("1,上鍵旋轉方塊\n");
	printf("2,0分:廢鐵 \n100分:青銅 \n500分:白銀 \n1000分:黃金 \n依次500分遞增,最高王者\n");
	printf("3,空格鍵暫停,回車鍵繼續遊戲");

}
void me()
{
    
    color(13);
printf("\t*****************************************************");    
printf("\t\t\t\t\t \t                                        .----.      \n");
printf("  \t\t                                            _.'__    `.    \n  ");
printf("  \t\t                                        .--(#)(##)---/#\\    \n");
printf("  \t\t                                      .' @          /###\\    \n");
printf("\t\t1 ------------------略略略略略略      :        ,  #####      \n");
printf("\t\t* ------------------★★★★★★        `-..__.-' _.-\\###/    \n"); 
printf("\t\t2 ------------------略略略略略略            `;_:    `\"\'    \n ");
printf("\t\t* ------------------★★★★★★          .\'\"\"\"\"\"`.    \n");
printf("\t\t3 ------------------略略略略略略          /,  Main ,\\      \n");
printf("\t\t* ------------------★★★★★★          //  Menu  \\\\    \n");
printf("\t\t4 ------------------略略略略略略        `-._______.-\'    \n");
printf("\t\t* ------------------★★★★★★        _ __`. | .'___    \n");
printf("\t\t0 ------------------略略略略略略        (______|______)    \n");   
 } 

void heart()
{
	
	
	//打印心形 
	color(13);
		int i = 0, j = 0;
	int a = 3;
	char c = 3;//心形的ASCII代碼是3
	for (i = 0; i < 3;i++)//行數  3行
	{
		gotoxy(10,9+i); 
		for (j = 0; j < 5- 2*i;j++)//空格, 5,3,1個空格
		{
			printf(" ");
		}
		
		for (j = 0; j < 5+ 4 * i;j++)//打印符號
		{
			printf("%c", c);
		}
		
		for (j = 0; j < 9- 4 * i;j++)//打印空格
		{
			printf(" ");
		}
		
		for (j = 0; j < 5+ 4 * i;j++)//打印符號
		{
			printf("%c", c);
		}
 
		printf("\n");
 
    }
	for (i = 0; i < 3; i++)//打印行數3行
	{  gotoxy(10,12+i);
		for (j = 0; j < 29;j++)//打印符號
			printf("%c", c);
		printf("\n");//打印空格
	}
	color(12);
	for (i = 0; i < 6+ 1; i++)//    打印6行
	{
	 	gotoxy(10,15+i);
		for (j = 0; j < 2 * i + 1; j++)//打印空格
			printf(" ");
		for (j = 0; j < 27-4 * i; j++)
			printf("%c", c);
		printf("\n");
	}
	for (i = 0; i <1; i++)//打印行數1行
	{
		gotoxy(10,22);
		for (j = 0; j < 14; j++)//打印空格
			printf(" ");
		for (j = 0; j < 1; j++)//打印符號
			printf("%c", c);
		printf("\n");
	}
	color(14);
	gotoxy(24,14);
	printf("L");

}
void welcom()
{
	heart(); 
	int n;
	color(6);
	gotoxy(-20,12);
	printf("1.Play game");
	gotoxy(-8,12);
	printf("2.The regulations");
	gotoxy(-20,17);
	printf("3.Exit");
	gotoxy(-8,17);
	printf("4.About me");
	gotoxy(13,25);
	color(4);
	printf("Please enter {1,2,3,4}:[ ]\b\b");//\b退格符
	scanf("%d",&n); 
	switch(n)
	{
		case 1:
			system("cls");//清屏 
			init();
	        run();
		    break;
		case 2:
			system("cls");//清屏 
			regulation();
			getchar();
			getchar();
			system("cls");//清屏 
			title();
			welcom();
			break;
		case 3:
			exit(0);
			break;
		case 4:
			system("cls");//清屏 
			me();
			getchar();
			getchar();
			system("cls");//清屏 
			title();
			welcom();
			break;
	}
	
}
void title()
{
	color(14);
	gotoxy(12,3);	
	printf("JELLY 的 俄 羅 斯 方 塊");// 若是顯示不成功,則看編譯的位數,
	                                  //若電腦是32位,則上面編譯要用32位編譯
	color(11);
	gotoxy(6,5);
	printf("■"); //漢字在x橫軸上佔用兩個位置 ,y軸上佔用一個位置
	gotoxy(6,6);
	printf("■■");
	gotoxy(6,7);
	printf("■"); 
	
	color(14);
	gotoxy(14,6);
	printf("■■"); //漢字在x橫軸上佔用兩個位置 ,y軸上佔用一個位置
	gotoxy(14,7);
	printf("■■"); 
	
	color(10);
	gotoxy(24,6);
	printf("■■");
	gotoxy(24,7);
	printf("■■");

	color(13);
	gotoxy(33,5);
	printf("■"); 
	gotoxy(33,6);
	printf("■"); 
	gotoxy(33,7);
	printf("■"); 
	gotoxy(33,8);
	printf("■"); 
	color(12);
	gotoxy(45,6);
	printf("■");
	gotoxy(41,7);
	printf("■■■");
	printf("\n\n"); 

}

 int color(int c)
{
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c);
	//只能用在windows系統,且不能改變控制檯的顏色 
	return 0;
}
//將光標移動到指定位置
void gotoxy(int x,int y)
{
	COORD c;
	c.X = x+23 ;
	c.Y = y+2;
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	SetConsoleCursorPosition(handle, c);
	CONSOLE_CURSOR_INFO CursorInfo;
	//獲取控制檯光標信息
	GetConsoleCursorInfo(handle, &CursorInfo);
	//隱藏控制檯光標,設置控制檯光標狀態
	CursorInfo.bVisible = false;
	SetConsoleCursorInfo(handle, &CursorInfo);
}

//初始化數據
void init()
{
	//map數組初始化賦值,0-239賦值爲0,240-249賦值爲2
	for (int i = 0; i < 240; i++)	
		map[i] = 0;
	for (int i = 240; i < 250; i++)
		map[i] = 2;
			
	endgame = 1;
	nextblock[0] = 0;// 
	nextblock[1] = ranblock();///
	xblock[0] = 0;//故開始第一個必爲I型 
	xblock[1] = 24;// 
	score = 0;
	drawborder();

}
//繪製邊框
void drawborder()
{
	//繪製地圖邊框
	color(12);
	gotoxy(-2,-1);
	printf("┏");
	gotoxy(20,-1);
	printf("┓");
	gotoxy(-2,20);
	printf("┗");
	gotoxy(20,20);
	printf("┛");
	for (int i = 0; i < 20; i+=2)
	{
		gotoxy(i, -1);
		printf("━");
		gotoxy(i, 20);
		printf("━");
		
    } 
    for (int i = -1; i < 21; i++)
	{
		if (i < 19) {
			gotoxy(-2, i + 1);
			//全角豎線
			printf("┃");
			gotoxy(20, i + 1);
			printf("┃");
		}
	}
	//繪製預覽方塊邊框
	for (int i = 0; i < 10; i++)
	{
		gotoxy(i + 30, 2);
		printf("-");
		}
	for (int i = 0; i < 10; i++)
	{
		gotoxy(i + 30, 7);
		printf("-");
//		if (i < 4)
//		{
//			gotoxy(29,i+2);
//			printf("丨");
//			gotoxy(39, i + 2);
//			printf("丨");
//		}
	}
//	color(12);
//	gotoxy(25, 1);
//	printf("下一個方塊:");
//	gotoxy(25, 19);
//	printf("製作者:jelly");
//	gotoxy(25,15);
//	printf("當前等級:") ;

	
}
//隨機方塊生成
int ranblock() {
	int x;
	srand((int)time(0));
	x = rand() % 7;
	return x;
}
//繪製地圖
void drawmap()
{
	for(int i=1;i<=15;i++)
	{
	color(i);
	gotoxy(-10,1);
	printf("俄"); 
	gotoxy(-10,3);
	printf("羅"); 
	gotoxy(-10,5);
	printf("斯"); 
	gotoxy(-10,7);
	printf("方"); 
	gotoxy(-10,9);
	printf("塊"); 
    }
	color(12);
	gotoxy(25, 1);
	printf("下一個方塊:");
	gotoxy(25, 19);
	printf("製作者:jelly");
	gotoxy(25,15);
	printf("當前等級:") ;
//	gotoxy(25, 14);
//	printf("                   ");
	gotoxy(25, 14);
	printf("遊戲得分: %d",score);
	gotoxy(25,13);
	printf("當前速度: %d",(21000-speed)/1000);
	for (int i = 40; i < 240; i++)
	{
		gotoxy(i%10*2, i/10 - 4);
		//map數組中0爲空
		if (map[i] == 0)
			printf(" ");
		//1爲移動中方塊
		if (map[i]== 1)
			printf("■");
		//2爲停止的方塊
		if (map[i] == 2) 
			printf("■");
	}
	gotoxy(35,15);
	if(score==0) printf("廢鐵");
}

//繪製下一個方塊
void drawnextblock(int x) 
{//下一個方塊顯示 區域清空,中文圖形佔用兩個字節 
	for (int i = 0; i < 4; i++)
	{
		gotoxy(i * 2 + 31, 2);
		printf(" ");
		gotoxy(i * 2 + 31, 3);
		printf(" ");
		gotoxy(i * 2 + 31, 4);
		printf(" ");
		gotoxy(i * 2 + 31, 5);
		printf(" ");
	}
	switch (x)//隨機數x進行選擇 
	{
	case 0:
		color(8);
		gotoxy(31, 4);
		printf("■");
		gotoxy(33, 4);
		printf("■");
		gotoxy(35, 4);
		printf("■");
		gotoxy(37, 4);
		printf("■");
		break;
	case 1://在next框中繪製不同的除了I型之外的方塊
	    color(14);
		drawblock(blockT);
		break;
	case 2:
		color(11);
		drawblock(blockL);
		break;
	case 3:
		color(13);
		drawblock(blockO);
		break;
	case 4:
		color(2);
		drawblock(blockS);
		break;
	case 5:
		color(6);
		drawblock(blockZ);
		break;
	case 6:
		color(15);
		drawblock(blockJ);
		break;
	}
}
//繪製方塊(除了I型的其他方塊)
void drawblock(int block[9]) { 
	for (int i = 0; i < 3; i++)
	{
		gotoxy(i * 2 + 31, 3);
		if (block[i] == 0)		
			printf(" ");	
		else
			printf("■");
		gotoxy(i * 2 + 31, 4);
		if (block[i + 3] == 0)
			printf(" ");
		else
			printf("■");
		gotoxy(i * 2 + 31, 5);
		if (block[i + 6] == 0)
			printf(" ");
		else
			printf("■");
	}
}

//方塊下落
void downblock()
{
	//碰撞檢測標識//touch爲1則爲未碰撞 
	int touch = 1;
	for (int i = 239; i >= 0; i--)
	{
		if (map[i] == 1 && map[i + 10] == 2)
			touch = 0;
	}
	if (touch == 1)
	{
		for (int i = 239; i >= 0; i--)
		{
			if (map[i] == 1)//向下移動,每行10個元素 
			{
				map[i + 10] = map[i];
				map[i] = 0;
			}
		}
		xblock[1] = xblock[1] + 10;///////
	}
	else if (touch == 0)//在碰撞的基礎上將1改爲2,即也就是將方塊改爲固定不動的方塊 
	{
		for (int i = 0; i < 240; i++)
		{
			if (map[i] == 1)
				map[i] = 2;
		}
	}
}
//向地圖上繪製方塊
void drawmapblock(int block[9])
{
	for (int i = 0; i < 3; i++)
	{
		map[i + 13] = block[i];
		map[i + 23] = block[i + 3];
		map[i + 33] = block[i + 6];
	}
	//記錄方塊座標和類型
	xblock[0] = 1;//1爲除i和o型其他的形狀 
	xblock[1] = 24;//////
}
//核心邏輯
void run()
{
	while (endgame)
	{
		//遊戲結束
		for (int i=20; i < 30; i++)
		{
			if (map[i] == 2||map[i+10]==2)
			{
				gotoxy(8, 7);
				printf("  遊戲結束,按任意鍵退出  ");
				_getch();
				endgame = 0; 
			}
		}
		//方塊消除
		for (int i = 0; i < 24; i++)
		{
			int sign = 0;
			for (int j = 0; j < 10; j++)
			{
				if (map[i * 10 + j] == 2)
					sign++;
			}
			if (sign == 10)//記錄每行的2數即固定的不能動的方塊 
			{
				for (int j = 0; j < 10; j++)
				{
					map[i * 10 + j] = 0;
				}
				for (int z = i*10+9; z >=0; z--)//消除一行後其他的向下移動 
				{
					if (map[z] == 2)
					{
						map[z + 10] = 2;
						map[z] = 0;
					}
				}
				score=score+100;
				//
			gotoxy(35,15);
	         switch(score)
	        {
			 case 100: printf("青銅");break; 
	         case 500: printf("白銀");speed=speed-1000;break;
	         case 1000:printf("黃金");break;
	         case 1500:printf("白金");speed=speed-3000;break;
	         case 2000:printf("鑽石");break;
	         case 2500:printf("大師");speed=speed-5000;break;
 	         case 3000:printf("王者");break;
        	}
				drawmap();
			}
		}
		//新方塊生成標識
		int newblock = 1;
		for (int i = 0; i < 240; i++)
		{
			if (map[i] == 1)
				newblock = 0;
		}
		//生成新方塊
		if (newblock == 1)
		{
			switch (nextblock[0])
			{
			case 0://i型 
				map[23] = 1;
				map[24] = 1;
				map[25] = 1;
				map[26] = 1;
				xblock[0] = 0;
				xblock[1] = 24;
				break;
			case 1:
				color(14);
				drawmapblock(blockT);
				break;
			case 2:
				color(11);
				drawmapblock(blockL);
				break;
			case 3:
				color(13);
				drawmapblock(blockO);//o型 
				xblock[0] = 2;
				break;
			case 4:
				color(2);
				drawmapblock(blockS);
				break;
			case 5:
			   color(6);
				drawmapblock(blockZ);
				break;
			case 6:
				color(15);
				drawmapblock(blockJ);
				break;
			}
			nextblock[0] = nextblock[1];
			drawnextblock(nextblock[0]);
			nextblock[1] = ranblock();

		}
		else if (newblock == 0)
		{
			//方向控制,形態變換
			int t = speed,t1=0;
			while (t>0)
			{
				int ch;
				if (t1<10&&_kbhit())//函數名:kbhit()
                                     //功能及返回值: 檢查當前是否有鍵盤輸入,若有則返回一個非0值,否則返回0。 
				{
					//需要調用兩次,因爲功能鍵第一次返回0或224
					ch = _getch();
					ch = _getch();
					//按下左鍵,判斷左邊是否有已經下落的方塊和是否已到達左邊界,如果沒有將正在下落的方塊左移
					if (ch == 75)//左鍵 
					{
						
							for (int i = 0; i < 24; i++)
							{
								if (map[i * 10] == 1)
									ch = 0;
							}
							if (ch!=0&&xblock[0] == 0&&map[xblock[1]+1]==1)
							{
								if (map[xblock[1] - 2] == 2)
									ch = 0;
							}
							if (ch != 0 && xblock[0] == 0 && map[xblock[1] - 10] == 1)
							{
								if (map[xblock[1] - 1] == 2)
									ch = 0;
							}
							if (ch != 0 && xblock[0] != 0)
							{
								for (int i = xblock[1] - 11; i < xblock[1] - 8; i++)
								{
									if ((map[i] == 1 && map[i - 1] == 2)|| (map[i + 10] == 1 && map[i + 9] == 2)||( map[i + 20] == 1 && map[i + 19] == 2))
										ch = 0;
								}
							}
							if (ch != 0)
							{
								for (int i = 0; i < 240; i++)
								{
									if (map[i] == 1)
									{
										map[i - 1] = map[i];
										map[i] = 0;
									}
								}
								xblock[1] = xblock[1] - 1;//
								drawmap();
							}
							
					}
					//按下上按鍵,判斷形態變換後是否重疊已經停止的方塊,如沒有形態變換
					if (ch == 72)//上鍵 
					{

						for (int i = 0; i < 24; i++)
						{
							if (i * 10 == xblock[1] || (i * 10 + 9) == xblock[1])
								ch = 0;
						}

						if (ch != 0 && xblock[0] == 0 && map[xblock[1] + 1] == 1 && map[xblock[1] + 10] != 2 && map[xblock[1] - 10] != 2 && map[xblock[1] - 20] != 2)
						{
							map[xblock[1] + 1] = 0;
							map[xblock[1] + 2] = 0;
							map[xblock[1] - 1] = 0;
							map[xblock[1] + 10] = 1;
							map[xblock[1] - 10] = 1;
							map[xblock[1] - 20] = 1;
							ch = 0;
						}
						if (ch != 0 && xblock[0] == 0 && map[xblock[1] - 10] == 1 && map[xblock[1] + 1] != 2 && map[xblock[1] + 2] != 2 && map[xblock[1] - 1] != 2)
						{
							map[xblock[1] + 1] = 1;
							map[xblock[1] + 2] = 1;
							map[xblock[1] - 1] = 1;
							map[xblock[1] + 10] = 0;
							map[xblock[1] - 10] = 0;
							map[xblock[1] - 20] = 0;
						}
						if (xblock[0] == 2)
							ch = 0;
						int tempblock[3][3];
						if (ch != 0 && xblock[0] == 1)
						{
							for (int i = 0; i < 3; i++)
							{
								for (int j = 0; j < 3; j++)
								{
									if (map[xblock[1] - 11 + j+i*10] != 2)
										tempblock[i][j] = map[xblock[1] - 11 + j + i * 10];
									else
										tempblock[i][j] = 0;
								}
							}
							for (int i = 0; i < 3; i++)
							{
								for (int j = 0; j < 3; j++)
								{
									if (tempblock[j][2 - i] == 1 && map[xblock[1] - 11 + j + i * 10] == 2)
										ch = 0;
								}
							}
						}
						if (ch != 0 && xblock[0] == 1)
						{
							for (int i = 0; i < 3; i++)
							{
								for (int j = 0; j < 3; j++)
								{
									if ( map[xblock[1] - 11 + j + i * 10] != 2)
										map[xblock[1] - 11 + j + i * 10] = tempblock[j][2-i];
								}
							}
						}
						drawmap();
						t1 = t1 + 1;
					}
					//按下右鍵,判斷右邊是否有已經下落的方塊和是否已到達右邊界,如果沒有將正在下落的方塊右移
					if (ch == 77)//右鍵 
					{
						for (int i = 0; i < 24; i++)
						{
							if (map[i * 10 + 9] == 1)
								ch = 0;

						}
						if (ch != 0 && xblock[0] == 0 && map[xblock[1] + 1] == 1)
						{
							if (map[xblock[1] +3] == 2)
								ch = 0;
						}
						if (ch != 0 && xblock[0] == 0 && map[xblock[1] - 10] == 1)
						{
							if (map[xblock[1] + 1] == 2)
								ch = 0;
						}
						if (ch != 0 && xblock[0] != 0)
						{
							for (int i = xblock[1] - 11; i < xblock[1] - 8; i++)
							{
								if ((map[i] == 1 && map[i + 1] == 2) || (map[i + 10] == 1 && map[i + 11] == 2) || (map[i + 20] == 1 && map[i + 21] == 2))
									ch = 0;
							}
						}
						if (ch != 0)
						{
							for (int i = 239; i >= 0; i--)
							{
								if (map[i] == 1)
								{
									map[i + 1] = map[i];
									map[i] = 0;
								}
							}
							xblock[1] = xblock[1] + 1;
								
						}
						drawmap();
					}
					//按下按鍵,方塊下落
					if (ch == 80)
					{
						downblock();
						drawmap();
						break;
					}
					//空格 暫停 
					if(ch==32) system("pause");
				}	
				t = t - 1;//t用來控制速度最開始循環20000次 
			}
			//自動下落
			if (t <= 0)
			{
				downblock();
				drawmap();
			}
			
		}	
	}
}
//入口函數
int main()
{
	title();
	welcom();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章