#include <windows.h>
#include <stdio.h>
#include <time.h>

#define BOARD_WIDTH 10
#define BOARD_HEIGHT 20
#define BLOCK_SIZE 25
#define WINDOW_WIDTH (BOARD_WIDTH * BLOCK_SIZE + 200)
#define WINDOW_HEIGHT (BOARD_HEIGHT * BLOCK_SIZE + 40)

// 方块形状定义
const int SHAPES[7][4][4] = {
    {{0,0,0,0}, {1,1,1,1}, {0,0,0,0}, {0,0,0,0}}, // I
    {{0,0,0,0}, {0,1,1,0}, {0,1,1,0}, {0,0,0,0}}, // O
    {{0,0,0,0}, {0,1,1,1}, {0,1,0,0}, {0,0,0,0}}, // L
    {{0,0,0,0}, {0,1,1,1}, {0,0,0,1}, {0,0,0,0}}, // J
    {{0,0,0,0}, {0,1,1,1}, {0,0,1,0}, {0,0,0,0}}, // T
    {{0,0,0,0}, {0,1,1,0}, {0,0,1,1}, {0,0,0,0}}, // S
    {{0,0,0,0}, {0,0,1,1}, {0,1,1,0}, {0,0,0,0}}  // Z
};

// 颜色定义
const COLORREF COLORS[8] = {
    RGB(0, 0, 0),        // 黑色 - 背景
    RGB(0, 255, 255),    // 青色 - I
    RGB(255, 255, 0),    // 黄色 - O
    RGB(255, 165, 0),    // 橙色 - L
    RGB(0, 0, 255),      // 蓝色 - J
    RGB(128, 0, 128),    // 紫色 - T
    RGB(0, 255, 0),      // 绿色 - S
    RGB(255, 0, 0)       // 红色 - Z
};

// 游戏状态
int board[BOARD_HEIGHT][BOARD_WIDTH];
int currentPiece[4][4];
int nextPiece[4][4];
int currentX, currentY;
int currentType, nextType;
int score;
int level;
int linesCleared;
BOOL gameOver;
BOOL isPaused;

// 函数声明
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void InitializeGame(void);
void NewPiece(void);
void RotatePiece(void);
int CheckCollision(void);
void LockPiece(void);
void ClearLines(void);
void DrawGame(HDC hdc);
void DrawBlock(HDC hdc, int x, int y, int colorIndex);
void DrawNextPiece(HDC hdc);
void DrawScore(HDC hdc);
void GameLoop(HWND hwnd);
void ResetGame(void);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    const char CLASS_NAME[] = "TetrisClass";
    WNDCLASS wc = {0};
    HWND hwnd;
    MSG msg;

    // 注册窗口类
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.lpszClassName = CLASS_NAME;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.style = CS_HREDRAW | CS_VREDRAW;

    if (!RegisterClass(&wc)) {
        MessageBox(NULL, "窗口注册失败!", "错误", MB_ICONERROR);
        return 0;
    }

    // 创建窗口
    hwnd = CreateWindowEx(
        0,
        CLASS_NAME,
        "俄罗斯方块 - C89 Windows API",
        WS_OVERLAPPEDWINDOW & ~WS_THICKFRAME & ~WS_MAXIMIZEBOX,
        CW_USEDEFAULT, CW_USEDEFAULT,
        WINDOW_WIDTH, WINDOW_HEIGHT,
        NULL, NULL, hInstance, NULL
    );

    if (hwnd == NULL) {
        MessageBox(NULL, "窗口创建失败!", "错误", MB_ICONERROR);
        return 0;
    }

    // 初始化游戏
    InitializeGame();

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    // 设置定时器用于游戏循环
    SetTimer(hwnd, 1, 500, NULL);

    // 消息循环
    while (GetMessage(&msg, NULL, 0, 0)) {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }

    KillTimer(hwnd, 1);
    return msg.wParam;
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    HDC hdc;
    PAINTSTRUCT ps;

    switch (uMsg) {
        case WM_PAINT:
            hdc = BeginPaint(hwnd, &ps);
            DrawGame(hdc);
            EndPaint(hwnd, &ps);
            break;

        case WM_TIMER:
            if (!gameOver && !isPaused) {
                GameLoop(hwnd);
            }
            break;

        case WM_KEYDOWN:
            if (!gameOver && !isPaused) {
                switch (wParam) {
                    case VK_LEFT:
                        currentX--;
                        if (CheckCollision()) currentX++;
                        InvalidateRect(hwnd, NULL, TRUE);
                        break;
                    case VK_RIGHT:
                        currentX++;
                        if (CheckCollision()) currentX--;
                        InvalidateRect(hwnd, NULL, TRUE);
                        break;
                    case VK_DOWN:
                        currentY++;
                        if (CheckCollision()) {
                            currentY--;
                            LockPiece();
                            ClearLines();
                            NewPiece();
                            if (CheckCollision()) {
                                gameOver = TRUE;
                            }
                        }
                        InvalidateRect(hwnd, NULL, TRUE);
                        break;
                    case VK_UP:
                        RotatePiece();
                        InvalidateRect(hwnd, NULL, TRUE);
                        break;
                    case VK_SPACE: // 硬降到底部
                        while (!CheckCollision()) {
                            currentY++;
                        }
                        currentY--;
                        LockPiece();
                        ClearLines();
                        NewPiece();
                        if (CheckCollision()) {
                            gameOver = TRUE;
                        }
                        InvalidateRect(hwnd, NULL, TRUE);
                        break;
                }
            }
            // 游戏控制键
            switch (wParam) {
                case 'P': case 'p':
                    isPaused = !isPaused;
                    InvalidateRect(hwnd, NULL, TRUE);
                    break;
                case 'R': case 'r':
                    ResetGame();
                    InvalidateRect(hwnd, NULL, TRUE);
                    break;
                case VK_ESCAPE:
                    PostQuitMessage(0);
                    break;
            }
            break;

        case WM_DESTROY:
            PostQuitMessage(0);
            break;

        default:
            return DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
    return 0;
}

