C语言---俄罗斯方块游戏
接下来,我们将实现一个基于C语言的小游戏源小游戏代俄罗斯方块小游戏,这个项目将综合运用之前所学的码俄码诸多知识点,包括键盘操作、俄罗lua小项目源码文本输出、斯方dnf柠檬源码图形绘制和显示等。小游戏源小游戏代首先,码俄码让我们看看游戏的俄罗几个界面:
1. 游戏欢迎界面
2. 游戏主界面,包括游戏区域、斯方预览下一个模块区、小游戏源小游戏代得分区以及游戏使用说明区
3. 游戏结束界面
游戏中,码俄码玩家可以操控模块在屏幕上下左右移动,俄罗源码交流区变换形状,斯方以及通过加速键快速下落。小游戏源小游戏代每当填满一行,就会消除该行并获得分。无亏损源码在预览区,玩家可以看到下一个即将出现的模块形状。游戏结束后,按下'r'键可重新开始。房源码失效
程序的数据结构主要分为两部分:
1. 游戏池数据结构:包含一个x的二维数组(po)表示小方块,通过改变po数组和颜色列表(col)实现方块的移动、翻转和消行效果。同时,记录下落模块位置的变量x和y也在其中。
2. 模块数据结构:一个struct model类型的数组,包含种不同模块的形状和颜色信息。当模块进入游戏池时,其形状和颜色将被复制到游戏池的数据结构中。
模块移动时的数据操作包括:模块初始化、左右移动、上下移动以及旋转。通过改变pool结构体中的对应数据,实时更新屏幕显示。
游戏的核心模块和流程包括mainloop函数,详细的实现步骤和源码注释可以在我的公众号《编程来了》获取。
用c++编写一个俄罗斯方块小游戏,能在codeblocks上运行
#include <iostream>
#include <windows.h>
#include <vector>
#include <mmsystem.h>
#include <cstdio>
#pragma comment(lib, "winmm.lib")
using namespace std;
#define GameW
#define GameH
const int CtrlLeft = GameW*2+4 + 3;
struct Point {
Point(){ }
Point(int x, int y) { _x = x, _y = y;}
int _x, _y;
};
HANDLE g_hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE g_hInput = GetStdHandle(STD_INPUT_HANDLE);
Point g_ptCursor(0,0);
BOOL isChecking = FALSE;
BOOL g_bGameOver = FALSE;
int g_nGameBack[GameH][GameW], Case;
int nowKeyInfo = -1;
int g_nDiff = 1;
int g_nLife = 2;
int g_nScore = 0;
void SetCursor(COORD cd) {
SetConsoleCursorPosition(g_hOutput, cd);
}
void SetCursor(int x, int y){
COORD cd = { x, y};
SetCursor(cd);
}
void SetBlockCursor(int x, int y){
COORD cd = { 2*x + 2, y + 1};
SetCursor(cd);
}
void SetBack(int x, int y, BOOL bk) {
SetBlockCursor(x, y);
if (bk)
printf("%s", "■");
else
printf(" ");
}
bool Out(int x, int y) {
return x < 0 || y < 0 || x >= GameW || y >= GameH;
}
struct xBlock {
public:
int len;
int nowRotateID;
BOOL mask[4][4][4];
static vector <xBlock> List;
xBlock() { len = 0; }
xBlock(int l, char *str) {
int i, j, k;
len = l;
memset(mask, FALSE, sizeof(mask));
for (i = 0; i < l; i++) {
for (j = 0; j < l; j++) {
mask[0][i][j] = str[i*l + j] - '0';
}
}
for (k = 1; k < 4; k++) {
for (i = 0; i < len; i++) {
for (j = 0; j < len; j++) {
mask[k][i][j] = mask[k-1][j][len-1-i];
}
}
}
nowRotateID = rand() % 4;
}
void rotate() {
nowRotateID ++;
if (nowRotateID >= 4)
nowRotateID = 0;
}
BOOL getUnit(int x, int y, int roID) {
if (roID == -1) {
roID = nowRotateID;
}
return mask[roID][y][x];
}
};
vector <xBlock> xBlock::List;
class Block {
public:
int x, y;
int ID;
xBlock bk;
void reset(xBlock *pbk) {
bk = *pbk;
x = 4, y = 0;
ID = ++ Case;
if (collide(0,0)) {
lifeDown();
}
draw();
*pbk = xBlock::List[rand() % xBlock::List.size()];
}
void lifeDown() {
int i, j;
for (i = 0; i < GameH; i++) {
for (j = 0; j < GameW; j++) {
SetBack(j, i, TRUE);
Sleep();
}
}
if (g_nLife) {
g_nLife --;
for (i = g_nLife; i < 6; i++) {
SetCursor(CtrlLeft + i, );
printf("%c", ' ');
}
for (i = GameH-1; i >= 0; i--) {
for (j = GameW-1; j >= 0; j--) {
SetBack(j, i, FALSE);
Sleep();
g_nGameBack[i][j] = 0;
}
}
}else {
g_bGameOver = TRUE;
}
}
void erase() {
int i, j;
for (i = 0; i < bk.len; i++) {
for (j = 0; j < bk.len; j++) {
if (bk.getUnit(j, i, -1)) {
if (! Out(j+x, i+y) && g_nGameBack[i+y][j+x]) {
SetBack(j+x, i+y, FALSE);
g_nGameBack[i+y][j+x] = 0;
}
}
}
}
}
void draw() {
int i, j;
for (i = 0; i < bk.len; i++) {
for (j = 0; j < bk.len; j++) {
if (bk.getUnit(j, i, -1)) {
if (! Out(j+x, i+y) && ! g_nGameBack[i+y][j+x]) {
SetBack(j+x, i+y, TRUE);
g_nGameBack[i+y][j+x] = ID;
}
}
}
}
}
void draw(int x, int y) {
int i, j;
for (i = 0; i < 4; i++) {
for (j = 0; j < 4; j++) {
SetCursor(x + 2*j, y + i);
if (bk.getUnit(j, i, -1)) {
printf("%s", "■");
}else
printf(" ");
}
}
}
bool collide(int dx, int dy, int roID = -1) {
int i, j;
for (i = 0; i < bk.len; i++) {
for (j = 0; j < bk.len; j++) {
if (bk.getUnit(j, i, roID)) {
Point ptPos(j + x + dx, i + y + dy);
if (Out(ptPos._x, ptPos._y)
|| g_nGameBack[ptPos._y][ptPos._x] && ID != g_nGameBack[ptPos._y][ptPos._x]) {
return TRUE;
}
}
}
}
return FALSE;
}
void rotate(int nTimes = 1) {
int nextro = (bk.nowRotateID + nTimes) % 4;
if (collide(0, 0, nextro)) {
return ;
}
Beep(, );
erase();
bk.nowRotateID = nextro;
draw();
}
BOOL changepos(int dx, int dy) {
if (collide(dx, dy)) {
return FALSE;
}
erase();
x += dx;
y += dy;
draw();
return TRUE;
}
};
void GameInit() {
CONSOLE_CURSOR_INFO cursor_info;
cursor_info.bVisible = FALSE;
cursor_info.dwSize = ;
SetConsoleCursorInfo(g_hOutput, &cursor_info);
xBlock::List.push_back(xBlock(3, ""));
xBlock::List.push_back(xBlock(3, ""));
xBlock::List.push_back(xBlock(3, ""));
xBlock::List.push_back(xBlock(3, ""));
xBlock::List.push_back(xBlock(3, ""));
xBlock::List.push_back(xBlock(3, ""));
xBlock::List.push_back(xBlock(4, ""));
}
void DrawFrame(int x, int y, int nWidth, int nHeight) {
int i;
for (i = 0; i < nWidth; i++) {
SetCursor(x + 2*i + 2, y);
printf("%s", "一");
SetCursor(x + 2*i + 2, y + nHeight+1);
printf("%s", "┄");
}
for (i = 0; i < nHeight; i++) {
SetCursor(x, y + i + 1);
printf("%s", "┆");
SetCursor(x + nWidth*2+2, y + i + 1);
printf("%s", "┆");
}
SetCursor(x, y);
printf("%s", "┌");
SetCursor(x, y + nHeight+1);
printf("%s", "└");
SetCursor(x + nWidth*2+2, y);
printf("%s", "┐");
SetCursor(x + nWidth*2+2, y + nHeight+1);
printf("%s", "┘");
}
void MissionInit() {
memset(g_nGameBack, FALSE, sizeof(g_nGameBack));
Case = 1;
int i;
DrawFrame(0, 0, GameW, GameH);
DrawFrame(GameW*2+4, 0, 4, GameH);
SetCursor(CtrlLeft, 2);
printf("Next");
SetCursor(CtrlLeft, 8);
printf("Speed");
for (i = 0; i < g_nDiff; i++) {
SetCursor(CtrlLeft + i, 9);
printf("%c", 1);
}
SetCursor(CtrlLeft, );
printf("Score");
SetCursor(CtrlLeft, );
printf("%d", g_nScore);
SetCursor(CtrlLeft, );
printf("Life");
for (i = 0; i < g_nLife; i++) {
SetCursor(CtrlLeft + i, );
printf("%c", 3);
}
}
void Check() {
isChecking = TRUE;
int i, j, k;
vector <int> line;
for (i = 0; i < GameH; i++) {
for (j = 0; j < GameW; j++) {
if (! g_nGameBack[i][j])
break;
}
if (j == GameW) {
line.push_back(i);
}
}
if (line.size()) {
int nCount = 7;
while (nCount --) {
for (i = 0; i < line.size(); i++) {
for (j = 0; j < GameW; j++) {
SetBack(j, line[i], nCount&1);
}
}
Sleep();
}
for (i = 0; i < line.size(); i++) {
for (j = 0; j < GameW; j++) {
g_nGameBack[line[i]][j] = 0;
}
}
for (i = 0; i < GameW; i++) {
int next = GameH-1;
for (j = GameH-1; j >= 0; j--) {
for (k = next; k >= 0; k--) {
if (g_nGameBack[k][i])
break;
}
next = k - 1;
BOOL is = (k >= 0);
SetBack(i, j, is);
g_nGameBack[j][i] = is;
}
}
g_nScore += 2*line.size()-1;
SetCursor(CtrlLeft, );
printf("%d", g_nScore);
if ( g_nScore >= g_nDiff * g_nDiff * ) {
if (g_nDiff <= 6)
g_nDiff ++;
}
if ( g_nScore >= * (g_nLife+1)) {
if (g_nLife <= 6)
g_nLife ++;
}
}
isChecking = FALSE;
}
int main() {
Block* obj = new Block();
Block* buf = new Block();
BOOL bCreateNew = FALSE;
int nTimer = GetTickCount();
int LastKeyDownTime = GetTickCount();
GameInit();
MissionInit();
buf -> bk = xBlock::List[rand() % xBlock::List.size()];
while (1) {
if (! bCreateNew) {
bCreateNew = TRUE;
obj -> reset(&buf -> bk);
if (g_bGameOver)
break;
buf -> draw(CtrlLeft - 1, 4);
}
if (GetTickCount() - nTimer >= / g_nDiff) {
nTimer = GetTickCount();
if (! obj -> collide(0, 1))
obj -> changepos(0, 1);
else {
Check();
bCreateNew = FALSE;
}
}
if (GetTickCount() - LastKeyDownTime >= ) {
if (FALSE == isChecking) {
LastKeyDownTime = GetTickCount();
if (GetAsyncKeyState(VK_UP)) {
obj -> rotate();
}
if (GetAsyncKeyState(VK_LEFT)) {
obj -> changepos(-1, 0);
}
if (GetAsyncKeyState(VK_RIGHT)) {
obj -> changepos(1, 0);
}
if (GetAsyncKeyState(VK_DOWN)) {
if ( FALSE == obj -> changepos(0, 2) )
obj -> changepos(0, 1);
}
}
}
}
SetCursor(8, );
printf("Game Over!");
SetCursor(0, GameH + 3);
while (1) {
if (GetAsyncKeyState(VK_ESCAPE))
break;
}
return 0;
}
2024-11-23 11:01
2024-11-23 10:27
2024-11-23 10:04
2024-11-23 09:44
2024-11-23 09:29