// ===== CodeLab: C++ 小游戏④:弹球 Pong(控制台动画) =====
// 来源: https://aoerliang.dpdns.org/articles/game-cpp-pong
// 以下代码片段按文章出现顺序拼接, 共 6 段

// ----- 片段 1 (cpp) -----
#include <iostream>
#include <thread>
#include <chrono>
#include <cstdlib>
#include <termios.h>
#include <fcntl.h>
#include <unistd.h>

const int W = 60, H = 20;
int ballX = W / 2, ballY = H / 2;
int vx = 1, vy = 1;          // 每帧移动 1 格
int paddleX = W / 2 - 3;     // 挡板左端坐标
const int paddleW = 6;
int score = 0;

// ----- 片段 2 (cpp) -----
void setNonBlocking() {
    int flags = fcntl(STDIN_FILENO, F_GETFL, 0);
    fcntl(STDIN_FILENO, F_SETFL, flags | O_NONBLOCK);
}

void hideEcho() {
    termios t;
    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag &= ~(ICANON | ECHO);   // 关行缓冲与回显
    tcsetattr(STDIN_FILENO, TCSANOW, &t);
}

int readKey() {
    char c;
    if (read(STDIN_FILENO, &c, 1) == 1) return c;
    return -1;
}

// ----- 片段 3 (cpp) -----
void draw() {
    std::cout << "\033[2J\033[H";   // 清屏 + 光标回原点
    for (int y = 0; y < H; ++y) {
        for (int x = 0; x < W; ++x) {
            if (x == ballX && y == ballY) std::cout << "O";
            else if (y == H - 2 && x >= paddleX && x < paddleX + paddleW)
                std::cout << "=";
            else if (x == 0 || x == W - 1) std::cout << "|";
            else if (y == 0) std::cout << "-";
            else std::cout << " ";
        }
        std::cout << "\n";
    }
    std::cout << "得分:" << score << "  a/d 移动,q 退出\n";
}

// ----- 片段 4 (cpp) -----
void update() {
    ballX += vx;
    ballY += vy;
    if (ballX <= 1 || ballX >= W - 2) vx = -vx;   // 左右墙
    if (ballY <= 1) vy = -vy;                      // 上墙
    if (ballY == H - 3) {                          // 挡板行
        if (ballX >= paddleX && ballX < paddleX + paddleW) {
            vy = -vy;
            ++score;
        } else {
            std::cout << "游戏结束!得分:" << score << "\n";
            std::exit(0);
        }
    }
    if (ballY >= H - 1) ballY = H - 2;            // 出界保护
}

// ----- 片段 5 (cpp) -----
int main() {
    setNonBlocking();
    hideEcho();
    while (true) {
        int key = readKey();
        if (key == 'a' || key == 'A') paddleX -= 2;
        else if (key == 'd' || key == 'D') paddleX += 2;
        else if (key == 'q') break;
        if (paddleX < 1) paddleX = 1;
        if (paddleX + paddleW > W - 1) paddleX = W - 1 - paddleW;
        update();
        draw();
        std::this_thread::sleep_for(std::chrono::milliseconds(80));
    }
    return 0;
}

// ----- 片段 6 (bash) -----
g++ -std=c++17 -o pong pong.cpp
./pong
