ETH官方钱包

前往
大廳
主題

C/C++ 紀錄三十六 <俄羅斯方塊實作Tetris> 2020/5/4

艾倫D索妮雅 | 2021-06-10 20:02:56 | 巴幣 0 | 人氣 1363




#include<iostream>
#include<windows.h>
#include<string>
#include<cstdlib>
#include<conio.h>
#include<ctime>
/* 俄羅斯方塊  Tetris */
using namespace std;
/* 工具箱  */
HANDLE hIn,hOut;
//取得後臺處理I/O控制權,hIn=>鍵盤控制  hOut=>螢幕輸出控制
void Control_HANDLE_Unit()
{
hIn=GetStdHandle(STD_INPUT_HANDLE);
hOut=GetStdHandle(STD_OUTPUT_HANDLE);
}
//座標給定函式
void position(int x,int y)
{
static COORD c;
c.X = x;
c.Y = y;
SetConsoleCursorPosition(hOut,c);
}
/*遊戲主體*/
/** 遊戲框架 **/
const int nWidth=15,nHeight=20;
char Unit[3]={'|','H','X'}; //邊、底邊、方塊
int frame[nHeight][nWidth]={0}; //後臺參數,框架中frame[y][x] x,y為x座標和y座標; 其值=>有0,1,2,3; 0空白,1為邊,2為底邊,3方塊
int Delay_time;
int score = 0;
//繪製函式
void draw(int x,int y,int uniframe,char *unit)
{
if(uniframe==1)
{
position(x,y);
cout<<unit[0];
}
else if(uniframe==2)
{
position(x,y);
cout<<unit[1];
}
else if(uniframe==3)
{
position(x,y);
cout<<unit[2];
}
else
{
position(x,y);
cout<<' ';
}
}
/**方塊架構 **/
int i=5,j=0; //方塊初始座標
//7種方塊
int Asset[7][4][4]={ {{0,0,3,0},{0,0,3,0},{0,0,3,0},{0,0,3,0}},
    {{0,0,3,0},{0,3,3,0},{0,3,0,0},{0,0,0,0}},
    {{0,3,0,0},{0,3,3,0},{0,0,3,0},{0,0,0,0}},
    {{0,0,0,0},{0,0,3,0},{0,3,3,3},{0,0,0,0}},
    {{0,0,0,0},{0,3,3,0},{0,3,3,0},{0,0,0,0}},
    {{0,3,3,0},{0,0,3,0},{0,0,3,0},{0,0,0,0}},
   {{0,3,3,0},{0,3,0,0},{0,3,0,0},{0,0,0,0}} };
