2021-05-15

俄羅斯方塊(bug未修復(fù)前)

include<stdio.h>

include<graphics.h>

include<time.h>

include<conio.h>//kbhit的使用

int score = 0;//分?jǐn)?shù)
int rank = 0;//等級(jí)

define BLOCK_COUNT 5

define BLOCK_WIDTH 5

define BLOCK_HEIGHT 5

define UNIT_SIZE 20

define START_X 130

define START_Y 30

define KEY_UP 72

define KEY_RIGHT 77

define KEY_DOWN 80

define KEY_LEFT 75

define KEY_SPACE 32

int speed = 500;
int minX = 30;
int minY = 30;

typedef enum {
BLOCK_UP,
BLOCK_RIGHT,
BLOCK_DOWN,
BLOCK_LEFT
}block_dir_t;

typedef enum {
MOVE_DOWN,
MOVE_LEFT,
MOVE_RIGHT,
}move_dir_t;

int NextIndex = -1;//下一個(gè)方塊的種類
int BlockIndex = -1;//當(dāng)前方塊的種類

int color[BLOCK_COUNT] = {
GREEN,CYAN,MAGENTA,BROWN,YELLOW
};

//訪問數(shù)組
int visit[30][15];
int markColor[30][15];//表示對(duì)應(yīng)位置的顏色

int block[BLOCK_COUNT * 4][BLOCK_WIDTH][BLOCK_HEIGHT] = {
// 1型方塊
{
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0,
},
//L性方塊
{
0,0,0,0,0,
0,0,1,0,0,
0,0,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,0,0,0,
0,1,1,1,0,
0,1,0,0,0,
0,0,0,0,0,
},
{
0, 0, 0, 0, 0,
0, 1, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 1, 0, 0,
0, 0, 0, 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,0,0,0,
0,1,1,0,0,
0,1,1,0,0,
0,0,0,0,0,
0,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,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,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,0,0,
},
//T形方塊
{
0,0,0,0,0,
0,1,1,1,0,
0,0,1,0,0,
0,0,0,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,0,1,0,
0,0,1,1,0,
0,0,0,1,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,1,0,
0,0,0,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,1,0,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0,
},
//Z形方塊
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,1,1,0,0,
0,0,1,1,0,
0,0,0,0,0,
0,0,0,0,0,
},
{
0,0,0,0,0,
0,0,1,0,0,
0,1,1,0,0,
0,1,0,0,0,
0,0,0,0,0,
}
};//=>;標(biāo)志著數(shù)組的結(jié)束

//實(shí)現(xiàn)歡迎界面
void welcome(void) {
//初始化畫布
initgraph(550,660);

//設(shè)置窗口標(biāo)題
HWND window = GetHWnd();//獲取窗口
SetWindowText(window, _T("俄羅斯方塊  設(shè)計(jì)師:曉寧 "));//設(shè)置窗口標(biāo)題

//設(shè)置文本的字體樣式
//setfont(40, 0, _T("微軟雅黑"));//setfont這個(gè)函數(shù)已經(jīng)棄用,代替它的是新函數(shù)settextstyle
settextstyle(40, 0,_T( "微軟雅黑"));//只指定高度,不指定寬度
setcolor(WHITE);
outtextxy(205,200,_T("俄羅斯方塊"));

//setfont(22, 0, _T("楷體"));//setfont這個(gè)函數(shù)已經(jīng)棄用,代替它的是新函數(shù)settextstyle
settextstyle(22, 0, _T("楷體"));
outtextxy(175, 300, _T("C++,從俄羅斯方塊開始!"));

Sleep(3000);//睡眠 (暫停) 3000毫秒 , 3秒鐘

}

//初始化游戲場(chǎng)景
void initGameScene(void) {
char str[16];

//清除屏幕
cleardevice();

rectangle(27, 27, 336, 635);
rectangle(29, 29, 334, 635);
rectangle(370, 50, 515, 195);

//setfont(22, 0, _T("楷體"));//setfont這個(gè)函數(shù)已經(jīng)棄用,代替它的是新函數(shù)settextstyle
settextstyle(24, 0, _T("楷體"));
setcolor(LIGHTGRAY);
outtextxy(405, 215,_T("下一個(gè)"));

setcolor(RED);
outtextxy(405, 280, _T("分?jǐn)?shù)"));
sprintf_s(str, "%d", score);
outtextxy(415, 310, str);

outtextxy(405, 375, _T("等級(jí)"));
sprintf_s(str, "%d", rank);
outtextxy(415, 405, str);

//操作說明
setcolor(LIGHTBLUE);
outtextxy(390, 475, _T("操作說明"));
outtextxy(390, 500, _T("↑:旋轉(zhuǎn)"));
outtextxy(390, 525, _T("↓:下降"));
outtextxy(390, 550, _T("←:左移"));
outtextxy(390, 575, _T("→:右移"));
outtextxy(390, 600, _T("空格:暫停"));

}

