#include <SFML/Graphics.hpp> #include #include #include

const int WIDTH = 10; const int HEIGHT = 20; const int BLOCK_SIZE = 30;

std::vector<std::vector> board(HEIGHT, std::vector(WIDTH, 0));

std::vector<std::vector<std::vector>> shapes = { { {1, 1, 1, 1} }, { {1, 1}, {1, 1} }, { {1, 1, 0}, {0, 1, 1} }, { {0, 1, 1}, {1, 1, 0} }, { {1, 1, 1}, {0, 1, 0} }, { {1, 1, 1}, {1, 0, 0} }, { {1, 1, 1}, {0, 0, 1} } };

struct Piece { int x, y; int shapeIndex; int rotation; };

bool canMove(const Piece& piece, int newX, int newY, int newRotation) { const auto& shape = shapes[piece.shapeIndex]; int rotatedShapeSize = shape.size();

for (int i = 0; i < rotatedShapeSize; ++i) {
    for (int j = 0; j < rotatedShapeSize; ++j) {
        int newCellX = piece.x + j + newX;
        int newCellY = piece.y + i + newY;

        if (shape[i][j] == 1) {
            if (newCellX < 0 || newCellX >= WIDTH || newCellY >= HEIGHT) {
                return false;
            }
            if (newCellY >= 0 && board[newCellY][newCellX] != 0) {
                return false;
            }
        }
    }
}
return true;

}

void mergePiece(const Piece& piece) { const auto& shape = shapes[piece.shapeIndex]; int rotatedShapeSize = shape.size();

for (int i = 0; i < rotatedShapeSize; ++i) {
    for (int j = 0; j < rotatedShapeSize; ++j) {
        if (shape[i][j] == 1) {
            board[piece.y + i][piece.x + j] = piece.shapeIndex + 1;
        }
    }
}

}

int clearLines() { int linesCleared = 0; for (int i = HEIGHT - 1; i >= 0; --i) { bool isLineFull = true; for (int j = 0; j < WIDTH; ++j) { if (board[i][j] == 0) { isLineFull = false; break; } } if (isLineFull) { linesCleared++; for (int k = i; k > 0; --k) { board[k] = board[k - 1]; } ++i; } } return linesCleared; }

bool isGameOver(const Piece& piece) { return!canMove(piece, 0, 0, piece.rotation); }

int main() { sf::RenderWindow window(sf::VideoMode(WIDTH * BLOCK_SIZE + 200, HEIGHT * BLOCK_SIZE), "Tetris");

std::random_device rd;
std::mt19937 gen(rd());
std::uniform_int_distribution<> dis(0, shapes.size() - 1);

Piece currentPiece;
currentPiece.x = WIDTH / 2 - shapes[0][0].size() / 2;
currentPiece.y = 0;
currentPiece.shapeIndex = dis(gen);
currentPiece.rotation = 0;

sf::Clock clock;
float fallTime = 0;

// 定义不同难度级别对应的下落速度
std::vector<float> fallSpeeds = {0.8, 0.6, 0.4, 0.2};
int difficultyLevel = 0;

// 显示难度选择界面
sf::Font font;
if (!font.loadFromFile("arial.ttf")) {
    std::cerr << "Failed to load font!" << std::endl;
    return -1;
}
sf::Text difficultyText;
difficultyText.setFont(font);
difficultyText.setCharacterSize(24);
difficultyText.setFillColor(sf::Color::White);
difficultyText.setPosition(WIDTH * BLOCK_SIZE / 2 - 100, HEIGHT * BLOCK_SIZE / 2 - 50);
difficultyText.setString("Select Difficulty:\n1. Easy\n2. Medium\n3. Hard\n4. Very Hard");

while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        if (event.type == sf::Event::Closed) {
            window.close();
        }
        if (event.type == sf::Event::KeyPressed) {
            if (event.key.code >= sf::Keyboard::Num1 && event.key.code <= sf::Keyboard::Num4) {
                difficultyLevel = event.key.code - sf::Keyboard::Num1;
                break;
            }
        }
    }

    if (difficultyLevel >= 0) {
        break;
    }

    window.clear();
    window.draw(difficultyText);
    window.display();
}

float fallSpeed = fallSpeeds[difficultyLevel];

int score = 0;
sf::Text scoreText;
scoreText.setFont(font);
scoreText.setCharacterSize(24);
scoreText.setFillColor(sf::Color::White);
scoreText.setPosition(WIDTH * BLOCK_SIZE + 20, 20);

while (window.isOpen()) {
    sf::Event event;
    while (window.pollEvent(event)) {
        if (event.type == sf::Event::Closed) {
            window.close();
        }
        if (event.type == sf::Event::KeyPressed) {
            if (event.key.code == sf::Keyboard::Left && canMove(currentPiece, -1, 0, currentPiece.rotation)) {
                --currentPiece.x;
            }
            if (event.key.code == sf::Keyboard::Right && canMove(currentPiece, 1, 0, currentPiece.rotation)) {
                ++currentPiece.x;
            }
            if (event.key.code == sf::Keyboard::Down && canMove(currentPiece, 0, 1, currentPiece.rotation)) {
                ++currentPiece.y;
            }
        }
    }

    float deltaTime = clock.restart().asSeconds();
    fallTime += deltaTime;

    if (fallTime >= fallSpeed) {
        if (canMove(currentPiece, 0, 1, currentPiece.rotation)) {
            ++currentPiece.y;
        } else {
            mergePiece(currentPiece);
            int lines = clearLines();
            score += lines * 100;
            scoreText.setString("Score: " + std::to_string(score));

            currentPiece.x = WIDTH / 2 - shapes[0][0].size() / 2;
            currentPiece.y = 0;
            currentPiece.shapeIndex = dis(gen);
            currentPiece.rotation = 0;

            if (isGameOver(currentPiece)) {
                window.close();
                std::cout << "Game Over! Your score is: " << score << std::endl;
            }
        }
        fallTime = 0;
    }

    window.clear();

    for (int i = 0; i < HEIGHT; ++i) {
        for (int j = 0; j < WIDTH; ++j) {
            if (board[i][j] != 0) {
                sf::RectangleShape block(sf::Vector2f(BLOCK_SIZE, BLOCK_SIZE));
                block.setPosition(j * BLOCK_SIZE, i * BLOCK_SIZE);
                block.setFillColor(sf::Color::Blue);
                window.draw(block);
            }
        }
    }

    const auto& shape = shapes[currentPiece.shapeIndex];
    int rotatedShapeSize = shape.size();
    for (int i = 0; i < rotatedShapeSize; ++i) {
        for (int j = 0; j < rotatedShapeSize; ++j) {
            if (shape[i][j] == 1) {
                sf::RectangleShape block(sf::Vector2f(BLOCK_SIZE, BLOCK_SIZE));
                block.setPosition((currentPiece.x + j) * BLOCK_SIZE, (currentPiece.y + i) * BLOCK_SIZE);
                block.setFillColor(sf::Color::Blue);
                window.draw(block);
            }
        }
    }

    window.draw(scoreText);
    window.display();
}

return 0;

}

0 条评论

目前还没有评论...

信息

ID
1976
时间
1000ms
内存
256MiB
难度
5
标签
递交数
64
已通过
25
上传者