Nimbin2git.christianimmanuel.de / Games / vier_gewinnt / main.c

vier_gewinnt git · main

git clone https://git.christianimmanuel.de/games/vier_gewinnt.gitwget https://git.christianimmanuel.de/games/vier_gewinnt/archive/vier_gewinnt.tar.gz
main.c 5 KB · 177 lines raw
#include <stdlib.h>
#include <stdio.h>
// #include <sys/ioctl.h>  // window size
// #include <unistd.h>     // window size

#include "keypress.c"

#include <termios.h>

#define ROWS_MAX 12
#define COLS_MAX 12

// disable user input
void disable_input_buffering() {
    struct termios t;
    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag &= ~(ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &t);
}

// enable user input
void enable_input_buffering() {
    struct termios t;
    tcgetattr(STDIN_FILENO, &t);
    t.c_lflag |= (ICANON | ECHO);
    tcsetattr(STDIN_FILENO, TCSANOW, &t);
}


#ifdef _WIN32
#define WINDOWS
#include <windows.h>
#else
#include <time.h>
void sleep_seconds(double seconds) {
    clock_t start_time = clock();
    double elapsed_time;

    do {
        elapsed_time = ((double)(clock() - start_time)) / CLOCKS_PER_SEC;
    } while (elapsed_time < seconds);
}
#endif


void draw_game(char game_area[COLS_MAX][ROWS_MAX]) {
    system("clear");

    printf("\n\n");
    printf("\n┌───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┬───┐\n");
    for (int i = 0; i < COLS_MAX; i++) {
        printf("│");
        for (int k = 0; k < ROWS_MAX; k++)
            printf(" %c │", game_area[i][k]);
        if (i != ROWS_MAX-1)
            printf("\n├───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┼───┤\n");
        else printf("\n└───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┴───┘\n");
    }
}

void draw_area_pos(char player, int x, int y) {
    if (player == 'x')
       printf("\033[38;5;28m");
    else if (player == 'o')
       printf("\033[38;5;124m");
    printf("\033[%d;%dH%c\033[0m", y, x, player);  
}

void draw_in_pos(int pos, char player) {
   printf("\033[%d;%dH                                                 ", 3, 0);  
   printf("\033[%d;%dH", 3, pos*3+pos-2);  
   if (player == 'x') 
       printf("\033[48;5;28m");
   else 
       printf("\033[48;5;124m");
   printf(" %c \033[0m", player);
   printf("\033[%d;%dH", 3, pos*3+pos-1);  
}

void draw_drop(char area[COLS_MAX][ROWS_MAX], char player, int pos) {
    disable_input_buffering();
    double sleep = 0.1;
    int i;
    for (i = 0; i < ROWS_MAX; i++){
        if (area[pos-1][i] != '.')
            break;
        draw_area_pos(player, 3*pos+pos-1, 5+2*i);
        fflush(stdout);
#ifdef WINDOWS
Sleep((int)sleep * 100);
#else
sleep_seconds(sleep/10);
#endif
        draw_area_pos('.', 3*pos+pos-1, 5+2*i);
    }

    enable_input_buffering();
}

int set_drop(char area[COLS_MAX][ROWS_MAX], char player, int pos) {
    int i;
    for (i = 0; i < ROWS_MAX && area[pos-1][i] == '.'; i++);
    if (i > 0)
        area[pos-1][i-1] = player;
    return i-1;
}


char check_winner(char area[COLS_MAX][ROWS_MAX], int x, int y) {
    char c = area[x][y];
    for (int i = -3; i < 1; i++) {
        char m[] = {0,0,0,0};
        for (int k = 0; k < 4; k++) {
            if (x+i+k > -1 && x+i+k < ROWS_MAX && area[x+i+k][y] == c) m[0]++;
            if (y+i+k > -1 && y+i+k < COLS_MAX && area[x][y+i+k] == c) m[1]++;
            if (x+i+k > -1 && x+i+k < ROWS_MAX && 
                    y+i+k > -1 && y+i+k < COLS_MAX && 
                    area[x+i+k][y+i+k] == c) m[2]++;
            if (x+i+k > -1 && x+i+k < ROWS_MAX && 
                    y-i-k > -1 && y-i-k < COLS_MAX && 
                    area[x+i+k][y-i-k] == c) m[3]++;
        }
        for (int j = 0; j < 4; j++) {
            if (m[j] == 4) return c;
        }
    }
    return '.';
    
}

void draw_winner(char winner) {
    printf("\033[48;5;231m");
    (winner == 'x') ?
        printf("\033[38;5;28m") :
        printf("\033[38;5;124m");
    printf("\033[%d;%dH!!! Winner: %c !!!\033[0m", ROWS_MAX*3/2, COLS_MAX*3/2, winner);  
}

int main() {
    char game_area[COLS_MAX][ROWS_MAX];

    for (int i = 0; i < COLS_MAX; i++)
        for (int k = 0; k < ROWS_MAX; k++)
            game_area[i][k] = '.';

    draw_game(game_area);
    char key = '0';
    int in_pos = 1;
    char player = 'x';
    while (1) {
        key = '0';
        while (key != 10) {
            draw_in_pos(in_pos, player);
            key = get_keypress();
            switch (key) {
                case 'a':
                    in_pos = in_pos == 1 ? COLS_MAX : in_pos-1;
                    break;
                case 'd':
                    in_pos = in_pos == COLS_MAX ? 1 : in_pos+1;
                    break;
            }
        }
        int drop_y = set_drop(game_area, player, in_pos);
        if (drop_y > -1) {
            // animate drop
            draw_drop(game_area, player, in_pos);
            // draw final position
            draw_area_pos(player, 3*in_pos+in_pos-1, 5+2*(drop_y));
            // switch player
            char winner = check_winner(game_area, in_pos-1, drop_y);
            if (winner != '.')
                draw_winner(winner);
            player = player == 'x' ? 'o' : 'x';
        }
    }
}