void InitializeGame(void) {
    int i, j;
    
    // 初始化随机数种子
    srand((unsigned)time(NULL));
    
    // 清空游戏板
    for (i = 0; i < BOARD_HEIGHT; i++) {
        for (j = 0; j < BOARD_WIDTH; j++) {
            board[i][j] = 0;
        }
    }
    
    // 初始化游戏状态
    score = 0;
    level = 1;
    linesCleared = 0;
    gameOver = FALSE;
    isPaused = FALSE;
    
    // 生成第一个和下一个方块
    currentType = rand() % 7;
    nextType = rand() % 7;
    NewPiece();
}

void NewPiece(void) {
    int i, j;
    
    // 复制当前类型
    currentType = nextType;
    nextType = rand() % 7;
    
    // 复制方块形状
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            currentPiece[i][j] = SHAPES[currentType][i][j];
            nextPiece[i][j] = SHAPES[nextType][i][j];
        }
    }
    
    // 设置初始位置
    currentX = BOARD_WIDTH / 2 - 2;
    currentY = 0;
    
    // 检查游戏是否结束
    if (CheckCollision()) {
        gameOver = TRUE;
    }
}

void RotatePiece(void) {
    int temp[4][4];
    int i, j;
    
    // 创建旋转后的临时方块
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            temp[j][3 - i] = currentPiece[i][j];
        }
    }
    
    // 复制回当前方块
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            currentPiece[i][j] = temp[i][j];
        }
    }
    
    // 检查旋转后是否碰撞,如果碰撞则恢复
    if (CheckCollision()) {
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                temp[3 - j][i] = currentPiece[i][j];
            }
        }
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                currentPiece[i][j] = temp[i][j];
            }
        }
    }
}

int CheckCollision(void) {
    int i, j;
    
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            if (currentPiece[i][j]) {
                int boardX = currentX + j;
                int boardY = currentY + i;
                
                if (boardX < 0 || boardX >= BOARD_WIDTH || 
                    boardY >= BOARD_HEIGHT || 
                    (boardY >= 0 && board[boardY][boardX])) {
                    return 1;
                }
            }
        }
    }
    return 0;
}

void LockPiece(void) {
    int i, j;
    
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            if (currentPiece[i][j]) {
                int boardX = currentX + j;
                int boardY = currentY + i;
                if (boardY >= 0) {
                    board[boardY][boardX] = currentType + 1;
                }
            }
        }
    }
}

void ClearLines(void) {
    int i, j, k;
    int linesToClear = 0;
    
    for (i = BOARD_HEIGHT - 1; i >= 0; i--) {
        int lineFull = 1;
        
        for (j = 0; j < BOARD_WIDTH; j++) {
            if (!board[i][j]) {
                lineFull = 0;
                break;
            }
        }
        
        if (lineFull) {
            linesToClear++;
            // 移动上面的行下来
            for (k = i; k > 0; k--) {
                for (j = 0; j < BOARD_WIDTH; j++) {
                    board[k][j] = board[k - 1][j];
                }
            }
            // 清空顶行
            for (j = 0; j < BOARD_WIDTH; j++) {
                board[0][j] = 0;
            }
            i++; // 重新检查当前行
        }
    }
    
    // 计算得分
    if (linesToClear > 0) {
        linesCleared += linesToClear;
        switch (linesToClear) {
            case 1: score += 100; break;
            case 2: score += 300; break;
            case 3: score += 500; break;
            case 4: score += 800; break;
        }
        level = linesCleared / 10 + 1;
    }
}

