Untitled

mail@pastecode.io avatar
unknown
plain_text
5 months ago
12 kB
2
Indexable
 Tôi sẽ in ra toàn bộ project bao gồm cả xử lý next tetromino. Đây là các file trong project:

Tetromino.h:

```cpp
#pragma once
#include <SFML/Graphics.hpp>

struct Point
{
    int x, y;
};

class Tetromino {
public:
    Tetromino();
    void reset(int colorNum);
    void move(int dx, int dy);
    void rotate();
    bool checkCollision(int field[23][10]);
    void draw(sf::RenderWindow& window, sf::Sprite& sprite, int offsetX, int offsetY);
    Point getPosition(int index) const;
    int getColorNum() const;

private:
    Point a[4];
    int colorNum;
    static const int figures[7][4];
};
```

Tetromino.cpp:

```cpp
#include "Tetromino.h"
#include <cstdlib>

const int Tetromino::figures[7][4] = {
    1,3,5,7, // I
    2,4,5,7, // Z
    3,5,4,6, // S
    3,5,4,7, // T
    2,3,5,7, // L
    3,5,7,6, // J
    2,3,4,5, // O
};

Tetromino::Tetromino() {
    reset(1 + rand() % 7);
}

void Tetromino::reset(int colorNum) {
    this->colorNum = colorNum;
    int n = rand() % 7;
    for (int i = 0; i < 4; i++) {
        a[i].x = figures[n][i] / 2;
        a[i].y = figures[n][i] % 2;
    }
}

void Tetromino::move(int dx, int dy) {
    for (int i = 0; i < 4; i++) {
        a[i].x += dx;
        a[i].y += dy;
    }
}

void Tetromino::rotate() {
    Point p = a[1];
    for (int i = 0; i < 4; i++) {
        int x = a[i].y - p.y;
        int y = a[i].x - p.x;
        a[i].x = p.x - x;
        a[i].y = p.y + y;
    }
}

bool Tetromino::checkCollision(int field[23][10]) {
    for (int i = 0; i < 4; i++) {
        if (a[i].x < 0 || a[i].x >= 10 || a[i].y >= 23) return false;
        else if (field[a[i].y][a[i].x]) return false;
    }
    return true;
}

void Tetromino::draw(sf::RenderWindow& window, sf::Sprite& sprite, int offsetX, int offsetY) {
    for (int i = 0; i < 4; i++) {
        sprite.setTextureRect(sf::IntRect(colorNum * 18, 0, 18, 18));
        sprite.setPosition(a[i].x * 36 + offsetX, a[i].y * 36 + offsetY);
        window.draw(sprite);
    }
}

Point Tetromino::getPosition(int index) const {
    return a[index];
}

int Tetromino::getColorNum() const {
    return colorNum;
}
```

Game.h:

```cpp
#pragma once
#include <SFML/Graphics.hpp>
#include "Tetromino.h"
#include "Score.h"

class Game {
public:
    Game();
    void run();

private:
    void processEvents();
    void update(float deltaTime);
    void render();
    void resetGame();
    void checkLines();
    bool isDraw();
    bool checkI();
    bool checkO();

    sf::RenderWindow window;
    sf::Texture t1, t2, t3;
    sf::Sprite s, frame;
    sf::RectangleShape background;
    sf::Font font;
    sf::Text scoreText, highScoreText, text1, text2, gameOverText, playAgainText;
    sf::RectangleShape playfieldBoundary, nextTempoBoundary, scoreBoundary, highScoreBoundary;
    sf::RectangleShape gridLines[230];

    Tetromino currentTetromino;
    Tetromino nextTetromino;
    Score score;

    int field[23][10] = {0};
    int dx;
    bool rotate;
    float timer, delay;
    bool gameOver;

    static const int M = 23;
    static const int N = 10;
    static const int blockSize = 36;
    static const int playfieldWidth = 360;
    static const int playfieldHeight = 720;
    static const int windowWidth = 720;
    static const int windowHeight = 960;
};
```

Game.cpp:

