俄罗斯方块,C语言源文件,带有详细的注释
生活随笔
收集整理的這篇文章主要介紹了
俄罗斯方块,C语言源文件,带有详细的注释
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
為了方便在其它程序中測試,將方塊的功能包裝成了一個類,下面是頭文件Tetris.h的內容?
歡迎測試并提出寶貴意見,其中有個bug不知到怎么回事,有時落下的方塊沒顯示
//俄羅斯方塊C++語言源代碼,vs2019編譯通過 #pragma once #include <stdio.h> #include <Windows.h> #include <stdlib.h> #include <time.h> #include <conio.h> #include <string.h> #include <math.h> //游戲區大小 #define ROW 29 //游戲區行數,建議不小于29,否則亂屏 #define COL 20 //游戲區列數 //鍵碼 #define SPACE 32 //空格鍵 #define ESC 27 //Esc鍵 //四個方向鍵控制方塊姿態,方便習慣右手操作的用戶 #define LEFT 75 #define RIGHT 77 #define DOWN 80 #define UP 72 //用于旋轉方塊 //其它 #define LenofName 11 struct Face {int data[ROW][COL + 20] = { 0 }; //用于標記指定位置是否有方塊(1為有,0為無)int color[ROW][COL + 20] = { 0 }; //用于記錄指定位置的方塊顏色編碼 };struct Block//用于存儲7種基本形狀方塊的各自的4種形態的信息,共28種 {int space[4][4] = { 0 }; }; //游戲得分數據 typedef struct Data {char user[LenofName];int hisScore;int hisGrade;//寫完了發現這個數沒意義,因為可以通過hisScore計算得到int max;Face history; }DATA; class Tetris { private:int lines;//記錄消去的行數,控制得分權值int disScore;//屏顯分數int forceGrade;//強制等級int grade;//等級int difficulty;//下落刷新時間,單位msFace face;Block block[7][4];DATA data;//設置方塊大小void SetFont(int size = 20);//重新開始的清理工作void Restart();//配置運行環境void ConfigEnvironment();//光標跳轉void CursorJump(int x, int y);//初始化界面void InitInterface();//初始化方塊信息void InitBlockInfo();//顏色設置void color(int num);//畫出方塊void DrawBlock(int shape, int form, int x, int y);//空格覆蓋void DrawSpace(int shape, int form, int x, int y);//合法性判斷int IsLegal(int shape, int form, int x, int y);//判斷得分與結束int JudeFunc();//游戲記錄DATA ReadGrade();//更新最高分到文件int WriteGrade(DATA);//根據得分調整下落速度int AdjustDifficulty();//刷新游戲燈牌void Display(); public:Tetris();int StartGame(); };類中函數的實現部分,文件名Tetris.app
#include "Tetris.h"#pragma warning (disable:4996) //消除警告,兼容舊版本庫文件Tetris::Tetris() {//通過構造函數完成初始化lines = 1;disScore =0;forceGrade = 0;data = ReadGrade();grade = data.hisGrade;//延續上次的等級difficulty = AdjustDifficulty();//重新計算下落時間ConfigEnvironment();SetFont();InitInterface();InitBlockInfo();}//配置運行窗口void Tetris:: ConfigEnvironment() {system("chcp 936");//設置utf-8字符集65001,GBK字符集936,如果亂碼才需要更改//設置標題char cmd[60];sprintf(cmd, "title 俄羅斯方塊:%s", data.user);//含變量的DOS命令,序列化到字符中再傳遞system(cmd);//設置cmd窗口的大小sprintf(cmd,"mode con lines=%d cols=%d" ,ROW, 2*COL+40);//改變ROW,COL時窗口自動調整大小system(cmd);//設置隨機數起點,每次啟動,游戲會有不同的開局srand((unsigned int)time(NULL));//隱藏光標CONSOLE_CURSOR_INFO curInfo; //光標結構體變量curInfo.dwSize = 1; //如果沒賦值的話,隱藏光標無效curInfo.bVisible = FALSE; //可見為TRUEHANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //獲取標準輸出句柄 SetConsoleCursorInfo(handle, &curInfo); //設置光標信息//游戲界面最大化會破壞布局,禁用最大化HWND hwnd = GetConsoleWindow();HMENU hmenu = GetSystemMenu(hwnd, false); // 復制或修改而訪問窗口菜單RemoveMenu(hmenu, SC_MAXIMIZE, MF_BYCOMMAND); // 從指定菜單刪除一個菜單項或分離一個子菜單DrawMenuBar(hwnd);//去除最大化菜單}//設置字體,一是美觀,二是控制方塊大小,太小的方塊玩起來太累//雖然可以游戲啟動后手動調節字體,但是為了具有良好游戲體驗,直接設好吧void Tetris::SetFont(int size) {//默認大小為20號字,傳入參數可以改變字體及方塊大小CONSOLE_FONT_INFOEX cfi;//控制臺字體信息的結構體cfi.cbSize = sizeof(CONSOLE_FONT_INFOEX);cfi.nFont = 0;cfi.dwFontSize.X = 0;cfi.dwFontSize.Y = size; //設置字體大小cfi.FontFamily = FF_DONTCARE;cfi.FontWeight = FW_NORMAL; //字體粗細 FW_BOLDwcscpy_s(cfi.FaceName, L"隸書"); //設置字體,必須是控制臺已有的SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi);//根據結構體內容改變字體}//重新開始void Tetris::Restart() {//清空游戲區方塊for (int i = 0; i < ROW-1; i++) {for (int j = 2; j < 2*COL - 2; j+=2) {CursorJump(j, i);printf(" ");//兩個空格填充一個方塊}}//清除當前分數disScore = 0;forceGrade = 0;grade = 0;//游戲速度降到最低,不再延續以前的速度繼續CursorJump(2 * COL + 22, 16);printf(" ");//這里可能寫了字,清除掉Display();//刷新游戲燈牌//清除已落下的方塊for (int i = 0; i < ROW-1; i++) {for (int j = 1; j < COL - 1; j++) {face.data[i][j] = 0;face.color[i][j] = 0;}}return;} //光標跳轉 void Tetris::CursorJump(int x, int y) {COORD pos; //光標位置的結構體變量pos.X = x; //橫坐標pos.Y = y; //縱坐標HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //獲取控制臺句柄SetConsoleCursorPosition(handle, pos); //設置光標位置 } //刷新游戲燈牌 void Tetris:: Display() {color(7);//白色int g = grade < forceGrade ? forceGrade:grade ;//高等級優先CursorJump(2 * COL + 31, 6);//光標要跳到正確位置再修改相應內容printf("%d", g);CursorJump(2 * COL + 23, 8);int i=0;for (; i <= g; i++) {//顯示一個看似酷炫的速度進度條color(0xae);//被景綠色,前景黃色printf(">");}for (; i <= 9; i++) {color(0x80);//灰色背景printf(" ");}color(7);//改回白色CursorJump(2 * COL + 31, 12);printf("%-5d", disScore);CursorJump(2 * COL + 31, 14);difficulty = AdjustDifficulty();printf("%-4dms", difficulty); } //初始化界面 void Tetris::InitInterface() {color(0x38); //邊框顏色for (int i = 0; i < ROW; i++){for (int j = 0; j < COL + 20; j++){if (j == 0 || j == COL - 1 || j == COL + 9||j==COL+19)//豎線位置{face.data[i][j] = 1; //標記該位置有方塊CursorJump(2 * j, i);printf("◆");}else if (i == ROW - 1){face.data[i][j] = 1;printf("◆");}elseface.data[i][j] = 0;}}for (int i = COL; i < COL + 10; i++)//左欄橫線{face.data[8][i] = 1; CursorJump(2 * i, 8);printf("◆");}for (int i = COL+10; i < COL + 20; i++)//右欄橫線{face.data[18][i] = 1; CursorJump(2 * i, 18);printf("◆");}color(7);//操作說明文字設置為白色CursorJump(2 * COL+4, 1);printf("下一個方塊");CursorJump(2 * COL + 4, ROW - 19);printf("左移:A←");CursorJump(2 * COL + 4, ROW - 17);printf("右移:F→");CursorJump(2 * COL + 4, ROW - 15);printf("加速:D ↓");CursorJump(2 * COL + 4, ROW - 13);printf("旋轉:空格↑");CursorJump(2 * COL + 4, ROW - 11);printf("暫停: S");CursorJump(2 * COL + 4, ROW - 9);printf("退出: esc");CursorJump(2 * COL + 4, ROW - 7);printf("重新開始:R");CursorJump(2 * COL + 2, ROW-5);printf("繼續上次游戲:C");CursorJump(2 * COL + 2, ROW-3);printf("更換新用戶名:U");//游戲燈牌CursorJump(2 * COL + 22, 2);printf("直接跳級提速");CursorJump(2 * COL + 22, 4);printf("請選擇:0--9");CursorJump(2 * COL + 22, 6);printf("當前等級:%d",grade);CursorJump(2 * COL + 22, 10);printf("最高紀錄:%-5d", data.max);//估計玩到大于10萬分就覺得沒意思了,所以5位數寬度就夠了CursorJump(2 * COL + 22, 12);printf("當前分數:%-5d", disScore);CursorJump(2 * COL + 22, 14);difficulty = AdjustDifficulty();printf("下落速度:%-4dms", difficulty);Display();//畫一下進度條 //打印游戲說明CursorJump(2 * COL + 21, 20);printf("將方塊壘整齊得分");CursorJump(2 * COL + 21, 21);printf("連續消多行多得分");CursorJump(2 * COL + 21, 23);printf("中途保存可按esc");CursorJump(2 * COL + 21, 24);printf("游戲結束不會保存");CursorJump(2 * COL + 21, 25);printf("根據你的分數速度");CursorJump(2 * COL + 21, 26);printf("只能提速不能降速"); } //初始化方塊信息 void Tetris::InitBlockInfo()//7種方塊28種形態預先存入數組,供顯示使用 {//“T”形for (int i = 0; i <= 2; i++)block[0][0].space[1][i] = 1;block[0][0].space[2][1] = 1;//“L”形for (int i = 1; i <= 3; i++)block[1][0].space[i][1] = 1;block[1][0].space[3][2] = 1;//“J”形for (int i = 1; i <= 3; i++)block[2][0].space[i][2] = 1;block[2][0].space[3][1] = 1;for (int i = 0; i <= 1; i++){//“Z”形block[3][0].space[1][i] = 1;block[3][0].space[2][i + 1] = 1;//“S”形block[4][0].space[1][i + 1] = 1;block[4][0].space[2][i] = 1;//“O”形block[5][0].space[1][i + 1] = 1;block[5][0].space[2][i + 1] = 1;}//“I”形for (int i = 0; i <= 3; i++)block[6][0].space[i][1] = 1;int temp[4][4];for (int shape = 0; shape < 7; shape++) //7種形狀{for (int form = 0; form < 3; form++) //4種形態,已經有了一種,每個還需增加3種{//獲取第form種形態for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){temp[i][j] = block[shape][form].space[i][j];}}//將第form種形態順時針旋轉,得到第form+1種形態for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){block[shape][form + 1].space[i][j] = temp[3 - j][i];}}}} } //顏色設置 void Tetris::color(int c) {//c可以用兩位十六進制數表示,高位為背景色,低位為前景色,也可以寫轉換后的10進制數switch (c){case 0:c = 13; //“T”形方塊設置為紫色break;case 1:case 2:c = 12; //“L”形和“J”形方塊設置為紅色break;case 3:case 4:c = 10; //“Z”形和“S”形方塊設置為綠色break;case 5:c = 14; //“O”形方塊設置為黃色break;case 6:c = 11; //“I”形方塊設置為淺藍色break;case 7:c = 7; //文字設置為白色break;default:c=c;//默認根據色碼設定}SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //調用API設置顏色 } //畫出方塊 void Tetris::DrawBlock(int shape, int form, int x, int y) {for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (block[shape][form].space[i][j] == 1) //如果該位置有方塊{CursorJump(2 * (x + j), y + i); //光標跳轉到指定位置printf("■"); //輸出方塊}}} } //空格覆蓋 void Tetris::DrawSpace(int shape, int form, int x, int y) {for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (block[shape][form].space[i][j] == 1) //如果該位置有方塊{CursorJump(2 * (x + j), y + i); printf(" "); //兩個空格占用一個方塊的位置}}} } //合法性判斷 int Tetris::IsLegal(int shape, int form, int x, int y) {for (int i = 3; i >=0; i--)//從方塊下沿開始判斷,可能少循環幾次,提高一點點性能{for (int j = 0; j <4; j++){//如果方塊落下的位置本來就已經有方塊了,則不合法if ((block[shape][form].space[i][j] == 1) && (face.data[y + i][x + j] == 1))return 0; //不合法}}return 1; //合法 } //調整游戲難度 int Tetris::AdjustDifficulty() {int t;//這里t越小,方塊下落越快,根據得分調整游戲難度int score;if (forceGrade > grade) {//有強制提速score = disScore % 1000 + forceGrade * 1000;}else {//根據等級設置速度,防止速度正反饋score = disScore % 1000 + grade * 1000;}if (score < 9000) {t = 1000 - sqrt(score)*9.4;//非線性調整}else {t = 100;//極限挑戰,只加分不提速,如果感覺難度不算極限,可以改小一點}return t; } //從文件讀取數據 DATA Tetris::ReadGrade() {DATA d;FILE* pf = fopen("record.dat", "r"); //以只讀方式打開文件if (pf == NULL) //第一次運行無此文件{//創建一個具有初始數據的新文件strcpy(d.user, "古老的經典\0");d.hisScore = 0;d.hisGrade = 0;d.max = 0;for (int i = 0; i < ROW; i++)//初始化face再保存{for (int j = 0; j < COL + 20; j++){if (j == 0 || j == COL - 1 || j == COL + 9 || j == COL + 19){face.data[i][j] = 1; //標記該位置有方塊 }else if (i == ROW - 1){face.data[i][j] = 1;//最下面一行全是方塊 }elseface.data[i][j] = 0; //一個方塊都沒落下}}d.history = face;//防止第一次運行就試圖繼續上次游戲,會造成方塊掉入無底深淵pf = fopen("record.dat", "w"); //自動創建該文件if (pf == NULL) {//創建文件失敗CursorJump(COL, ROW / 2);printf("你的存儲介質為只讀類型,無法創建游戲數據文件");CursorJump(COL, ROW / 2+2);printf("按任意鍵繼續進入游戲……");system("pause>nul");}else {fwrite(&d, sizeof(DATA), 1, pf);}}else {fseek(pf, 0, SEEK_SET); //使文件指針pf指向文件開頭fread(&d, sizeof(DATA), 1, pf); //讀取文件中的數據fclose(pf); //關閉文件pf = NULL; //防止內存泄露}return d;//讀取失敗游戲也可以玩,因為d被初始化了 } //保存得分記錄 int Tetris::WriteGrade(DATA d) {FILE* pf = fopen("record.dat", "w");if (pf == NULL) {CursorJump(COL, ROW / 2 + 4);printf("保存游戲數據失敗,record.dat文件為只讀或存儲介質為只讀");CursorJump(COL, ROW / 2 + 6);printf("按任意鍵直接退出……");system("pause>nul");return 1;}else{fwrite(&d, sizeof(DATA), 1, pf);fclose(pf); pf = NULL; }return 0; } //判斷是否得分 int Tetris::JudeFunc() {for (int i = ROW - 2; i > 4; i--)//最底層開始判斷{int sum = 0; //記錄第i行的方塊個數for (int j = 1; j < COL - 1; j++){sum += face.data[i][j]; //統計第i行的方塊個數}if (sum == 0) {break;//最后一行沒有方塊,無需再判斷其上的層次}else if (sum == COL - 2) //該行全是方塊,可得分{disScore += 10 * lines * lines; //根據一次性得分行數加分for (int j = 1; j < COL - 1; j++) //清除整行的方塊{face.data[i][j] = 0; //標記為無方塊既被清除}//把被清除行上面的行整體向下挪一格for (int m = i; m > 1; m--){sum = 0; //記錄上一行的方塊個數for (int n = 1; n < COL - 1; n++){sum += face.data[m - 1][n]; //統計上一行的方塊個數face.data[m][n] = face.data[m - 1][n]; //將上一行方塊的標識移到下一行face.color[m][n] = face.color[m - 1][n]; //將上一行方塊的顏色編號移到下一行if (face.data[m][n] == 1) //上一行移下來的是方塊,打印方塊{CursorJump(2 * n, m); //光標跳轉到該位置color(face.color[m][n]); //顏色設置為原方塊的顏色printf("■"); //打印方塊}else //上一行移下來的是空格,打印空格{CursorJump(2 * n, m); //光標跳轉到該位置printf(" "); //打印空格(兩個空格)}}//上一行移下來的全是空格,無需再將上層的方塊向下移動(移動結束)if (sum == 0)return 1; //移動下來的可能還有滿行,還需調用該函數進行判斷 }}}lines = 1;//重置連續消掉的行數return 0; //返回值用于結束調用者的死循環 } //游戲主體邏輯函數 int Tetris::StartGame(){clock_t start, end=clock();//用于計時char ch;int gameover = 0;int nextShape,nextForm;int x, y;//方塊坐標int shape = rand() % 7, form = rand() % 4; //隨機獲取方塊的形狀和形態while (1){//主循環,用于不斷產生新的方塊nextShape = rand() % 7, nextForm = rand() % 4; //隨機獲取下一個方塊的形狀和形態x = COL / 2 - 2,y = 0;//初始位置color(nextShape); //顏色設置為下一個方塊的顏色DrawBlock(nextShape, nextForm, COL + 3, 3); //將下一個方塊顯示在右上角//下落循環,控制方塊不斷下落while (1){color(shape); //顏色設置為當前正在下落的方塊DrawBlock(shape, form, x, y); //將該方塊顯示在初始下落位置start = clock();//計時開始while (kbhit()) {//下落過程中不斷檢測鍵盤是否有動作,用于控制方塊ch = getch(); //讀取keycodeswitch (ch){case 'd': case 'D':case DOWN://方向鍵:下if (IsLegal(shape, form, x, y + 1)==1) //判斷方塊向下移動一位后是否合法{DrawSpace(shape, form, x, y); //用空格覆蓋當前方塊所在位置y++; //下一次顯示方塊時就相當于下落了一格了DrawBlock(shape, form, x, y);//及時重畫該方塊}break;case 'a': //方便左手操作case 'A':case LEFT://方向鍵:左,方便右手操作if (IsLegal(shape, form, x - 1, y) == 1) {DrawSpace(shape, form, x, y); x--;DrawBlock(shape, form, x, y);}break;case 'f': case 'F':case RIGHT://方向鍵:右if (IsLegal(shape, form, x + 1, y) == 1) {DrawSpace(shape, form, x, y); x++; DrawBlock(shape, form, x, y);}break;case SPACE: //空格鍵case UP://方向,上if (IsLegal(shape, (form + 1) % 4, x, y) == 1){DrawSpace(shape, form, x, y); form = (form + 1) % 4;DrawBlock(shape, form, x, y);}break;case 's'://暫停case 'S':CursorJump(2 * COL + 4, ROW - 11);printf("%-10s", "任意鍵繼續");//讓用戶知道自己暫停了system("pause>nul"); //按任意鍵繼續color(7);CursorJump(2 * COL + 4, ROW - 11);printf("%-10s","暫停: S");//恢復運行后,將操作提示寫回去break;case 'r'://重新開始case 'R':Restart();break;case ESC: //esc鍵system("cls"); //清空屏幕color(7);CursorJump(COL, ROW / 2);printf("確認要保存游戲并退出嗎?(y/n):");CursorJump(COL, ROW / 2-4);printf("不想保存直接退出請再次按esc");while (1) {//必須做出正確選擇ch = getch();if (ch == 'y' ||ch== 'Y') {//同意保存退出if (disScore > data.max) { data.max = disScore; }data.hisScore = disScore;data.hisGrade = grade;data.history = face;//保存現場WriteGrade(data);return 1;//結束所有循環,返回主程序}else if (ch == 'n' || ch == 'N') {system("cls");//保護現場Face tempFace=face;InitInterface();//重畫界面會清除數據face = tempFace;//恢復現場for (int i = 1; i < ROW - 1; i++) {for (int j = 1; j < COL - 1; j++) {if (face.data[i][j] == 1) {CursorJump(2*j,i);color(face.color[i][j]); //顏色設置為原方塊的顏色printf("■"); //打印方塊}}}DrawBlock(nextShape, nextForm, COL + 3, 3);//畫出下一個方塊break;//結束讀取循環}else if (ch == ESC) {return 1;//相當于雙擊esc直接退出游戲}else {Beep(500,500);//輸入錯誤發出提示音}}break;case 'U'://改名操作case 'u': {CursorJump(2 * COL + 22, 16);printf("姓名:");CursorJump(2 * COL + 27, 16);color(8);printf("最多五個字");color(7);CursorJump(2 * COL + 27, 16);//顯示光標CONSOLE_CURSOR_INFO curInfo; curInfo.dwSize = 1;curInfo.bVisible = true;HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleCursorInfo(handle, &curInfo);char cmd[600];//如果非要輸入大于這個數的字符串也溢出scanf("%s", cmd);if (strlen(cmd)<LenofName) {//處理一下用戶名溢出strcpy(data.user, cmd);sprintf(cmd, "title 俄羅斯方塊當前用戶:%s", data.user);system(cmd);//把你的名字寫在標題欄,裝酷WriteGrade(data);}else {CursorJump(13, ROW/2);printf("你的名字太長了");}//隱藏光標curInfo.bVisible = false;SetConsoleCursorInfo(handle, &curInfo);CursorJump(2 * COL + 22, 16);//回到起始位置,擦掉剛才寫的字printf(" ");break;}case 'C'://繼續上次游戲case 'c':Face temFace=face;system("cls"); //清空屏幕CursorJump(COL, ROW / 2);color(7);printf("確認要恢復上次游戲繼續玩嗎?(y/任意鍵繼續當前游戲):");ch = getch();if (ch == 'y' || ch == 'Y') {system("cls");data=ReadGrade();disScore = data.hisScore;grade = data.hisGrade;forceGrade = 0;//恢復時沒有強制提速InitInterface();face = data.history;difficulty = AdjustDifficulty();//恢復游戲速度Display();}else {//誤操作時繼續system("cls");InitInterface();face = temFace;}//恢復現場for (int i = 1; i < ROW - 1; i++) {for (int j = 1; j < COL - 1; j++) {if (face.data[i][j] == 1) {CursorJump(2 * j, i);color(face.color[i][j]); //顏色設置為原方塊的顏色printf("■"); //打印方塊}}}DrawBlock(nextShape, nextForm, COL + 3, 3);//畫出下一個方塊break;}//越級調整游戲難度,既方塊下落速度if (ch >= '0' && ch <= '9') {int g=ch-'0';//起步速度為上次最高得分的速度,想降速,根據本局得分確定可以將到的最低速度if (g>=grade) {//速度選擇正確forceGrade = g;difficulty = AdjustDifficulty();Display();}else{//給點提示,為什么不讓降速CursorJump(2 * COL + 22, 16);printf("堅持!別走回頭路");Beep(500, 500);}}}if (start-end>=difficulty) //下落時間到達{if (IsLegal(shape, form, x, y + 1)==1) //可以下落{DrawSpace(shape, form, x, y); y++; DrawBlock(shape, form, x, y);}else if(IsLegal(shape, form, x, y + 1) == 0)//不再下落{//face:記錄界面的每個位置是否有方塊,若有方塊還需記錄該位置方塊的顏色。for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (block[shape][form].space[i][j]==1){face.data[y + i][x + j] = 1; //將該位置標記為有方塊face.color[y + i][x + j] = shape; //記錄該方塊的顏色數值}}}//判斷此次方塊下落是否得分while (JudeFunc()) {//有得分情況下lines++;//有連續滿行//根據分數調整等級if (disScore / 1000 > 9) {//防止得分過萬顯示大于9的等級grade = 9;}else if (disScore / 1000 < data.hisGrade) {//延續歷史速度grade = data.hisGrade; }else {grade = disScore / 1000;}difficulty = AdjustDifficulty();//重新計算下落時間Display();//擦掉試圖降速時寫的字CursorJump(2 * COL + 22, 16);//printf("堅持!別走回頭路");printf(" ");}break; //跳出當前死循環,準備進行下一個方塊的下落}end = start;//重新開始計時}Sleep(20);//休眠20ms,減少無用循環次數,降低CPU占用率,否則CPU30%消耗在這個死循環}//判斷游戲是否結束for (int j = 1; j < COL - 1; j++){if (face.data[1][j] == 1) {//最上面一行有方塊就OVERgameover = 1;//用于后面處理GAME OVER事項break;}}//游戲結束放在循環外面,這樣方便退出死循環if (gameover){//弄點動靜Beep(523, 400);//do Beep(578, 400);//re Beep(659, 400);//miSleep(1200);//等上面的doremiif (disScore / 1000 <= 9) { data.hisGrade = disScore / 1000; }//下次玩的初始速度else { data.hisGrade = 0; }//分數過萬且創記錄,相當于通過所有挑戰而爆機,等級恢復最低system("cls"); color(7); CursorJump(2 * (COL / 3), ROW / 2 - 3);if (disScore > data.max){printf("恭喜你創造出新的世界記錄%d,留給后人慢慢挑戰吧!", disScore);data.max = disScore;}else if (disScore == data.max){printf("你已追平世界記錄,離超越只差一點點");}else{printf("你與最高記錄相差%d,請繼續加油", data.max - disScore);}WriteGrade(data);//不管玩不玩,還是保存一下吧CursorJump(2 * (COL / 3), ROW / 2);printf("GAME OVER");CursorJump(2 * (COL / 3), ROW / 2 + 3);printf("再來一局?(y/n):");while (1)//要有明確選擇才肯放過你{ch = getch();if (ch == 'y' || ch == 'Y'){gameover = 0;system("cls");InitInterface();Restart();break;//跳出本死循環,進入主死循環,就開始了新的一局}else if (ch == 'n' || ch == 'N'){return 1;//直接跳出死循環返回主程序}else//錯誤選擇鳴笛{Beep(500, 500);}}}//準備下一個方塊shape = nextShape, form = nextForm;DrawSpace(nextShape, nextForm, COL + 3, 3); //將右上角的方塊信息用空格覆蓋} }主程序,僅僅為了測試一下
#include "Tetris.h" int main() {Tetris t = Tetris();t.StartGame(); //開始游戲return 0; }錯誤之處敬請批評指正?
總結
以上是生活随笔為你收集整理的俄罗斯方块,C语言源文件,带有详细的注释的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【转】成为Java顶尖程序员 ,看这10
- 下一篇: 如何查看光驱硬盘托架的尺寸_如何确定光驱