//方塊落下 =>方塊放置位置(x,y)、清除方塊、方塊放置位置(x,y+1)
void AssetPos(int px,int py,int (&asset)[4][4])//px,py為起始位置
{
for(int y=py; y<(py+4); y++)
{
for(int x=px; x<(px+4); x++)
{
if(frame[y][x]==0 && asset[y-py][x-px]!=0)
{
frame[y][x]=asset[y-py][x-px];
draw(x,y,frame[y][x],Unit);
}
}
}
}
void cleanAsset(int px,int py,int (&asset)[4][4])
{
for(int y=py; y<(py+4); y++)
{
for(int x=px; x<(px+4); x++)
{
if(asset[y-py][x-px]==3)
{
frame[y][x]=0;
draw(x,y,frame[y][x],Unit);
}
}
}
}
//判斷方塊是否碰撞
bool collision(int px,int py,int (&asset)[4][4])
{
for(int y=py; y<(py+4); y++)
for(int x=px; x<(px+4); x++)
if(frame[y][x]!=0 && asset[y-py][x-px]!=0) return 1;
return 0;
}
//方塊旋轉
void Rotation(int px,int py,int (&asset)[4][4])
{
int temp[4][4]={0};
for(int x=0; x<4; x++)
for(int y=0; y<4; y++)
temp[x][y]=asset[3-y][x]; //轉90度
cleanAsset(px,py,asset);
if(!collision(px, py, temp))
{
for(int x=0; x<4; x++)
for(int y=0; y<4; y++)
asset[x][y]=temp[x][y];
}
AssetPos(px,py,asset);
}
//鍵盤控制 往左、往右、旋轉
static DWORD count;
static INPUT_RECORD ir;
void key_Control(int (&asset)[4][4])
{
ReadConsoleInput(hIn,&ir,1,&count);
switch(ir.Event.KeyEvent.wVirtualKeyCode)
{
case VK_LEFT: //向左
cleanAsset(i,j,asset);
if(collision(i-1,j,asset))//判斷落到下一格是否發生碰撞
AssetPos(i,j,asset);
else
{
i--;
AssetPos(i,j,asset);
}
break;
    case VK_RIGHT: //向右
cleanAsset(i,j,asset);
if(collision(i+1,j,asset))//判斷落到下一格是否發生碰撞
AssetPos(i,j,asset);
else
{
i++;
AssetPos(i,j,asset);
}
break;
case VK_UP: //旋轉
Rotation(i,j,asset);
break;
case VK_DOWN: //快速落下
Delay_time=0;
break;
}
Sleep(30);
}
//遊戲判定
bool Eliminate_Row_Asset(int y) //當一排都為方塊時,消除該牌方塊
{
for(int x=1;x<nWidth-1;x++)
if(frame[y][x]!=3) return 0;
return 1;
}
void Score(int count)
{
score+=count;
position(nWidth+16,nHeight-1);
cout<<score;
}
bool GameOver()
{
for(int x=0; x<nWidth; x++)
{
if(frame[0][x]==3)
return 1;
}
return 0;
}
void SpeedMode()
{
if(score>5000)
Delay_time = 25;
else if(score>4000)
Delay_time = 50;
else if(score>2000)
Delay_time = 100;
else if (score>1000)
Delay_time = 150;
else
Delay_time = 200;
}
int main()
{
Control_HANDLE_Unit();
//遊戲背景
for(int x=0; x<nWidth; x++) //底邊框
frame[nHeight-1][x]=2;
for(int y=0; y<nHeight; y++) //邊框
{
frame[y][0]=1;
frame[y][nWidth-1]=1;
}
for(int y=0; y<nHeight; y++)
for(int x=0; x<nWidth; x++)
draw(x,y,frame[y][x],Unit);
for(int y=0; y<nHeight; y++)
{
position(nWidth+1,y);
cout<<'>'<<y;
}
//計分板
position(nWidth+10,nHeight-1);
cout<<"Score:";
Score(0);
//放入方塊  
int asset[4][4]={0}; //目前的方塊
while(1)
{
i=5,j=0; //起始座標i,j
SpeedMode(); //速度模式
srand(time(NULL));
int random = rand()%7;
for(int i=0; i<4; i++)
{
for(int j=0; j<4; j++)
asset[i][j]=Asset[random][i][j]; //選取隨機7種方塊之一
}
AssetPos(i,j,asset);
//方塊落下
while(1)
{
while(!kbhit())
{
Sleep(Delay_time);
cleanAsset(i,j,asset);
if(collision(i,j+1,asset)) //有碰撞
{
AssetPos(i,j,asset);
break;
}
j++;
AssetPos(i,j,asset);
Sleep(Delay_time);
if(kbhit())
{
ReadConsoleInput(hIn,&ir,1,&count);
key_Control(asset);
}
}
if(kbhit())
{
ReadConsoleInput(hIn,&ir,1,&count);
key_Control(asset);
}
cleanAsset(i,j,asset);
if(collision(i,j+1,asset))
{
AssetPos(i,j,asset);
break;
}
AssetPos(i,j,asset);
}
for(int y=nHeight-2; y>0; y--) //削掉方塊並計分
{
if(Eliminate_Row_Asset(y))
{
for(int x=1; x<nWidth-1; x++)
{
frame[y][x]=0;
draw(x,y,frame[y][x],Unit);
}
Sleep(100);
Score(100);
for(int j=y; j>0; j--)//上面方塊掉下來
{
for(int x=1; x<nWidth-1; x++)
{
frame[j][x]=frame[j-1][x];
draw(x,j,frame[j][x],Unit);
}
}
y++;
}
}
if(GameOver())
{
position(nWidth+10,nHeight/2);
cout<<"GAME OVER!!";
break;
}
}
system("PAUSE");
return 0;
}

創作回應

更多創作