#include #include #include #define BALL_SYMBOL "O" #define BORDER "#" #define PADDLE "||" struct Ball { int px, py, dx, dy; }; struct Paddle { int px, py, length; }; int main(void) { int sleep_time = 20000; int time = 0; int hits = 0, misses = 0, best = 0, streak = 0, quit = 0, frame = 1, left_score = 0, right_score = 0; int max_y, max_x; struct Ball ball; struct Paddle paddle1, paddle2; int i; system("clear"); initscr(); curs_set(0); cbreak(); noecho(); nodelay(stdscr, 1); start_color(); init_pair(1, COLOR_CYAN, COLOR_BLACK); init_pair(2, COLOR_YELLOW, COLOR_BLACK); init_pair(3, COLOR_GREEN, COLOR_BLACK); getmaxyx(stdscr, max_y, max_x); // Initialize ball ball.py = max_y / 2; ball.px = max_x / 2; ball.dy = rand() & 1 ? 1 : -1; ball.dx = rand() & 1 ? 1 : -1; // Initialize paddles paddle1.length = 6; paddle1.py = (max_y / 2) - (paddle1.length / 2); paddle1.px = max_x - 3; paddle2.length = 6; paddle2.py = (max_y / 2) - (paddle2.length / 2); paddle2.px = 1; // Game loop while (!quit) { getmaxyx(stdscr, max_y, max_x); // Timer if (frame % (1000000 / sleep_time) == 0) { time++; } // Draw stats mvprintw(0, 0, "Hits: %d Misses: %d Streak: %d Best: %d Time: %d | Score left: %d Score right: %d | ", hits, misses, streak, best, time, left_score, right_score); // Draw controls mvprintw(max_y - 1, 0, "Controls: left up -> \',\' left down -> \'o\'; right up -> \'r\' right down -> \'n\'; speed up -> \'f\' slow down -> \'s\'; quit -> \'Q\'"); // Draw borders attron(COLOR_PAIR(3)); for (i = 0; i < max_x; i++) { mvprintw(1, i, BORDER); mvprintw(max_y - 2, i, BORDER); } attroff(COLOR_PAIR(3)); // Clear old paddles for (i = 2; i < max_y - 2; i++) { mvprintw(i, paddle1.px, " "); mvprintw(i, paddle2.px, " "); } // Draw paddles attron(COLOR_PAIR(1)); for (i = 0; i < paddle1.length; i++) { mvprintw(paddle1.py + i, paddle1.px, PADDLE); } for (i = 0; i < paddle2.length; i++) { mvprintw(paddle2.py + i, paddle2.px, PADDLE); } attroff(COLOR_PAIR(1)); // Clear previous ball position mvprintw(ball.py, ball.px, " "); // Ball collisions if ((ball.py + ball.dy) < 2 || (ball.py + ball.dy) > max_y - 3) { ball.dy *= -1; } // Right paddle collision (Player 1) if ((ball.px + ball.dx == paddle1.px) && (ball.py + ball.dy >= paddle1.py) && (ball.py + ball.dy < paddle1.py + paddle1.length)) { hits++; streak++; if (streak > best) best = streak; ball.dx *= -1; } // Left paddle collision (Player 2) if ((ball.px + ball.dx == paddle2.px + 1) && (ball.py + ball.dy >= paddle2.py) && (ball.py + ball.dy < paddle2.py + paddle2.length)) { hits++; streak++; if (streak > best) best = streak; ball.dx *= -1; } // Ball goes past right paddle if (ball.px > max_x) { left_score++; misses++; streak = 0; ball.py = max_y / 2; ball.px = max_x / 2; ball.dy = rand() & 1 ? 1 : -1; ball.dx = rand() & 1 ? 1 : -1; } // Ball goes past Player 2's paddle (left side) if (ball.px < 1) { right_score++; misses++; streak = 0; ball.py = max_y / 2; ball.px = max_x / 2; ball.dy = rand() & 1 ? 1 : -1; ball.dx = rand() & 1 ? 1 : -1; } // Ball movement if (frame % 4 == 0) { ball.py += ball.dy; ball.px += ball.dx; } // Draw ball attron(COLOR_PAIR(2)); mvprintw(ball.py, ball.px, BALL_SYMBOL); attroff(COLOR_PAIR(2)); // Input switch (getch()) { case 'r': // Player 1 up if (paddle1.py > 2) paddle1.py -= 1; break; case 'n': // Player 1 down if (paddle1.py + paddle1.length < max_y - 2) paddle1.py += 1; break; case ',': // Player 2 up if (paddle2.py > 2) paddle2.py -= 1; break; case 'o': // Player 2 down if (paddle2.py + paddle2.length < max_y - 2) paddle2.py += 1; break; case 'f': // Speed up if (sleep_time > 1000) { sleep_time -= 1000; } break; case 's': // Slow down if (sleep_time < 30000) { sleep_time += 1000; } break; case 'Q': quit = 1; break; } frame++; usleep(sleep_time); } // Exit endwin(); system("clear"); return 0; }