```cpp
#include "Game.h"
#include <cstdlib>
#include <ctime>
#include <string>

Game::Game() : window(sf::VideoMode(windowWidth, windowHeight), "Tetris"), score() {
    srand(time(0));
    
    t1.loadFromFile("images/tiles.png");
    t2.loadFromFile("images/background.png");
    t3.loadFromFile("images/frame.png");
    
    s.setTexture(t1);
    frame.setTexture(t3);
    s.setScale(2, 2);
    
    background.setSize(sf::Vector2f(windowWidth, windowHeight));
    background.setFillColor(sf::Color(200, 220, 255, 180));
    
    font.loadFromFile("Roboto-Regular.ttf");
    
    scoreText.setFont(font);
    highScoreText.setFont(font);
    text1.setFont(font);
    text2.setFont(font);
    gameOverText.setFont(font);
    playAgainText.setFont(font);

    text1.setString("Score");
    text2.setString("High");

    scoreText.setFillColor(sf::Color(35, 47, 68));
    highScoreText.setFillColor(sf::Color(35, 47, 68));
    text1.setFillColor(sf::Color(35, 47, 68));
    text2.setFillColor(sf::Color(35, 47, 68));
    gameOverText.setFillColor(sf::Color::Red);
    playAgainText.setFillColor(sf::Color(35, 47, 68));

    scoreText.setCharacterSize(20);
    highScoreText.setCharacterSize(20);
    text1.setCharacterSize(20);
    text2.setCharacterSize(20);
    gameOverText.setCharacterSize(30);
    playAgainText.setCharacterSize(20);

    scoreText.setPosition(500, 20);
    highScoreText.setPosition(500, 50);
    gameOverText.setPosition(80, 440);
    playAgainText.setPosition(140, 520);

    for (int i = 3; i < M; ++i)
    {
        for (int j = 0; j < N; ++j)
        {
            gridLines[i * N + j].setSize(sf::Vector2f(blockSize - 1, blockSize - 1));
            gridLines[i * N + j].setFillColor(sf::Color::Transparent);
            gridLines[i * N + j].setOutlineThickness(1);
            gridLines[i * N + j].setOutlineColor(sf::Color::Black);
            gridLines[i * N + j].setPosition(j * blockSize, i * blockSize);
            gridLines[i * N + j].move(blockSize, 2 * blockSize);
        }
    }

    playfieldBoundary.setSize(sf::Vector2f(playfieldWidth, playfieldHeight));
    playfieldBoundary.setFillColor(sf::Color(200, 220, 255));
    playfieldBoundary.setOutlineThickness(4);
    playfieldBoundary.setOutlineColor(sf::Color(100, 100, 150));
    playfieldBoundary.setPosition(blockSize, 4 * blockSize);

    nextTempoBoundary.setSize(sf::Vector2f(playfieldWidth / 1.5f, playfieldHeight / 5.0f));
    nextTempoBoundary.setFillColor(sf::Color(200, 220, 255));
    nextTempoBoundary.setOutlineThickness(4);
    nextTempoBoundary.setOutlineColor(sf::Color(100, 100, 150));
    nextTempoBoundary.setPosition(blockSize + blockSize + playfieldWidth, 4 * blockSize);

    scoreBoundary.setSize(sf::Vector2f(playfieldWidth / 1.5f, playfieldHeight / 12.0f));
    scoreBoundary.setFillColor(sf::Color(200, 220, 255));
    scoreBoundary.setOutlineThickness(4);
    scoreBoundary.setOutlineColor(sf::Color(100, 100, 150));
    scoreBoundary.setPosition(blockSize + blockSize + playfieldWidth, 4 * blockSize + playfieldHeight * 2 / 5 + blockSize);

    highScoreBoundary.setSize(sf::Vector2f(playfieldWidth / 1.5f, playfieldHeight / 12.0f));
    highScoreBoundary.setFillColor(sf::Color(200, 220, 255));
    highScoreBoundary.setOutlineThickness(4);
    highScoreBoundary.setOutlineColor(sf::Color(100, 100, 150));
    highScoreBoundary.setPosition(blockSize + blockSize + playfieldWidth, 4 * blockSize + playfieldHeight * 2 / 5 + blockSize + playfieldHeight / 12 + 8);

    resetGame();
}

void Game::run() {
    sf::Clock clock;
    while (window.isOpen()) {
        float deltaTime = clock.restart().asSeconds();
        processEvents();
        update(deltaTime);
        render();
    }
}

void Game::processEvents() {
    sf::Event e;
    while (window.pollEvent(e)) {
        if (e.type == sf::Event::Closed)
            window.close();

        if (gameOver) {
            if (e.type == sf::Event::KeyPressed && e.key.code == sf::Keyboard::Space)
                resetGame();
            continue;
        }

        if (e.type == sf::Event::KeyPressed) {
            if (e.key.code == sf::Keyboard::Up) rotate = true;
            else if (e.key.code == sf::Keyboard::Left) dx = -1;
            else if (e.key.code == sf::Keyboard::Right) dx = 1;
        }
    }
}

void Game::update(float deltaTime) {
    if (gameOver) return;

    timer += deltaTime;
    if (sf::Keyboard::isKeyPressed(sf::Keyboard::Down)) delay = 0.05;

    if (dx) {
        currentTetromino.move(dx, 0);
        if (!currentTetromino.checkCollision(field)) currentTetromino.move(-dx, 0);
    }

    if (rotate) {
        currentTetromino.rotate();
        if (!currentTetromino.checkCollision(field)) {
            currentTetromino.rotate();
            currentTetromino.rotate();
            currentTetromino.rotate();
        }
    }

    if (timer > delay) {
        currentTetromino.move(0, 1);
        if (!currentTetromino.checkCollision(field)) {
            currentTetromino.move(0, -1);
            for (int i = 0; i < 4; i++) {
                Point p = currentTetromino.getPosition(i);
                field[p.y][p.x] = currentTetromino.getColorNum();
            }
            currentTetromino = nextTetromino;
            nextTetromino.reset(1 + rand() % 7);
            if (!currentTetromino.checkCollision(field)) {
                gameOver = true;
            }
        }
        timer = 0;
    }

    checkLines();

    dx = 0;
    rotate = false;
    delay = 0.3;
}

void Game::render() {
    window.clear(sf::Color::White);
    window.draw(background);
    window.draw(playfieldBoundary);
    window.draw(nextTempoBoundary);
    window.draw(scoreBoundary);
    window.draw(highScoreBoundary);

    for (int i = 3; i < M; i++)
        for (int j = 0; j < N; j++)
        {
            if (field[i][j] == 0) continue;
            s.setTextureRect(sf::IntRect(field[i][j] * 18, 0, 18, 18));
            s.setPosition(j * blockSize + blockSize, i * blockSize + blockSize);
            window.draw(s);
        }

    currentTetromino.draw(window, s, blockSize, blockSize);
    nextTetromino.draw(window, s, blockSize + blockSize + playfieldWidth + blockSize, 4 * blockSize + blockSize);

    scoreText.setString(std::to_string(score.getScore()));
    highScoreText.setString(std::to_string(score.getHighScore()));
    window.draw(scoreText);
    window.draw(highScoreText);
    window.draw(text1);
    window.draw(text2);

    if (gameOver) {
        window.draw(gameOverText);
        playAgainText.setString("Press SPACE to Play Again");
        window.draw(playAgainText);
    }

    window.display();
}

void Game::resetGame() {
    for (int i = 0; i < M; i++)
        for (int j = 0; j < N; j++)
            field[i][j] = 0;

    score.reset();
    currentTetromino.reset(1 + rand() % 7);
    nextTetromino.reset(1 + rand() % 7);
    timer = 0;
    delay = 0.3;
    gameOver = false;
}

void Game::checkLines() {
    int k = M - 1;
    for (int i = M - 1; i >= 0; i--)
    {
        int count = 0;
        for (int j = 0; j < N; j++)
        {
            if (field[i][j]) count++;
            field[k][j] = field[i][j];
        }
        if (count < N) k--;
        else score.addPoints(100);
    }
}

bool Game::isDraw() {
    for (int i = 0; i < 4; i++)
        if (currentTetromino.getPosition(i).y < 3) return false;
    return true;
}

 Xin lỗi vì sự cố. Tôi sẽ tiếp tục từ đoạn bị cắt:

```cpp
bool Game::checkO() {
    return (nextTetromino.getPosition(0).y == 0 &&
            nextTetromino.getPosition(1).y == 1 &&
            nextTetromino.getPosition(2).y == 0 &&
            nextTetromino.getPosition(3).y == 1);
}
```

Score.h:

```cpp
#pragma once

