# 小專題4 Tetris 烏克蘭方塊 ## 開頭 5秒後開始 ![](https://i.imgur.com/wkkpBlN.jpg) ```c printf(" .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. \n"); printf("| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | \n"); printf("| | _________ | || | _________ | || | _________ | || | _______ | || | _____ | || | _______ | | \n"); printf("| | | _ _ | | || | |_ ___ | | || | | _ _ | | || | |_ __ \\ | || | |_ _| | || | / ___ | | | \n"); printf("| | |_/ | | \\_| | || | | |_ \\_| | || | |_/ | | \\_| | || | | |__) | | || | | | | || | | (__ \\_| | | \n"); printf("| | | | | || | | _| _ | || | | | | || | | __ / | || | | | | || | '.___`-. | | \n"); printf("| | _| |_ | || | _| |___/ | | || | _| |_ | || | _| | \\ \\_ | || | _| |_ | || | |`\\____) | | | \n"); printf("| | |_____| | || | |_________| | || | |_____| | || | |____| |___| | || | |_____| | || | |_______.' | | \n"); printf("| | | || | | || | | || | | || | | || | | | \n"); printf("| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | \n"); printf(" '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' \n"); sleep(5); ``` ## 增加功能 ### 1.space 按空白鍵直接到底 ```c case 32: while(isCollision(cur_x,cur_y+1)!=1) { eraseBlock(block_cur,cur_x,cur_y); cur_y++; printBlock(block_cur,cur_x,cur_y); } break; ``` ### 2.整版變色 ```c case O: system("color 01"); copy_block(blockO,block_cur); break; case J: system("color 02"); copy_block(blockJ,block_cur); break; . . . ``` 七種顏色 #### 1.O ![](https://i.imgur.com/AmdqPs8.jpg) #### 2.J ![](https://i.imgur.com/hgLRDGM.jpg) #### 3.L ![](https://i.imgur.com/5a7nzQ7.jpg) #### 4.I ![](https://i.imgur.com/3yEvcuA.jpg) #### 5.Z ![](https://i.imgur.com/HMM7NFy.jpg) #### 6.S ![](https://i.imgur.com/Jq1KVT2.jpg) #### 7.T ![](https://i.imgur.com/q5iuKkp.jpg) ### 3.分數 削掉一條+10分 ```c clear_line++; score += 10; ``` ![](https://i.imgur.com/JNTNXYM.jpg) ## 完整程式碼 ```c #include <stdio.h> #include <windows.h> #include <stdlib.h> #include <time.h> #include <unistd.h> #include <conio.h> #define HEIGHT 14 #define WIDTH 18 #define block_h 4 #define block_w 4 HANDLE hand; int cur_x,cur_y; int block_cur[block_h][block_w]={0}; int screen[HEIGHT][WIDTH]={0}; int blockO[block_h][block_w]={ {0,0,0,0}, {0,1,1,0}, {0,1,1,0}, {0,0,0,0} }; int blockL[block_h][block_w]={ {0,1,0,0}, {0,1,0,0}, {0,1,1,0}, {0,0,0,0} }; int blockJ[block_h][block_w]={ {0,0,1,0}, {0,0,1,0}, {0,1,1,0}, {0,0,0,0} }; int blockI[block_h][block_w]={ {0,1,0,0}, {0,1,0,0}, {0,1,0,0}, {0,1,0,0} }; int blockZ[block_h][block_w]={ {0,0,0,0}, {1,1,0,0}, {0,1,1,0}, {0,0,0,0} }; int blockS[block_h][block_w]={ {0,0,0,0}, {0,1,1,0}, {1,1,0,0}, {0,0,0,0} }; int blockT[block_h][block_w]={ {0,0,0,0}, {1,1,1,0}, {0,1,0,0}, {0,0,0,0} }; enum block_type{ O,J,L,I,Z,S,T }; int block_type_num = 7; int score=0; int clear_line = 0; int tm = 800; UINT_PTR timerId; void setCursorVisible(int v){ CONSOLE_CURSOR_INFO info={1, v};//size1-100 v bool SetConsoleCursorInfo(hand, &info); } void gotoxy(int x, int y){ COORD pos={.X=x, .Y=y}; SetConsoleCursorPosition(hand, pos); } static void set_timer(int t){ KillTimer(NULL, timerId); timerId = SetTimer(NULL,0,t,NULL); } static void close_timer(){ KillTimer(NULL, timerId); } void printxy(char c, int x, int y){ gotoxy(x, y); printf("%c",c); } void printScreen(){ int i,j; for(i=0;i<WIDTH;i++){ printxy('E',i+6,1); printxy('E',i+6,2+HEIGHT); } for(j=-1;j<HEIGHT+1;j++){ printxy('E',5,j+2); printxy('E',6+WIDTH,j+2); } for(i=0;i<WIDTH;i++){ for(j=0;j<HEIGHT;j++){ if(screen[j][i]==0){ printxy(' ',i+6,j+2); } else{ printxy('O',i+6,j+2); } } } gotoxy(30,12); printf("shift left : <-"); gotoxy(30,14); printf("shift right : ->"); gotoxy(30,16); printf("rotate : up"); gotoxy(30,18); printf("lower : down"); gotoxy(30,20); printf("bace : space"); gotoxy(0,20); printf("score:%d\n",score); printf("clearn_line:%d\n",clear_line); } void printBlock(int block[][block_w],int x,int y){ int i,j; for(i=0;i<block_h;i++){ for(j=0;j<block_w;j++){ if(block[i][j]==1){ printxy('O',x+6+j,y+2+i); } } } } void eraseBlock(int block[][block_w],int x,int y){ int i,j; for(i=0;i<block_w;i++){ for(j=0;j<block_h;j++){ if(block[i][j]==1){ printxy(' ',x+6+j,y+2+i); } } } } int get_block_y_fill(int row){ int ans=0; for(int col=0;col<block_w;col++){ if(block_cur[row][col]==1){ ans=1; } } return ans; } int get_block_x_fill(int col){ int ans=0; for(int row=0;row<block_w;row++){ if(block_cur[row][col]==1){ ans=1; } } return ans; } void get_block_left_right_margin(int *left_margin ,int *right_margin){ for(int col=0;col<2;col++){ if(get_block_x_fill(col)==0){ *left_margin=*left_margin+1; } } for(int col=2;col<4;col++){ if(get_block_x_fill(col)==0){ *right_margin=*right_margin+1; } } return ; } void get_block_top_button_margin(int *top_margin ,int *button_margin){ for(int row=0;row<2;row++){ if(get_block_y_fill(row)==0){ *top_margin=*top_margin+1; } } for(int row=2;row<4;row++){ if(get_block_y_fill(row)==0){ *button_margin=*button_margin+1; } } } int isCollision(int x , int y){ int top_margin=0,button_margin=0,left_margin=0,right_margin=0; get_block_top_button_margin(&top_margin,&button_margin); get_block_left_right_margin(&left_margin,&right_margin); if(x<0-left_margin || y<0-top_margin || x>WIDTH-block_w+right_margin || y>HEIGHT-block_h+button_margin){ return 1; } int w,h; for(w=0;w<block_w;w++){ for(h=0;h<block_h;h++){ if(block_cur[h][w]==1){ if(screen[y+h][x+w]==1){ return 1; } } } } return 0; } int is_line_fill(int h){ int w; for(w=0;w<WIDTH;w++){ if(screen[h][w]==0){ return 0; } } return 1; } void clear_one_line(int h){ int w,row; for(row = h;row>0;row--){ for(w=0;w<WIDTH;w++){ screen[row][w] = screen[row-1][w]; } } for(w=0;w<WIDTH;w++){ screen[0][w] = 0; } clear_line++; score += 10; } void check_line(){ int total_line = 0; int h; for(h=cur_y;h<HEIGHT;h++) { if(is_line_fill(h)==1) { clear_one_line(h); printScreen(); total_line++; } } } void land_block(){ int w,h; for(w=0;w<block_w;w++){ for(h=0;h<block_h;h++){ if(block_cur[h][w]==1){ screen[cur_y+h][cur_x+w]=1; } } } } void copy_block(int block_s[][block_w],int block_d[][block_w]){ int w,h; for(w=0;w<block_w;w++){ for(h=0;h<block_h;h++){ block_d[h][w] = block_s[h][w]; } } } void rotate_block(){ int temp[block_h][block_w] = {0}; copy_block(block_cur,temp); int w,h; for(w=0;w<block_w;w++){ for(h=0;h<block_h;h++){ block_cur[h][w] = temp[w][block_h-1-h]; } } } void make_new_block(){ enum block_type type = (int)(rand() % block_type_num); switch(type){ case O: system("color 01"); copy_block(blockO,block_cur); break; case J: system("color 02"); copy_block(blockJ,block_cur); break; case L: system("color 03"); copy_block(blockL,block_cur); break; case I: system("color 04"); copy_block(blockI,block_cur); break; case Z: system("color 05"); copy_block(blockZ,block_cur); break; case S: system("color 06"); copy_block(blockS,block_cur); break; case T: system("color 07"); copy_block(blockT,block_cur); break; default: break; } cur_x = (WIDTH-block_w)/2; cur_y = 0; printBlock(block_cur,cur_x,cur_y); } void move_block_down(){ if(isCollision(cur_x,cur_y+1)!=1){ eraseBlock(block_cur,cur_x,cur_y); cur_y++; printBlock(block_cur,cur_x,cur_y); } else{ land_block(); check_line(); make_new_block(); printBlock(block_cur,cur_x,cur_y); if(isCollision(cur_x,cur_y)==1){ close_timer(); } } } void key_control(){ MSG msg; while(1){ if(PeekMessage(&msg,NULL,WM_TIMER,WM_TIMER,PM_REMOVE)!=0){//如果timer的倒數結束,會發訊息到這裡 move_block_down(); } if(kbhit()!=0){ char ch=getch(); switch(ch){ case 72://up eraseBlock(block_cur,cur_x,cur_y); rotate_block(); if(isCollision(cur_x,cur_y)==1) { rotate_block(); rotate_block(); rotate_block(); } printBlock(block_cur,cur_x,cur_y); break; case 80://down if(isCollision(cur_x,cur_y+1)!=1){ eraseBlock(block_cur,cur_x,cur_y); cur_y++; printBlock(block_cur,cur_x,cur_y); } break; case 75://left if(isCollision(cur_x-1,cur_y)!=1){ eraseBlock(block_cur,cur_x,cur_y); cur_x--; printBlock(block_cur,cur_x,cur_y); } break; case 77://right if(isCollision(cur_x+1,cur_y)!=1){ eraseBlock(block_cur,cur_x,cur_y); cur_x++; printBlock(block_cur,cur_x,cur_y); } break; case 32: while(isCollision(cur_x,cur_y+1)!=1) { eraseBlock(block_cur,cur_x,cur_y); cur_y++; printBlock(block_cur,cur_x,cur_y); } break; } } } } int main(){ printf(" .----------------. .----------------. .----------------. .----------------. .----------------. .----------------. \n"); printf("| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. || .--------------. | \n"); printf("| | _________ | || | _________ | || | _________ | || | _______ | || | _____ | || | _______ | | \n"); printf("| | | _ _ | | || | |_ ___ | | || | | _ _ | | || | |_ __ \\ | || | |_ _| | || | / ___ | | | \n"); printf("| | |_/ | | \\_| | || | | |_ \\_| | || | |_/ | | \\_| | || | | |__) | | || | | | | || | | (__ \\_| | | \n"); printf("| | | | | || | | _| _ | || | | | | || | | __ / | || | | | | || | '.___`-. | | \n"); printf("| | _| |_ | || | _| |___/ | | || | _| |_ | || | _| | \\ \\_ | || | _| |_ | || | |`\\____) | | | \n"); printf("| | |_____| | || | |_________| | || | |_____| | || | |____| |___| | || | |_____| | || | |_______.' | | \n"); printf("| | | || | | || | | || | | || | | || | | | \n"); printf("| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' || '--------------' | \n"); printf(" '----------------' '----------------' '----------------' '----------------' '----------------' '----------------' \n"); sleep(5); system("cls"); hand=GetStdHandle(STD_OUTPUT_HANDLE); srand(time(NULL)); setCursorVisible(0); set_timer(tm); int i,j; for(i=0;i<WIDTH;i++){ for(j=0;j<HEIGHT;j++){ screen[j][i]=0; } } printScreen(); make_new_block(); key_control(); return 0; } ```