製作一個簡易的俄羅斯方塊,未調用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;
}