c++自制俄罗斯方块代码
include
include
include
include <conio.h>
include <windows.h>
include
using namespace std;
// 游戏常量定义
const int WIDTH = 12; // 游戏区域宽度
const int HEIGHT = 20; // 游戏区域高度
const int NEXT_WIDTH = 6; // 下一个方块预览区宽度
// 全局变量
int board[HEIGHT][WIDTH] = {0}; // 游戏区域
int nextBoard[NEXT_WIDTH][NEXT_WIDTH] = {0}; // 下一个方块预览区
int score = 0; // 分数
int level = 1; // 级别
int lines = 0; // 消除的行数
bool gameOver = false; // 游戏结束标志
bool isPaused = false; // 暂停标志
// 方块形状定义 (7种经典形状)
// 0: I, 1: O, 2: T, 3: L, 4: J, 5: S, 6: Z
int shapes[7][4][4] = {
{{1,1,1,1}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0}}, // I
{{1,1,0,0}, {1,1,0,0}, {0,0,0,0}, {0,0,0,0}}, // O
{{0,1,0,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0}}, // T
{{0,0,1,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0}}, // L
{{1,0,0,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0}}, // J
{{0,1,1,0}, {1,1,0,0}, {0,0,0,0}, {0,0,0,0}}, // S
{{1,1,0,0}, {0,1,1,0}, {0,0,0,0}, {0,0,0,0}} // Z
};
// 当前方块信息
struct CurrentPiece {
int shape; // 形状
int x; // x坐标
int y; // y坐标
int rotation; // 旋转状态
} current;
// 下一个方块信息
int nextShape;
// 函数声明
void setupGame();
void createNewPiece();
void drawBoard();
void drawPiece();
void drawNextPiece();
void rotatePiece();
bool checkCollision(int dx, int dy, int rotation);
void lockPiece();
void clearLines();
void increaseScore(int linesCleared);
void handleInput();
void gameLoop();
void gameOverScreen();
void pauseGame();
// 工具函数
void setCursorPosition(int x, int y);
void clearScreen();
void printCentered(string text, int y);
void hideCursor();
// 主函数
int main() {
srand(time(0)); // 初始化随机数生成器
hideCursor(); // 隐藏光标
setupGame(); // 初始化游戏
gameLoop(); // 游戏主循环
return 0;
}
// 初始化游戏
void setupGame() {
// 初始化游戏区域边界
for (int i = 0; i < HEIGHT; i++) {
board[i][0] = 2;
board[i][WIDTH-1] = 2;
}
for (int j = 0; j < WIDTH; j++) {
board[HEIGHT-1][j] = 2;
}
// 生成第一个和第二个方块
nextShape = rand() % 7;
createNewPiece();
score = 0;
level = 1;
lines = 0;
gameOver = false;
}
// 创建新方块
void createNewPiece() {
// 当前方块设为下一个方块
current.shape = nextShape;
current.rotation = 0;
current.x = WIDTH / 2 - 2;
current.y = 1;
// 生成下一个方块
nextShape = rand() % 7;
// 清空下一个方块预览区
for (int i = 0; i < NEXT_WIDTH; i++)
for (int j = 0; j < NEXT_WIDTH; j++)
nextBoard[i][j] = 0;
// 绘制下一个方块到预览区
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (shapes[nextShape][i][j]) {
nextBoard[i+1][j+1] = 1;
}
}
}
// 检查游戏是否结束(新方块无法生成)
if (checkCollision(0, 0, 0)) {
gameOver = true;
}
}
// 绘制游戏界面
void drawBoard() {
clearScreen();
// 绘制标题
printCentered("===== 俄罗斯方块 =====", 0);
// 绘制游戏区域
for (int i = 0; i < HEIGHT; i++) {
setCursorPosition(10, i + 2); // 游戏区域x坐标为10
for (int j = 0; j < WIDTH; j++) {
if (board[i][j] == 0) {
cout << " "; // 空白
} else if (board[i][j] == 1) {
cout << "[]"; // 已落下的方块
} else if (board[i][j] == 2) {
cout << "##"; // 边界
}
}
}
// 绘制当前方块
drawPiece();
// 绘制游戏信息
setCursorPosition(WIDTH*2 + 15, 3);
cout << "分数: " << score;
setCursorPosition(WIDTH*2 + 15, 5);
cout << "行数: " << lines;
setCursorPosition(WIDTH*2 + 15, 7);
cout << "级别: " << level;
// 绘制下一个方块预览
setCursorPosition(WIDTH*2 + 15, 10);
cout << "下一个方块:";
for (int i = 0; i < NEXT_WIDTH; i++) {
setCursorPosition(WIDTH*2 + 15, i + 12);
for (int j = 0; j < NEXT_WIDTH; j++) {
if (nextBoard[i][j] == 1) {
cout << "[]";
} else {
cout << " ";
}
}
}
// 绘制操作说明
setCursorPosition(WIDTH*2 + 15, 20);
cout << "操作说明:";
setCursorPosition(WIDTH*2 + 15, 21);
cout << "← → : 移动";
setCursorPosition(WIDTH*2 + 15, 22);
cout << "↑ : 旋转";
setCursorPosition(WIDTH*2 + 15, 23);
cout << "↓ : 加速下落";
setCursorPosition(WIDTH*2 + 15, 24);
cout << "P : 暂停";
setCursorPosition(WIDTH*2 + 15, 25);
cout << "ESC : 退出";
// 显示暂停状态
if (isPaused) {
printCentered("===== 游戏暂停 =====", HEIGHT/2 + 2);
printCentered("按P键继续游戏", HEIGHT/2 + 4);
}
}
// 绘制当前方块
void drawPiece() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (shapes[current.shape][i][j]) {
setCursorPosition(10 + (current.x + j) * 2, 2 + current.y + i);
cout << "[]";
}
}
}
}
// 旋转方块
void rotatePiece() {
int oldRotation = current.rotation;
current.rotation = (current.rotation + 1) % 4;
// 如果旋转后碰撞,恢复原来的旋转状态
if (checkCollision(0, 0, current.rotation)) {
current.rotation = oldRotation;
}
}
// 检查碰撞
bool checkCollision(int dx, int dy, int rotation) {
// 创建旋转后的临时形状
int rotatedShape[4][4] = {0};
// 根据旋转状态旋转形状
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
switch (rotation % 4) {
case 0: // 0度
rotatedShape[i][j] = shapes[current.shape][i][j];
break;
case 1: // 90度
rotatedShape[i][j] = shapes[current.shape][3-j][i];
break;
case 2: // 180度
rotatedShape[i][j] = shapes[current.shape][3-i][3-j];
break;
case 3: // 270度
rotatedShape[i][j] = shapes[current.shape][j][3-i];
break;
}
}
}
// 检查是否与边界或已有方块碰撞
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (rotatedShape[i][j]) {
int newX = current.x + j + dx;
int newY = current.y + i + dy;
if (newX < 0 || newX >= WIDTH || newY < 0 || newY >= HEIGHT) {
return true; // 与边界碰撞
}
if (board[newY][newX] == 1 || board[newY][newX] == 2) {
return true; // 与已有方块或边界碰撞
}
}
}
}
return false; // 没有碰撞
}
// 锁定方块到游戏区域
void lockPiece() {
// 创建旋转后的形状
int rotatedShape[4][4] = {0};
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
switch (current.rotation % 4) {
case 0:
rotatedShape[i][j] = shapes[current.shape][i][j];
break;
case 1:
rotatedShape[i][j] = shapes[current.shape][3-j][i];
break;
case 2:
rotatedShape[i][j] = shapes[current.shape][3-i][3-j];
break;
case 3:
rotatedShape[i][j] = shapes[current.shape][j][3-i];
break;
}
}
}
// 将方块锁定到游戏区域
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (rotatedShape[i][j]) {
board[current.y + i][current.x + j] = 1;
}
}
}
// 检查并消除完整行
clearLines();
// 创建新方块
createNewPiece();
}
// 消除完整行
void clearLines() {
int linesCleared = 0;
for (int i = HEIGHT - 2; i > 0; i--) {
bool isLineComplete = true;
// 检查当前行是否完整
for (int j = 1; j < WIDTH - 1; j++) {
if (board[i][j] == 0) {
isLineComplete = false;
break;
}
}
// 如果行完整,则消除
if (isLineComplete) {
linesCleared++;
// 将上面的行下移
for (int k = i; k > 1; k--) {
for (int j = 1; j < WIDTH - 1; j++) {
board[k][j] = board[k - 1][j];
}
}
// 清空最上面一行
for (int j = 1; j < WIDTH - 1; j++) {
board[1][j] = 0;
}
// 重新检查当前行(因为上面的行下移了)
i++;
}
}
// 增加分数
if (linesCleared > 0) {
increaseScore(linesCleared);
}
}
// 增加分数
void increaseScore(int linesCleared) {
// 根据消除的行数和当前级别计算分数
const int lineScores[] = {0, 100, 300, 500, 800}; // 1-4行的分数
score += lineScores[linesCleared] * level;
lines += linesCleared;
// 每消除10行升一级
level = lines / 10 + 1;
}
// 处理用户输入
void handleInput() {
if (_kbhit()) {
char key = _getch();
if (key == 27) { // ESC键退出游戏
gameOver = true;
return;
}
if (isPaused) {
if (key == 'p' || key == 'P') { // P键继续游戏
isPaused = false;
}
return;
}
switch (key) {
case 75: // 左箭头
if (!checkCollision(-1, 0, current.rotation)) {
current.x--;
}
break;
case 77: // 右箭头
if (!checkCollision(1, 0, current.rotation)) {
current.x++;
}
break;
case 80: // 下箭头
if (!checkCollision(0, 1, current.rotation)) {
current.y++;
} else {
lockPiece();
}
break;
case 72: // 上箭头旋转
rotatePiece();
break;
// P键暂停游戏
isPaused = true;
break;
}
}
}
// 游戏主循环
void gameLoop() {
int fallSpeed = 50; // 初始下落速度(数值越小越快)
int fallCounter = 0;
while (!gameOver) {
drawBoard();
handleInput();
if (!isPaused) {
// 控制方块下落速度,随级别提高而加快
fallSpeed = max(10, 50 - (level - 1) * 5);
if (fallCounter++ >= fallSpeed) {
// 自动下落
if (!checkCollision(0, 1, current.rotation)) {
current.y++;
} else {
lockPiece();
}
fallCounter = 0;
}
}
Sleep(10); // 控制循环速度
}
gameOverScreen();
}
// 游戏结束界面
void gameOverScreen() {
clearScreen();
printCentered("===== 游戏结束 =====", 10);
printCentered("最终分数: " + to_string(score), 12);
printCentered("消除行数: " + to_string(lines), 13);
printCentered("达到级别: " + to_string(level), 14);
printCentered("按任意键退出", 16);
_getch(); // 等待用户按键
}
// 工具函数:设置光标位置
void setCursorPosition(int x, int y) {
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}
// 工具函数:清屏
void clearScreen() {
system("cls");
}
// 工具函数:居中打印文本
void printCentered(string text, int y) {
int x = (80 - text.length()) / 2; // 假设控制台宽度为80
setCursorPosition(x, y);
cout << text;
}
// 工具函数:隐藏光标
void hideCursor() {
CONSOLE_CURSOR_INFO cursor_info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}