2021-05-15

bug修復(fù)后
可正常運(yùn)行

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_HEIGHT][BLOCK_WIDTH] = {
// 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, 633);
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(425, 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, "楷體");

for (int i = 0; i < BLOCK_HEIGHT; i++) {//參數(shù)錯(cuò)誤!=>已改正
    for (int j = 0; j < BLOCK_WIDTH; j++) {
        //"■"
        int x = 391 + j * UNIT_SIZE;
        int y = 71 + i * UNIT_SIZE;
        outtextxy(x, y, "■");
    }
}

}

// 繪制方塊
void drawBlock(int x, int y) {
setcolor(color[NextIndex]);
settextstyle(23, 0, "楷體");

for (int i = 0; i < BLOCK_HEIGHT; i++) {
    for (int j = 0; j < BLOCK_WIDTH; j++) {
        if (block[NextIndex * 4][i][j] == 1) {
            int x2 = x + j * UNIT_SIZE;
            int y2 = y + i * UNIT_SIZE;
            outtextxy(x2, y2, "■");
        }
    }
}

}

void drawBlock(int x, int y, int blockIndex, block_dir_t dir) {
setcolor(color[blockIndex]);
settextstyle(23, 0, "楷體");//參數(shù)錯(cuò)誤=>已更正
int id = blockIndex * 4 + dir;

for (int i = 0; i < BLOCK_HEIGHT; i++) {//參數(shù)錯(cuò)誤=>已更正
    for (int j = 0; j < BLOCK_WIDTH; j++) {
        //"■"
        if (block[id][i][j] == 1) {
            int x2 = x + j * UNIT_SIZE;
            int y2 = y + 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);//找其定義,揪出錯(cuò)誤

}

//如果在指定位置可以向指定方向移動(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 = 1;

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 dir) {
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 +i][yIndex +j]==1)) {
            return 0;

        }
    }
}

}

void wait(int interval) {//500
int count = interval / 10;
for (int i = 0;i < count;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 - minY)/20;
int y2 = (x - minX) / 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() {
//確定即將使用的方塊的類別
BlockIndex = NextIndex;

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

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

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

//方塊降落
move();

}

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

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

}

void updateGrade() {
//更新等級(jí)的提示
//假設(shè):50分一級(jí)
rank = score / 50;
char str[16];
sprintf_s(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 ( i = 29;i >= 0;i--) {
//檢查第i行有沒有滿
for ( 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,640評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異朦乏,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)氧骤,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,254評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門呻疹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人筹陵,你說我怎么就攤上這事刽锤∧鞒撸” “怎么了?”我有些...
    開封第一講書人閱讀 165,011評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵并思,是天一觀的道長(zhǎng)庐氮。 經(jīng)常有香客問我,道長(zhǎng)宋彼,這世上最難降的妖魔是什么弄砍? 我笑而不...
    開封第一講書人閱讀 58,755評(píng)論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮输涕,結(jié)果婚禮上音婶,老公的妹妹穿的比我還像新娘。我一直安慰自己莱坎,他們只是感情好衣式,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,774評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著檐什,像睡著了一般碴卧。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乃正,一...
    開封第一講書人閱讀 51,610評(píng)論 1 305
  • 那天螟深,我揣著相機(jī)與錄音,去河邊找鬼烫葬。 笑死界弧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搭综。 我是一名探鬼主播垢箕,決...
    沈念sama閱讀 40,352評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼兑巾!你這毒婦竟也來了条获?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,257評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤蒋歌,失蹤者是張志新(化名)和其女友劉穎帅掘,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體堂油,經(jīng)...
    沈念sama閱讀 45,717評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡修档,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,894評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了府框。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吱窝。...
    茶點(diǎn)故事閱讀 40,021評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出院峡,到底是詐尸還是另有隱情兴使,我是刑警寧澤,帶...
    沈念sama閱讀 35,735評(píng)論 5 346
  • 正文 年R本政府宣布照激,位于F島的核電站发魄,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏俩垃。R本人自食惡果不足惜欠母,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,354評(píng)論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吆寨。 院中可真熱鬧赏淌,春花似錦、人聲如沸啄清。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,936評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)辣卒。三九已至掷贾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荣茫,已是汗流浹背想帅。 一陣腳步聲響...
    開封第一講書人閱讀 33,054評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留啡莉,地道東北人港准。 一個(gè)月前我還...
    沈念sama閱讀 48,224評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像咧欣,于是被迫代替她去往敵國(guó)和親浅缸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,974評(píng)論 2 355

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