class Score {
public:
    Score();
    void addPoints(int points);
    int getScore() const;
    int getHighScore() const;
    void reset();

private:
    int score;
    int highScore;
};
```

Score.cpp:

```cpp
#include "Score.h"

Score::Score() : score(0), highScore(0) {}

void Score::addPoints(int points) {
    score += points;
    if (score > highScore) {
        highScore = score;
    }
}

int Score::getScore() const {
    return score;
}

int Score::getHighScore() const {
    return highScore;
}

void Score::reset() {
    score = 0;
}
```

main.cpp:

```cpp
#include "Game.h"

int main() {
    Game game;
    game.run();
    return 0;
}
```

Đây là toàn bộ project, bao gồm cả xử lý next tetromino. Project này đã được tổ chức thành các class riêng biệt để dễ quản lý và mở rộng. Class Game xử lý phần lớn logic của trò chơi, bao gồm cả việc hiển thị và cập nhật next tetromino.

Các tính năng chính:
1. Hiển thị khối tetromino hiện tại và khối tiếp theo
2. Xử lý di chuyển và xoay khối
3. Kiểm tra va chạm và xóa các hàng đã hoàn thành
4. Tính điểm và hiển thị điểm cao
5. Xử lý kết thúc trò chơi và reset

Để chạy game, bạn chỉ cần biên dịch tất cả các file và chạy file main.cpp. Đảm bảo rằng bạn đã cài đặt thư viện SFML và liên kết nó đúng cách trong project của bạn.
Leave a Comment