C語言代碼實(shí)現(xiàn)俄羅斯方塊
這里為大家敲寫一段怎樣用C語言實(shí)現(xiàn)俄羅斯方塊:
首先推薦大家使用CodeBlocks這個(gè)軟件,方便添加不同的工程。
代碼中有很多注釋便于理解!
下面是效果圖和全部的代碼以及注釋,大家可以觀看并自己新增內(nèi)容!
1、首先是main.c文件:
#include <stdio.h> #include <stdlib.h> #include "game.h" int main() { gameInit(); return 0; }
2、然后是mywindows.h文件:
#ifndef MYWINDOWS_H_INCLUDED #define MYWINDOWS_H_INCLUDED // 封裝系統(tǒng)函數(shù)-系統(tǒng)調(diào)用模塊 #include <windows.h> // 初始化句柄 extern void initHandle(); // 設(shè)置顏色 extern void setColor(int color); // 設(shè)置光標(biāo)位置 extern void setPos(int x, int y); // 設(shè)置光標(biāo)是否可見 extern void setCursorVisible(int flag); // 關(guān)閉句柄 extern void closeHandle(); #endif // MYWINDOWS_H_INCLUDED
3、接下來是mywindows.c文件:
#include "mywindows.h" HANDLE handle; // 初始化句柄 void initHandle() { handle = GetStdHandle(STD_OUTPUT_HANDLE); } // 設(shè)置顏色 void setColor(int color) { SetConsoleTextAttribute(handle, color); } void setPos(int x, int y) { //, , COORD coord = {x*2, y}; SetConsoleCursorPosition(handle, coord); } // 設(shè)置光標(biāo)是否可見 void setCursorVisible(int flag) { CONSOLE_CURSOR_INFO info; info.bVisible = flag; //光標(biāo)是否可見 info.dwSize = 100; //光標(biāo)寬度1-100 SetConsoleCursorInfo(handle, &info); } // 關(guān)閉句柄 void closeHandle() { CloseHandle(handle); }
4、下面是data.h文件,也就是數(shù)據(jù)庫的存儲(chǔ)地址:
#ifndef DATA_H_INCLUDED #define DATA_H_INCLUDED //函數(shù)聲明\變量聲明 // 存儲(chǔ)數(shù)據(jù)-數(shù)據(jù)模塊 //界面數(shù)組 extern int windowShape[25][26]; extern int block[7][4][4][4]; #endif // DATA_H_INCLUDED
5、數(shù)據(jù)庫內(nèi)容:data.c
#include "data.h" //函數(shù)的定義 int windowShape[25][26] = { {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1}, {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1} };// 邊框?yàn)?,游戲池長度為14 int block[7][4][4][4] = { { //Z{} {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}}, {{1,1,0,0},{0,1,1,0},{0,0,0,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}} }, { //S {{0,1,1,0},{1,1,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,1,1,0},{1,1,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}} }, { //L{} {{1,0,0,0},{1,0,0,0},{1,1,0,0},{0,0,0,0}}, {{1,1,1,0},{1,0,0,0},{0,0,0,0},{0,0,0,0}}, {{1,1,0,0},{0,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,0,1,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}} }, { //J {{0,1,0,0},{0,1,0,0},{1,1,0,0},{0,0,0,0}}, {{1,0,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}, {{1,1,0,0},{1,0,0,0},{1,0,0,0},{0,0,0,0}}, {{1,1,1,0},{0,0,1,0},{0,0,0,0},{0,0,0,0}} }, { //I{} {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}}, {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}}, {{1,1,1,1},{0,0,0,0},{0,0,0,0},{0,0,0,0}}, {{1,0,0,0},{1,0,0,0},{1,0,0,0},{1,0,0,0}} }, { //T {{1,1,1,0},{0,1,0,0},{0,0,0,0},{0,0,0,0}}, {{0,1,0,0},{1,1,0,0},{0,1,0,0},{0,0,0,0}}, {{0,1,0,0},{1,1,1,0},{0,0,0,0},{0,0,0,0}}, {{1,0,0,0},{1,1,0,0},{1,0,0,0},{0,0,0,0}} }, { //田 {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}, {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}, {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}}, {{1,1,0,0},{1,1,0,0},{0,0,0,0},{0,0,0,0}} } };
6、游戲頭部:game.h:
#ifndef GAME_H_INCLUDED #define GAME_H_INCLUDED // 游戲邏輯模塊 #include <stdio.h> #include <time.h> typedef struct{ int x; int y; int shape; int status; int color; }BLOCK; // 定義當(dāng)前正在下落的方塊,和下一個(gè)方塊 BLOCK curBlock; BLOCK nextBlock; // 繪制游戲池邊框 extern void gamePool(int x, int y); // 打印操作說明 extern void printRule(); // 打印分?jǐn)?shù)和等級(jí) extern void printGradeLevel(int num); // 游戲計(jì)時(shí) extern void gameTime(clock_t startTime); // 打印一個(gè)方塊 extern void printBlock(int x, int y, int shape, int status, int color); // 刪除一個(gè)方塊 extern void delBlock(int x, int y, int shape, int status); //方塊左移 extern void leftBlock(); //方塊右移 extern void rightBlock(); //方塊下移 extern int downBlock(); //方塊變形 extern void changeBlock(); //方塊直接落底 extern void bottomBlock(); //游戲暫停 extern void pause(); //隨機(jī)產(chǎn)生游戲第一個(gè)方塊 extern void startBlock(); //隨機(jī)產(chǎn)生下一個(gè)方塊 extern void blockNext(); //拷貝方塊:把下一個(gè)方塊變成當(dāng)前正在下落的方塊 extern void copyBlock(); //碰撞檢測 extern int crash(int x, int y, int shape, int status); //保存方塊 extern void saveBlock(); //刷新游戲池 extern void updateGamePool(); //消行檢測 extern void lineClear(); //消行下移 extern void lineDown(int line); // 初始化游戲 extern void gameInit(); #endif // GAME_H_INCLUDED
7、最后一部分,游戲內(nèi)容,game.c文件:
#include "game.h" #include "mywindows.h" #include "data.h" #include <conio.h> int level = 1; int grade = 100; // 打印游戲池 void gamePool(int x, int y) { int i, j; for(i=0;i<25;i++) { for(j=0;j<26;j++) { if(windowShape[i][j] == 1) { setColor(0xc0); setPos(x+j,y+i); printf(" "); // printf("%2s", ""); } } } } // 打印操作說明 void printRule() { setColor(0x0f); setPos(31, 9); printf("操作規(guī)則:"); setPos(32, 11); printf("按a或A左移"); setPos(32, 12); printf("按d或D右移"); setPos(32, 13); printf("按s或S下移"); setPos(32, 14); printf("按w或W變形"); setPos(32, 15); printf("按空格暫停"); setPos(32, 16); printf("按回車直接下落"); } void printGradeLevel(int num) { switch(num) { case 0: break; case 1: grade += 10;break; case 2: grade += 25;break; case 3: grade += 50;break; case 4: grade += 70;break; } //等級(jí)-->作業(yè) setColor(0x09); setPos(3,6); printf("分?jǐn)?shù):%d", grade); setColor(0x0a); setPos(3,7); printf("等級(jí):%d", level); } void gameTime(clock_t startTime) { //clock_t endTime = clock(); //clock_t ti = (endTime-startTime)/CLOCKS_PER_SEC; setColor(0x0d); setPos(3,8); printf("本次游戲運(yùn)行時(shí)間:%ld", (clock()-startTime)/CLOCKS_PER_SEC); } // 打印一個(gè)方塊 void printBlock(int x, int y, int shape, int status, int color) { int i,j; setColor(color); for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(1 == block[shape][status][i][j]) { setPos(x+j,y+i); printf("■"); } } } } // 刪除一個(gè)方塊 void delBlock(int x, int y, int shape, int status) { int i, j; for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(1 == block[shape][status][i][j]) { setPos(x+j,y+i); printf(" "); //打印兩個(gè)空格 } } } } //方塊左移 void leftBlock() { //已經(jīng)顯示的方塊刪除,改變坐標(biāo),重新打印 if(crash(curBlock.x-1, curBlock.y, curBlock.shape,curBlock.status) == -1) { return; } delBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status); curBlock.x -= 1; printBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status,curBlock.color); } //方塊右移 void rightBlock() { if(crash(curBlock.x+1, curBlock.y, curBlock.shape,curBlock.status) == -1) { return; } delBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status); curBlock.x += 1; printBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status,curBlock.color); } //方塊下移 int downBlock() { if(crash(curBlock.x, curBlock.y+1,curBlock.shape,curBlock.status) == -1) { //落到游戲池底部,產(chǎn)生新方塊 saveBlock(); lineClear(); updateGamePool(); copyBlock(); return -1; }else if(crash(curBlock.x, curBlock.y+1,curBlock.shape,curBlock.status) == -2) { //游戲結(jié)束 return -2; }else{ delBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status); curBlock.y += 1; printBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status,curBlock.color); return 0; } } //方塊變形 void changeBlock() { if(crash(curBlock.x, curBlock.y, curBlock.shape, (curBlock.status+1)%4) == -1){ return; } delBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status); curBlock.status = (curBlock.status+1)%4; printBlock(curBlock.x,curBlock.y,curBlock.shape, curBlock.status,curBlock.color); } //方塊直接落底 void bottomBlock() { while(1){ //流程參考方塊下落 if(downBlock() !=0){ return; } } } //游戲暫停 void pause() { // } //隨機(jī)產(chǎn)生游戲第一個(gè)方塊 void startBlock() { //設(shè)置時(shí)間為隨機(jī)數(shù)種子 srand((unsigned)time(NULL)); //初始化curBlock curBlock.x = 22; curBlock.y = 1; //rand取一個(gè)隨機(jī)整數(shù) curBlock.shape = rand()%7; //0-6 curBlock.status = rand()%4; //0-3 curBlock.color = rand()%0x10; if(0x00 == curBlock.color) { curBlock.color = 0x0f; } printBlock(curBlock.x, curBlock.y, curBlock.shape, curBlock.status, curBlock.color); } //隨機(jī)產(chǎn)生下一個(gè)方塊 void blockNext() { //初始化nextBlock delBlock(nextBlock.x,nextBlock.y, nextBlock.shape,nextBlock.status); nextBlock.x = 34; nextBlock.y = 2; nextBlock.shape = rand()%7; nextBlock.status = rand()%4; nextBlock.color = rand()%0x10; if(0x00 == nextBlock.color) { nextBlock.color = 0x0f; } printBlock(nextBlock.x,nextBlock.y, nextBlock.shape,nextBlock.status,nextBlock.color); } //拷貝方塊:把下一個(gè)方塊變成當(dāng)前正在下落的方塊 void copyBlock() { //當(dāng)前方塊=下一個(gè)方塊 curBlock = nextBlock; curBlock.x = 22; curBlock.y = 1; printBlock(curBlock.x, curBlock.y, curBlock.shape, curBlock.status, curBlock.color); blockNext(); } //碰撞檢測 //x,y為方塊的下一個(gè)位置, status下一種形態(tài) //碰撞返回-1,未碰撞返回0, 游戲結(jié)束返回-2 int crash(int x, int y, int shape, int status) { int i,j; for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(block[shape][status][i][j] == 1) { if(windowShape[i+y][j+x-15] == 1) { //方塊一產(chǎn)生就發(fā)生碰撞 if(curBlock.x == 22 && curBlock.y == 1) { return -2; } return -1; } } } } return 0; } //保存方塊 void saveBlock() { int i,j; for(i=0;i<4;i++) { for(j=0;j<4;j++) { if(block[curBlock.shape][curBlock.status][i][j] == 1) { windowShape[i+curBlock.y][j+curBlock.x-15] = 1; } } } } //刷新游戲池 void updateGamePool() { int i,j; //從下到上刷新游戲池 for(i=23;i>0;i--) { for(j=1;j<15;j++) { if(windowShape[i][j] == 1) { setColor(0x0e); setPos(j+15,i); printf("■"); }else{ setColor(0x00); setPos(j+15,i); printf(" "); } } } } //消行檢測 //檢測滿行->這一行所有值都為1 void lineClear() { int i,j; int num = 0; //統(tǒng)計(jì)一次消行數(shù)目 for(i=23;i>0;i--) { int total = 0; for(j=1;j<15;j++) { total += windowShape[i][j]; } if(total == 14) { //滿行 lineDown(i); i += 1; num += 1; } } printGradeLevel(num); } //消行下移 //從滿行的這行開始,上面所有行順序下移 void lineDown(int line) { int i,j; for(i=line;i>1;i--) { for(j=1;j<15;j++) { windowShape[i][j] = windowShape[i-1][j]; } } } // 初始化游戲 void gameInit() { //第一步,必須初始化句柄 //clock_t startTime = clock(); initHandle(); setCursorVisible(FALSE); gamePool(15,0); printRule(); printGradeLevel(0); startBlock(); blockNext(); //定時(shí)開始時(shí)間,結(jié)束時(shí)間,通過控制時(shí)間差實(shí)現(xiàn)定時(shí) clock_t start,stop; start = clock(); while(1) //for(;;) { //檢測是否有按鍵按下 if(kbhit()) { switch(getch()) { case 'a': case 'A': case 75: leftBlock();break; case 'd': case 'D': case 77: rightBlock();break; case 's': case 'S': case 80: downBlock();break; case 'w': case 'W': case 72: changeBlock();break; case 32: pause();break; case 13: bottomBlock();break; } } //獲取時(shí)間 stop = clock(); if(stop-start>0.5*CLOCKS_PER_SEC) { downBlock(); //重新計(jì)時(shí) start = stop; } } }
好,到現(xiàn)在這個(gè)游戲也就結(jié)束了!
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言實(shí)現(xiàn)括號(hào)配對的方法示例
本文主要介紹了C語言實(shí)現(xiàn)括號(hào)配對的方法示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09C++實(shí)現(xiàn)LeetCode(50.求x的n次方)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(50.求x的n次方),本篇文章通過簡要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列(面試官的小結(jié))
這篇文章主要給大家介紹了關(guān)于C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的相關(guān)資料,這是來自一名面試官的小結(jié),文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05C語言中函數(shù)棧幀的創(chuàng)建和銷毀的深層分析
在C語言中,每一個(gè)正在運(yùn)行的函數(shù)都有一個(gè)棧幀與其對應(yīng),棧幀中存儲(chǔ)的是該函數(shù)的返回地址和局部變量。從邏輯上講,棧幀就是一個(gè)函數(shù)執(zhí)行的環(huán)境:函數(shù)參數(shù)、函數(shù)的局部變量、函數(shù)執(zhí)行完后返回到哪里等等2022-04-04VC中LINK 2001 和 LINK 2009 的錯(cuò)誤的解決方法
最近將兩個(gè)開源C++項(xiàng)目編譯成windows版本的時(shí)候遇到很多問題,編譯的時(shí)候總是報(bào)錯(cuò),報(bào)的最多的是無法解析的外部符號(hào)”,經(jīng)過近3天的折騰總算都通過了,這里是一些總結(jié)2020-10-10C語言數(shù)據(jù)結(jié)構(gòu)深入探索順序表
順序表,全名順序存儲(chǔ)結(jié)構(gòu),是線性表的一種,線性表用于存儲(chǔ)邏輯關(guān)系為“一對一”的數(shù)據(jù),順序表自然也不例外,不僅如此,順序表對數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu)也有要求,跟隨下文來具體了解吧2022-03-03