본문 바로가기
SW/ETC

우분투 Ubuntu 24.04 테트리스 게임 코딩 연습(1)

by bigju 2025. 10. 16.
반응형

우분투 24버전에 심심해서 테트리스 코딩

c언어로 만들어봄

#include <ncurses.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>

#define WIDTH 10
#define HEIGHT 20

int field[HEIGHT][WIDTH] = {0};
int shapes[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
};

typedef struct {
    int x, y;
    int shape;
    int rotation;
} Piece;

Piece current;
int score = 0;

void draw_field() {
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            move(y + 1, x * 2 + 1);
            if (field[y][x])
                attron(COLOR_PAIR(field[y][x]));
            printw(field[y][x] ? "[]" : "  ");
            if (field[y][x])
                attroff(COLOR_PAIR(field[y][x]));
        }
    }
}

int fits(int shape, int rotation, int posX, int posY) {
    for (int i = 0; i < 4; i++) {
        int px = (shapes[shape][i] % 2);
        int py = (shapes[shape][i] / 2);
        for (int r = 0; r < rotation; r++) {
            int temp = px;
            px = py;
            py = -temp + 1;
        }
        int x = posX + px;
        int y = posY + py;
        if (x < 0 || x >= WIDTH || y >= HEIGHT || (y >= 0 && field[y][x]))
            return 0;
    }
    return 1;
}

void place_piece() {
    for (int i = 0; i < 4; i++) {
        int px = shapes[current.shape][i] % 2;
        int py = shapes[current.shape][i] / 2;
        for (int r = 0; r < current.rotation; r++) {
            int temp = px;
            px = py;
            py = -temp + 1;
        }
        int x = current.x + px;
        int y = current.y + py;
        if (y >= 0)
            field[y][x] = current.shape + 1;
    }
}

void remove_lines() {
    for (int y = HEIGHT - 1; y >= 0; y--) {
        int full = 1;
        for (int x = 0; x < WIDTH; x++) {
            if (!field[y][x]) {
                full = 0;
                break;
            }
        }
        if (full) {
            score += 100;
            for (int ty = y; ty > 0; ty--) {
                for (int tx = 0; tx < WIDTH; tx++)
                    field[ty][tx] = field[ty - 1][tx];
            }
            for (int tx = 0; tx < WIDTH; tx++)
                field[0][tx] = 0;
            y++;
        }
    }
}

void draw_piece(Piece p, int erase) {
    for (int i = 0; i < 4; i++) {
        int px = shapes[p.shape][i] % 2;
        int py = shapes[p.shape][i] / 2;
        for (int r = 0; r < p.rotation; r++) {
            int temp = px;
            px = py;
            py = -temp + 1;
        }
        int x = p.x + px;
        int y = p.y + py;
        if (y >= 0) {
            move(y + 1, x * 2 + 1);
            if (!erase) attron(COLOR_PAIR(p.shape + 1));
            printw(erase ? "  " : "[]");
            if (!erase) attroff(COLOR_PAIR(p.shape + 1));
        }
    }
}

int main() {
    initscr();
    noecho();
    curs_set(FALSE);
    keypad(stdscr, TRUE);
    nodelay(stdscr, TRUE);
    start_color();

    for (int i = 1; i <= 7; i++)
        init_pair(i, i, 0);

    srand(time(0));

    current.shape = rand() % 7;
    current.rotation = 0;
    current.x = WIDTH / 2 - 1;
    current.y = 0;

    int delay = 500000;
    int tick = 0;
    int game_over = 0;

    while (!game_over) {
        clear();
        mvprintw(0, 1, "Score: %d", score);
        draw_field();
        draw_piece(current, 0);
        refresh();
        usleep(50000);
        tick += 50000;

        int ch = getch();
        Piece temp = current;

        if (ch == KEY_LEFT) temp.x--;
        else if (ch == KEY_RIGHT) temp.x++;
        else if (ch == KEY_UP) temp.rotation = (temp.rotation + 1) % 4;
        else if (ch == KEY_DOWN) tick = delay;
        else if (ch == 'q' || ch == 'Q') break;

        if (fits(temp.shape, temp.rotation, temp.x, temp.y))
            current = temp;

        if (tick >= delay) {
            tick = 0;
            Piece next = current;
            next.y++;
            if (fits(next.shape, next.rotation, next.x, next.y))
                current = next;
            else {
                place_piece();
                remove_lines();
                current.shape = rand() % 7;
                current.rotation = 0;
                current.x = WIDTH / 2 - 1;
                current.y = 0;
                if (!fits(current.shape, current.rotation, current.x, current.y))
                    game_over = 1;
            }
        }
    }

    clear();
    mvprintw(10, 5, "GAME OVER");
    mvprintw(11, 5, "Final Score: %d", score);
    mvprintw(13, 5, "Press any key to exit...");
    refresh();
    nodelay(stdscr, FALSE);
    getch();

    endwin();
    return 0;
}

 

실행 방법 :

gcc tetris.c -o tetris -lncurses

./tetris.c

 

반응형

댓글

메인으로가기


    

Big Ju

IT Engineer


항상 답을 위해 노력하는

엔지니어입니다.

 

 

    


 UP!