void GameLoop(HWND hwnd) {
    currentY++;
    if (CheckCollision()) {
        currentY--;
        LockPiece();
        ClearLines();
        NewPiece();
    }
    InvalidateRect(hwnd, NULL, TRUE);
}

void ResetGame(void) {
    InitializeGame();
}

void DrawGame(HDC hdc) {
    int i, j;
    RECT rect;
    
    // 绘制背景
    GetClientRect(WindowFromDC(hdc), &rect);
    FillRect(hdc, &rect, (HBRUSH)(COLOR_WINDOW + 1));
    
    // 绘制游戏板边框
    rect.left = 0;
    rect.top = 0;
    rect.right = BOARD_WIDTH * BLOCK_SIZE;
    rect.bottom = BOARD_HEIGHT * BLOCK_SIZE;
    FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
    
    // 绘制已固定的方块
    for (i = 0; i < BOARD_HEIGHT; i++) {
        for (j = 0; j < BOARD_WIDTH; j++) {
            if (board[i][j] > 0) {
                DrawBlock(hdc, j, i, board[i][j]);
            }
        }
    }
    
    // 绘制当前方块
    if (!gameOver) {
        for (i = 0; i < 4; i++) {
            for (j = 0; j < 4; j++) {
                if (currentPiece[i][j]) {
                    int x = currentX + j;
                    int y = currentY + i;
                    if (y >= 0) {
                        DrawBlock(hdc, x, y, currentType + 1);
                    }
                }
            }
        }
    }
    
    // 绘制下一个方块预览
    DrawNextPiece(hdc);
    
    // 绘制分数和信息
    DrawScore(hdc);
    
    // 绘制游戏状态
    SetBkMode(hdc, TRANSPARENT);
    if (gameOver) {
        TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 150, "游戏结束!", 8);
        TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 170, "按R重新开始", 11);
    } else if (isPaused) {
        TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 150, "游戏暂停", 8);
    }
}

void DrawBlock(HDC hdc, int x, int y, int colorIndex) {
    HBRUSH brush = CreateSolidBrush(COLORS[colorIndex]);
    HBRUSH oldBrush = SelectObject(hdc, brush);
    HPEN pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
    HPEN oldPen = SelectObject(hdc, pen);
    
    Rectangle(hdc, 
             x * BLOCK_SIZE, 
             y * BLOCK_SIZE, 
             (x + 1) * BLOCK_SIZE, 
             (y + 1) * BLOCK_SIZE);
    
    SelectObject(hdc, oldBrush);
    SelectObject(hdc, oldPen);
    DeleteObject(brush);
    DeleteObject(pen);
}

void DrawNextPiece(HDC hdc) {
    int i, j;
    RECT rect;
    
    // 绘制下一个方块区域
    rect.left = BOARD_WIDTH * BLOCK_SIZE + 20;
    rect.top = 20;
    rect.right = rect.left + 100;
    rect.bottom = rect.top + 100;
    FrameRect(hdc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
    
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 5, "下一个方块:", 10);
    
    // 绘制下一个方块
    for (i = 0; i < 4; i++) {
        for (j = 0; j < 4; j++) {
            if (nextPiece[i][j]) {
                int x = (BOARD_WIDTH * BLOCK_SIZE + 45) + j * BLOCK_SIZE;
                int y = 45 + i * BLOCK_SIZE;
                
                HBRUSH brush = CreateSolidBrush(COLORS[nextType + 1]);
                HBRUSH oldBrush = SelectObject(hdc, brush);
                HPEN pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
                HPEN oldPen = SelectObject(hdc, pen);
                
                Rectangle(hdc, x, y, x + BLOCK_SIZE, y + BLOCK_SIZE);
                
                SelectObject(hdc, oldBrush);
                SelectObject(hdc, oldPen);
                DeleteObject(brush);
                DeleteObject(pen);
            }
        }
    }
}

void DrawScore(HDC hdc) {
    char buffer[50];
    
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 200, "分数:", 4);
    sprintf(buffer, "%d", score);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 70, 200, buffer, strlen(buffer));
    
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 220, "等级:", 4);
    sprintf(buffer, "%d", level);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 70, 220, buffer, strlen(buffer));
    
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 240, "消除行数:", 8);
    sprintf(buffer, "%d", linesCleared);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 90, 240, buffer, strlen(buffer));
    
    // 绘制控制说明
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 280, "控制:", 4);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 300, "←→: 移动", 8);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 320, "↑: 旋转", 6);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 340, "↓: 加速下落", 10);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 360, "空格: 硬降", 8);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 380, "P: 暂停", 6);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 400, "R: 重新开始", 10);
    TextOut(hdc, BOARD_WIDTH * BLOCK_SIZE + 20, 420, "ESC: 退出", 8);
}

----------------------------------------------------------------------------------
cmd编译命令: gcc tetris_winapi.c -o tetris.exe -lgdi32 -luser32

----------------------------------------------------------------------------------

运行界面:

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