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)?,游戲池長(zhǎng)度為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();
//碰撞檢測(cè)
extern int crash(int x, int y, int shape, int status);
//保存方塊
extern void saveBlock();
//刷新游戲池
extern void updateGamePool();
//消行檢測(cè)
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();
}
//碰撞檢測(cè)
//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(" ");
}
}
}
}
//消行檢測(cè)
//檢測(cè)滿行->這一行所有值都為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(;;)
{
//檢測(cè)是否有按鍵按下
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é)束了!
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語言實(shí)現(xiàn)括號(hào)配對(duì)的方法示例
本文主要介紹了C語言實(shí)現(xiàn)括號(hào)配對(duì)的方法示例,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
C++實(shí)現(xiàn)LeetCode(50.求x的n次方)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(50.求x的n次方),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列(面試官的小結(jié))
這篇文章主要給大家介紹了關(guān)于C++用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的相關(guān)資料,這是來自一名面試官的小結(jié),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05
C語言中函數(shù)棧幀的創(chuàng)建和銷毀的深層分析
在C語言中,每一個(gè)正在運(yùn)行的函數(shù)都有一個(gè)棧幀與其對(duì)應(yīng),棧幀中存儲(chǔ)的是該函數(shù)的返回地址和局部變量。從邏輯上講,棧幀就是一個(gè)函數(shù)執(zhí)行的環(huán)境:函數(shù)參數(shù)、函數(shù)的局部變量、函數(shù)執(zhí)行完后返回到哪里等等2022-04-04
VC中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-10
C語言數(shù)據(jù)結(jié)構(gòu)深入探索順序表
順序表,全名順序存儲(chǔ)結(jié)構(gòu),是線性表的一種,線性表用于存儲(chǔ)邏輯關(guān)系為“一對(duì)一”的數(shù)據(jù),順序表自然也不例外,不僅如此,順序表對(duì)數(shù)據(jù)的物理存儲(chǔ)結(jié)構(gòu)也有要求,跟隨下文來具體了解吧2022-03-03

