命令列之俄羅斯方塊
阿新 • • 發佈:2019-01-23
#include <iostream> #include <windows.h> #include <conio.h> #include <time.h> #include <cstdlib> #define Coord_x 15 #define Coord_y 15 #define Height 20 #define Width 16 using namespace std; class Block{ public: int x; int y; int flag; int next_flag; int block_speed; int block_speed_temp; int block_num; int score; int level; int patten_mark[80][80]; int block[4]; public: void get_flag(); void make_block(); void output_block(HANDLE hOutk); void clear_Block(HANDLE hOut); bool if_move(); void if_full(HANDLE hOut); Block(int bs = 300, int bst = 300, int bn = 0, int s = 0, int l = 1); }B; class Console{ public: void gotoxy(HANDLE hOut, int x, int y); void enter_game(); void initialize_window(); void start_game(); void end_game(); friend class Block; }C; Block::Block(int bs,int bst,int bn,int s,int l) { block_speed = bs; block_speed_temp = bst; block_num = bn; score = s; level = l; } void Console::gotoxy(HANDLE hOut, int x, int y) { COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(hOut, pos); } void Console::enter_game() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); system("title 俄羅斯方塊 by Tc"); gotoxy(hOut,Coord_x+Width+1,Coord_y-10); SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); cout<<"歡迎進入俄羅斯方塊"; for(int i = 8; i > 0; i--) { gotoxy(hOut,Coord_x+Width-2,Coord_y-i); SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY | FOREGROUND_GREEN); cout << "■■■■■■■■■■■■"; } gotoxy(hOut,Coord_x+Width+2,Coord_y+2); SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY | FOREGROUND_RED); cout << "按回車鍵進入遊戲\n"<< endl;; while(1) { char c; if(kbhit()) { //監控鍵盤是否被按下,並顯示按下的字元 c = getch(); if(c == 13) { system("CLS"); C.initialize_window(); C.start_game(); } } cout << "■" ; Sleep(200); } if(getch() == 27) { C.end_game(); } else { C.enter_game(); } } void Console::end_game() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); system("CLS"); gotoxy(hOut,Coord_x+Width+5,Coord_y-10); cout << "遊戲結束"; gotoxy(hOut,Coord_x+Width+5,Coord_y-7); cout << "最終得分 : " << B.score << endl; exit(0); } void Console::initialize_window() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); system("title 俄羅斯方塊 by Tc"); system("color 0C"); gotoxy(hOut,Coord_x+Width-5,Coord_y-1); cout << "**********"; gotoxy(hOut,Coord_x+Width-5,Coord_y-2); cout << "俄羅斯方塊"; gotoxy(hOut,Coord_x+Width-5,Coord_y-3); cout << "**********"; gotoxy(hOut,Coord_x+2*Width+3,Coord_y+6); SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); cout << "***********"; gotoxy(hOut,Coord_x+2*Width+3,Coord_y+7); cout << "下一個方塊:"; gotoxy(hOut,Coord_x+2*Width+3,Coord_y+12); cout << "***********"; gotoxy(hOut,Coord_x+2*Width+3,Coord_y+Height-4); cout << "w鍵 : 旋轉 " << "s鍵 : 沉底"; gotoxy(hOut,Coord_x+2*Width+3,Coord_y+Height-2); cout << "a鍵 : 左移 " << "d鍵 : 右移"; gotoxy(hOut,Coord_x+2*Width+3,Coord_y+Height); cout << "空格鍵 :暫停"; gotoxy(hOut,Coord_x+2*Width+3,Coord_y+Height-6); cout << "Esc :退出"; SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY | FOREGROUND_GREEN); for(int i = 0;i < 2 * Width - 1; i += 2) { gotoxy(hOut,Coord_x+i,Coord_y); cout << "*"; } for(int i = 0;i < 2 * Width - 1; i += 2) { gotoxy(hOut,Coord_x+i,Coord_y+Height); cout << "*"; B.patten_mark[Coord_x+i][Coord_y+Height] = 2; } for(int i = 0;i < Height;i++) { gotoxy(hOut,Coord_x,Coord_y+i); cout << "*"; B.patten_mark[Coord_x][Coord_y+i] = 2; } for(int i = 0;i < Height;i ++) { gotoxy(hOut,Coord_x+2*Width-2,Coord_y+i); cout << "*"; B.patten_mark[Coord_x+2*Width-2][Coord_y+i] = 2; } } void Block::make_block() { B.patten_mark[B.x][B.y] = block[0]; switch(B.flag) { case 1: //田 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x+2][B.y-1] = block[2]; B.patten_mark[B.x+2][B.y] = block[3]; break; } case 2: //橫直線 { B.patten_mark[B.x-2][B.y] = block[1]; B.patten_mark[B.x+2][B.y] = block[2]; B.patten_mark[B.x+4][B.y] = block[3]; break; } case 3: //豎直線 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x][B.y-2] = block[2]; B.patten_mark[B.x][B.y+1] = block[3]; break; } case 4: //T { B.patten_mark[B.x-2][B.y] = block[1]; B.patten_mark[B.x+2][B.y] = block[2]; B.patten_mark[B.x][B.y+1] = block[3]; break; } case 5: //T順時針轉90度 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x][B.y+1] = block[2]; B.patten_mark[B.x-2][B.y] = block[3]; break; } case 6: //T順時針轉180度 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x-2][B.y] = block[2]; B.patten_mark[B.x+2][B.y] = block[3]; break; } case 7: //T順時針轉270度 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x][B.y+1] = block[2]; B.patten_mark[B.x+2][B.y] = block[3]; break; } case 8: //Z { B.patten_mark[B.x][B.y+1] = block[1]; B.patten_mark[B.x-2][B.y] = block[2]; B.patten_mark[B.x+2][B.y+1] = block[3]; break; } case 9: //Z順時針轉90度 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x-2][B.y] = block[2]; B.patten_mark[B.x-2][B.y+1] = block[3]; break; } case 10: //Z順時針轉180度 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x-2][B.y-1] = block[2]; B.patten_mark[B.x+2][B.y] = block[3]; break; } case 11: //Z順時針轉270度 { B.patten_mark[B.x][B.y+1] = block[1]; B.patten_mark[B.x+2][B.y-1] = block[2]; B.patten_mark[B.x+2][B.y] = block[3]; break; } case 12: //倒Z { B.patten_mark[B.x][B.y+1] = block[1]; B.patten_mark[B.x+2][B.y] = block[2]; B.patten_mark[B.x-2][B.y+1] = block[3]; break; } case 13: //倒Z順時針轉90度 { B.patten_mark[B.x-2][B.y] = block[1]; B.patten_mark[B.x-2][B.y-1] = block[2]; B.patten_mark[B.x][B.y+1] = block[3]; break; } case 14: //倒Z順時針轉180度 { B.patten_mark[B.x-2][B.y] = block[1]; B.patten_mark[B.x][B.y-1] = block[2]; B.patten_mark[B.x+2][B.y-1] = block[3]; break; } case 15: //倒Z順時針轉270度 { B.patten_mark[B.x+2][B.y] = block[1]; B.patten_mark[B.x][B.y-1] = block[2]; B.patten_mark[B.x+2][B.y+1] = block[3]; break; } case 16: //7 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x][B.y+1] = block[2]; B.patten_mark[B.x-2][B.y-1] = block[3]; break; } case 17: //7順時針轉90度 { B.patten_mark[B.x-2][B.y]=block[1]; B.patten_mark[B.x+2][B.y-1]=block[2]; B.patten_mark[B.x+2][B.y]=block[3]; break; } case 18: //7順時針轉180度 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x][B.y+1] = block[2]; B.patten_mark[B.x+2][B.y+1] = block[3]; break; } case 19: //7順時針轉270度 { B.patten_mark[B.x-2][B.y+1] = block[1]; B.patten_mark[B.x+2][B.y] = block[2]; B.patten_mark[B.x-2][B.y] = block[3]; break; } case 20: //倒7 { B.patten_mark[B.x][B.y+1] = block[1]; B.patten_mark[B.x][B.y-1] = block[2]; B.patten_mark[B.x+2][B.y-1] = block[3]; break; } case 21: //倒7順指標轉90度 { B.patten_mark[B.x-2][B.y] = block[1]; B.patten_mark[B.x+2][B.y+1] = block[2]; B.patten_mark[B.x+2][B.y] = block[3]; break; } case 22: //倒7順時針轉180度 { B.patten_mark[B.x][B.y-1] = block[1]; B.patten_mark[B.x][B.y+1] = block[2]; B.patten_mark[B.x-2][B.y+1] = block[3]; break; } case 23: //倒7順時針轉270度 { B.patten_mark[B.x-2][B.y] = block[1]; B.patten_mark[B.x-2][B.y-1] = block[2]; B.patten_mark[B.x+2][B.y] = block[3]; break; } } } bool Block::if_move() { if(B.patten_mark[B.x][B.y] != 0) { return 0; } else { if( (B.flag == 1 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x+2][B.y-1] == 0 && B.patten_mark[B.x+2][B.y] == 0)) || (B.flag == 2 && (B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x+2][B.y] == 0 && B.patten_mark[B.x+4][B.y] == 0)) || (B.flag == 3 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x][B.y-2] == 0 && B.patten_mark[B.x][B.y+1] == 0)) || (B.flag == 4 && (B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x+2][B.y] == 0 && B.patten_mark[B.x][B.y+1] == 0)) || (B.flag == 5 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x-2][B.y] == 0)) || (B.flag == 6 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x+2][B.y] == 0)) || (B.flag == 7 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x+2][B.y] == 0)) || (B.flag == 8 && (B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x+2][B.y+1] == 0)) || (B.flag == 9 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x-2][B.y+1] == 0)) || (B.flag == 10 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x-2][B.y-1] == 0 && B.patten_mark[B.x+2][B.y] == 0)) || (B.flag == 11 && (B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x+2][B.y-1] == 0 && B.patten_mark[B.x+2][B.y] == 0)) || (B.flag == 12 && (B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x+2][B.y] == 0 && B.patten_mark[B.x-2][B.y+1] == 0)) || (B.flag == 13 && (B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x-2][B.y-1] == 0 && B.patten_mark[B.x][B.y+1] == 0)) || (B.flag == 14 && (B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x+2][B.y-1] == 0)) || (B.flag == 15 && (B.patten_mark[B.x+2][B.y] == 0 && B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x+2][B.y+1] == 0)) || (B.flag == 16 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x-2][B.y-1] == 0)) || (B.flag == 17 && (B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x+2][B.y-1] == 0 && B.patten_mark[B.x+2][B.y] == 0)) || (B.flag == 18 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x+2][B.y+1] == 0)) || (B.flag == 19 && (B.patten_mark[B.x-2][B.y+1] == 0 && B.patten_mark[B.x+2][B.y] == 0 && B.patten_mark[B.x-2][B.y] == 0)) || (B.flag == 20 && (B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x+2][B.y-1] == 0)) || (B.flag == 21 && (B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x+2][B.y+1] == 0 && B.patten_mark[B.x+2][B.y] == 0)) || (B.flag == 22 && (B.patten_mark[B.x][B.y-1] == 0 && B.patten_mark[B.x][B.y+1] == 0 && B.patten_mark[B.x-2][B.y+1] == 0)) || (B.flag == 23 && (B.patten_mark[B.x-2][B.y] == 0 && B.patten_mark[B.x-2][B.y-1] == 0 && B.patten_mark[B.x+2][B.y] == 0)) ) { return 1; } } return 0; } void Block::get_flag() { B.block_num ++; srand((unsigned)time(NULL)); if(B.block_num == 1) { B.flag = rand()%23+1; } B.next_flag = rand()%23+1; } void Block::output_block(HANDLE hOut) { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); for(int i = 0;i < 4; i++) { B.block[i] = 1; } B.make_block(); for(int i = B.x-2;i <= B.x+4; i += 2) //列印方塊,4*4 { for(int j = B.y-2;j <= B.y+1; j++) { if(B.patten_mark[i][j] == 1 && j > Coord_y && j < Coord_y + Height) { C.gotoxy(hOut,i,j); SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY |FOREGROUND_GREEN); cout << "■"; } } } SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN); C.gotoxy(hOut,Coord_x+2*Width+3,Coord_y); cout << "等級 : " << B.level; C.gotoxy(hOut,Coord_x+2*Width+3,Coord_y+2); cout << "分數 : " << B.score; C.gotoxy(hOut,Coord_x+2*Width+3,Coord_y+4); cout << "速度 : " << B.block_speed << "ms"; } void Block::clear_Block(HANDLE hOut) { for(int i = 0;i < 4; i++) { block[i] = 0; } B.make_block(); for(int i = B.x-2; i <= B.x+4; i +=2) { for(int j = B.y-2;j <= B.y+1; j++) { if(B.patten_mark[i][j] == 0 && j > Coord_y && j < Coord_y + Height) { C.gotoxy(hOut,i,j); cout << " "; } } } } void Block::if_full(HANDLE hOut) { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); int block_count, delete_block_num = 0; //block_count記錄某行方塊的個數,delete_block_num記錄刪除方塊的行數的變數 for(int j = Coord_y+Height-1;j >= Coord_y+1; j--) { block_count = 0; for(int i = Coord_x+2;i < Coord_x+2*Width-2; i += 2) { if(B.patten_mark[i][j] == 1) { block_count++; if(block_count == Width-2) { for(block_count = Coord_x+2; block_count < Coord_x+2*Width-2; block_count += 2) { B.patten_mark[block_count][j] = 0; C.gotoxy(hOut,block_count,j); cout << " "; Sleep(0); } for(block_count = j-1;block_count > Coord_y; block_count--) { for(i = Coord_x+2;i < Coord_x+2*Width-2; i += 2) { if(B.patten_mark[i][block_count] == 1) { B.patten_mark[i][block_count]=0; C.gotoxy(hOut,i,block_count); cout << " "; B.patten_mark[i][block_count+1]=1; C.gotoxy(hOut,i,block_count+1); SetConsoleTextAttribute(handle,FOREGROUND_INTENSITY |FOREGROUND_GREEN); cout << "■"; } } } j++; delete_block_num++; } } } } B.score += 100 * delete_block_num; if(delete_block_num > 0 && (B.score%1000 == 0 || B.score / 1000 > B.level - 1 )) { block_speed_temp -= 20; B.level++; } } void Console::start_game() { HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE); int temp,temp1,temp2; char ch; while(1) { B.get_flag(); temp = B.flag; B.x = Coord_x + 2 * Width + 6; B.y = Coord_y + 10; B.flag = B.next_flag; B.output_block(hOut); B.x = Coord_x + Width; B.y = Coord_y - 1; B.flag = temp; while(1) { Loop: B.output_block(hOut); Sleep(B.block_speed); B.clear_Block(hOut); temp1 = B.x; temp2 = B.flag; if(kbhit()) { ch = getch(); if(ch == 97) { B.x -= 2; } if(ch == 100) { B.x += 2; } if(ch == 115) { B.block_speed = 0; } if(ch == 119) //加一取餘實現旋轉 { if(B.flag >= 2 && B.flag <= 3) { B.flag++; B.flag %= 2; B.flag += 2; } if(B.flag >= 4 && B.flag <= 7) { B.flag++; B.flag %= 4; B.flag += 4; } if(B.flag >= 8 && B.flag <= 11) { B.flag++; B.flag %= 4; B.flag += 8; } if(B.flag >= 12 && B.flag <= 15) { B.flag++; B.flag %= 4; B.flag += 12; } if(B.flag >= 16 && B.flag <= 19) { B.flag++; B.flag %= 4; B.flag += 16; } if(B.flag >= 20 && B.flag <= 23) { B.flag++; B.flag %= 4; B.flag += 20; } } if(ch == 27) { C.end_game(); } if(ch == ' ') { B.output_block(hOut); while(1) { if(kbhit()) { ch = getch(); if(ch == 32) { goto Loop; } } } } if(B.if_move() == 0) { B.x = temp1; B.flag = temp2; } else { goto Loop; } } B.y++; if(B.if_move() == 0) { B.y--; B.output_block(hOut); B.if_full(hOut); B.block_speed = B.block_speed_temp; break; } } for(int i = B.y-2;i < B.y+2; i++) { if(i == Coord_y) { C.end_game(); } } B.flag = B.next_flag; B.x = Coord_x + 2 * Width + 6; B.y = Coord_y + 10; B.clear_Block(hOut); } } int main() { C.enter_game(); return 0; }