void clearBlock(void) {//清除方塊
setcolor(BLACK);
settextstyle(23,0,_T("楷體"));
for (int i = 1;i < BLOCK_HEIGHT;i++) {
for (int j = 0;j < BLOCK_HEIGHT;j++) {
//"■"
int x = 391 + j * UNIT_SIZE;
int y = 71 + i * UNIT_SIZE;
outtextxy(x,y, "■");
}
}
}

void clearBlock(int x, int y, block_dir_t dir) {

}

//在右上角區(qū)域中,繪制下一個(gè)方塊
//繪制方塊:在指定位置繪制指定方塊的指定方向
void drawBlock(int x,int y,int blockIndex,block_dir_t dir) {
setcolor(color[NextIndex]);
settextstyle(23, 0, _T("楷體"));
int id = blockIndex * 4 + dir;
for (int i = 1;i < BLOCK_HEIGHT;i++) {
for (int j = 0;j < BLOCK_HEIGHT;j++) {
//"■"
if (block[4 * NextIndex][i][j] == 1) {
int x2 = 391 + j * UNIT_SIZE;
int y2 = 71 + i * UNIT_SIZE;
outtextxy(x2, y2, "■");
}
}
}
}
//清除指定位置指定方向的方塊
//參數(shù)x:方塊的左上角的x坐標(biāo)
//參數(shù)y:方塊的左上角在游戲區(qū)域內(nèi)的坐標(biāo),距離游戲區(qū)域頂部的距離
void clearBlock(int x, int y , block_dir_t dir) {
setcolor(BLACK);
int id = BlockIndex * 4 + dir;
y += START_Y;

for (int i = 0;i < 5;i++) {
    for (int j = 0;j < 5;j++) {
        if (block[id][i][j] == 1) {
            //擦出該方塊的第i行的第j列
            outtextxy(x + 20 * j, y + i * 20, "■");
        }
    }
}

}

void nextblock(void) {
clearBlock();//清除右上角區(qū)域

//隨機(jī)選擇一種方塊
srand(time(NULL));//使用時(shí)間函數(shù)的返回值,來作為隨機(jī)種子
NextIndex = rand() % BLOCK_COUNT;

drawBlock(391,71);

}

//如果在指定位置可以向指定方向移動(dòng),就返回1,否則就返回0
int moveable(int x0, int y0, move_dir_t moveDir, block_dir_t blockDir) {
//計(jì)算當(dāng)前方塊的左(zuo)上角在30*15的游戲區(qū)的位置(第多少行,第多少列)
int x = (y0 - minY) / UNIT_SIZE;
int y = (x0 - minX) / UNIT_SIZE;

int id = BlockIndex * 4 + blockDir;
int ret = 0;

if (moveDir = MOVE_DOWN) {
    for (int i = 0;i < 5;i++) {
        for (int j = 0;j < 5;j++) {
            if (block[id][i][j] == 1 &&
                (x + i + 1 >= 30 || visit[x + i + 1][y + j] == 1)) {
                ret = 0;
            }
        }
    }
}
else if (moveDir == MOVE_LEFT) {
    for (int i = 0;i < 5;i++) {
        for (int j = 0;j < 5;j++) {
            if (block[id][i][j] == 1 &&
                (y + j == 0 || visit[x + i][y + j - 1] == 1)) {
                ret = 0;
            }
        }
    }
}
else if (moveDir == MOVE_RIGHT) {
    for (int i = 0;i < 5;i++) {
        for (int j = 0;j < 5;j++) {
            if (block[id][i][j] == 1 &&
                (y + j + 1 >= 15 || visit[x + i][y + j + 1] == 1))) {
                ret = 0;
            }
        }
    }
}
return ret;

}

//檢測(cè)游戲是否結(jié)束
void failCheck() {
if (!moveable(START_X, START_Y, MOVE_DOWN, BLOCK_UP)) {
setcolor(WHITE);
settextstyle(45,0,"隸體");
outtextxy(75,300,"GAME OVER!");
Sleep(1000);
system("pause");
closegraph();
exit(0);
}
}

//判斷當(dāng)前方塊是否可以轉(zhuǎn)向到指定方向
//注意,此時(shí)還沒有轉(zhuǎn)到指定方向!!!
int rotatable(int x, int y, block_dir_t) {
int id = BlockIndex * 4 + dir;
int xIndex = (y - minY) / 20;
int yIndex = (x - minX) / 20;

if (!moveable(x, y, MOVE_DOWN, dir)) {
    return 0;
}

for (int i = 0;i < 5;i++) {
    for (int j = 0;j < 5;j++) {
        if (block[id][i][j]==1&&
            (yIndex +j<0|| yIndex +j>=15||visit[xIndex +1][yIndex +j]==1)) {
            return 0;

        }
    }
}

}

void wait(int interval) {//500
int cout = interval / 10;
for (int i = 0;i < cout;i++) {
Sleep(10);
if (_kbhit()) {
return;
}
}
}

void mark(int x, int y, int blockIndex, block_dir_t dir) {
int id = blockIndex * 4 + dir;
int x2 = (y - minX)/20;
int y2 = (x - minY) / 20;

for (int i = 0;i < 5;i++) {
    for (int j = 0;j < 5;j++) {
        if (block[id][i][j] == 1) {
            visit[x2+i][y2+j] = 1;
            markColor[x2 + i][y2 + j] = color[blockIndex];
        }
    }
}

}

void move(void) {
int x = START_X;
int y = START_Y;
int k = 0;
block_dir_t blockDir = BLOCK_UP;
int curSpeed = speed;

//檢測(cè)游戲是否結(jié)束
failCheck();

//持續(xù)向下降落
while (1) {
    if (_kbhit()) {
        int key = _getch();
        if (key == KEY_SPACE) {
            _getch();
        }
    }

    //清除當(dāng)前方塊
    clearBlock(x, k, blockDir);

    if (_kbhit()) {
        int key = _getch();
        if (key == KEY_UP) {

            block_dir_t nextDir = (block_dir_t)((blockDir + 1) % 4);

            if (rotatable(x, y + k, nextDir) {

                blockDir = nextDir;

            }
        }
        else if (key == KEY_DOWN) {
            curSpeed = 50;
        }
        else if (key == KEY_LEFT) {
            if (moveable(x, y + k + 20, MOVE_LEFT, blockDir)) {
                x -= 20;
            }
        }
        else if (key == KEY_RIGHT) {
            if (moveable(x, y + k + 20, MOVE_RIGHT, blockDir)) {
                x += 20;
                //x=x+20;
            }
        }
    }

    k += 20;

    //繪制當(dāng)前方塊
    drawBlock(x, y + k, BlockIndex, blockDir);
    wait(curSpeed);

    

    //方塊的"固化"處理
    if (!moveable(x, y + k, MOVE_DOWN, blockDir)) {
        mark(x, y + k, BlockIndex, blockDir);
        break;
    }
}

}

void newblock(void) {
//確定即將使用的方塊的類別
BlockIndex = NextIndex;

//繪制剛從頂部下降的方塊
drawBlock(START_X, START_Y);

//讓新方塊停0.1秒
Sleep(100);

//在右上角區(qū)域,繪制下一個(gè)方塊
nextblock();

//方塊降落
move();

}

//消除第i行,并把上面的行都下移
void down(int i) {
for (int i = x;i > 0;i--) {
//消除第i行,第j列的方塊
for (j = 0;j < 15;j++) {
if (visit[i - 1][j]) {
visit[i][j] = 1;
markColor[i][j] = markColor[i - 1][j];
setcolor(markColor[i][j]);
outtextxy(20 * j + minX, 20 * j + minY, "■");
}
else {
visit[i][j] = 0;
setcolor(BLACK);
outtextxy(20 * j + mianX, 20 * j + mianY, "■");
}
}
}
//清除頂行(就是行標(biāo)為0的哪一行)
SetBkColor(BLACK);
for (int j = 0;j < 15;j++) {
visit[0][j] = 0;
outtextxy(20 * j + minX, minY, "■");
}

}

//更新分?jǐn)?shù),參數(shù)line表示消除行數(shù)
void addScore(int lines) {
char sty[32];

setcolor(RED);
score += lines * 10;
sprintf(str, "%d", score);
outtextxy(415, 310, str);

}

void updateGrade() {
//更新等級(jí)的提示
//假設(shè):50分一級(jí)
rank = score / 50;
char str[16];
sprintf(str,"%d",rank);
outtextxy(425, 405, str);
//更新速度
//注意:更新速度,速度越快,speed越小!
//最慢:500,最快:100
speed = 500 - rank * 100;
if (speed <= 100) {
speed = 100;
}
}

void check(void) {
int i, j;
int clearLines = 0;
for (int i = 29;i >= 0;i--) {
//檢查第i行有沒有滿
for (int j = 0;j < 15 && visit[i][j];j++);

    //執(zhí)行到此處,有兩種情況:
    //1.第i行沒有滿,即表示有空位 此時(shí)j<15
    //2.第j行已滿了,此時(shí)j>=15
    if (j >= 15) {
        //此時(shí),第i行已經(jīng)滿了,就需要消除第i行
        down(i);//消除第i行,并把上面的行都下移
        i++;//因?yàn)樽钔鈱拥难h(huán)有i--,所以我們先i++,使得下次循環(huán),再把這一行檢查一下
        clearLines++;
    }
}
//更新分?jǐn)?shù)
addScore(clearLines);
//更新等級(jí)
//等級(jí)越高,方塊下降速度越快,難度越大
//(更新等級(jí)提示,更新速度)
updateGrade();

}

int main(void) {
welcome();
initGameScene();

//產(chǎn)生新方塊
nextblock();
Sleep(500);
    
//初始化訪問數(shù)組
memset(visit, 0, sizeof(visit));

while (1) {
    newblock();

    //消除滿行,并更新分?jǐn)?shù)和速度
    check();

}

system("pause");

closegraph();

return 0;

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過簡(jiǎn)信或評(píng)論聯(lián)系作者瘟判。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌彼棍,老刑警劉巖民泵,帶你破解...
    沈念sama閱讀 218,546評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異莫辨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,224評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門沮榜,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盘榨,“玉大人,你說我怎么就攤上這事蟆融〔菅玻” “怎么了?”我有些...
    開封第一講書人閱讀 164,911評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵型酥,是天一觀的道長(zhǎng)山憨。 經(jīng)常有香客問我,道長(zhǎng)弥喉,這世上最難降的妖魔是什么郁竟? 我笑而不...
    開封第一講書人閱讀 58,737評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮由境,結(jié)果婚禮上棚亩,老公的妹妹穿的比我還像新娘。我一直安慰自己虏杰,他們只是感情好讥蟆,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,753評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著纺阔,像睡著了一般瘸彤。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上笛钝,一...
    開封第一講書人閱讀 51,598評(píng)論 1 305
  • 那天质况,我揣著相機(jī)與錄音,去河邊找鬼玻靡。 笑死拯杠,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的啃奴。 我是一名探鬼主播潭陪,決...
    沈念sama閱讀 40,338評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼最蕾!你這毒婦竟也來了依溯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,249評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤瘟则,失蹤者是張志新(化名)和其女友劉穎黎炉,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體醋拧,經(jīng)...
    沈念sama閱讀 45,696評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡慷嗜,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,888評(píng)論 3 336
  • 正文 我和宋清朗相戀三年淀弹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片庆械。...
    茶點(diǎn)故事閱讀 40,013評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡薇溃,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出缭乘,到底是詐尸還是另有隱情沐序,我是刑警寧澤,帶...
    沈念sama閱讀 35,731評(píng)論 5 346
  • 正文 年R本政府宣布堕绩,位于F島的核電站策幼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏奴紧。R本人自食惡果不足惜特姐,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,348評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望黍氮。 院中可真熱鬧到逊,春花似錦、人聲如沸滤钱。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,929評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)件缸。三九已至,卻和暖如春叔遂,著一層夾襖步出監(jiān)牢的瞬間他炊,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,048評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工已艰, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留痊末,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,203評(píng)論 3 370
  • 正文 我出身青樓哩掺,卻偏偏與公主長(zhǎng)得像凿叠,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子嚼吞,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,960評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容