This commit is contained in:
Matej Hajduk 2025-06-11 12:22:15 +02:00
parent 419d8ead1f
commit f560dd6060
10 changed files with 254 additions and 0 deletions

15
du8/Makefile Normal file
View File

@ -0,0 +1,15 @@
CC=gcc
CFLAGS=-Wall -Wextra -std=c99
LDFLAGS=-lncurses
SRC=main.c game.c world.c
OBJ=$(SRC:.c=.o)
EXEC=tictactoe
all: $(EXEC)
$(EXEC): $(OBJ)
$(CC) -o $@ $^ $(LDFLAGS)
clean:
rm -f $(EXEC) $(OBJ)

117
du8/game.c Normal file
View File

@ -0,0 +1,117 @@
#include <stdio.h>
#include "game.h"
#include "world.h" // *
int select_game_mode() {
world_clear(); // *
world_print("Zvol si herny rezim:\n1. PvP\n2. PvE\n3. AI vs Human\n"); // *
char c = world_read_key(); // *
return c - '0';
}
void init_game(GameState *game, int mode) {
game->mode = mode;
game->current_player = 0;
game->moves_made = 0;
char default_symbols[MAX_PLAYERS] = {'X', 'O', 'A', 'B'};
for (int i = 0; i < MAX_PLAYERS; i++) {
game->symbols[i] = default_symbols[i];
}
if (mode == 1) {
game->board_size = 4;
game->num_players = 3;
} else if (mode == 2) {
game->board_size = 2; // začne s 2x2, rastie do 4x4
game->num_players = 2;
} else {
game->board_size = 3;
game->num_players = 2;
}
for (int y = 0; y < MAX_BOARD_SIZE; y++) {
for (int x = 0; x < MAX_BOARD_SIZE; x++) {
game->board[y][x] = ' ';
}
}
}
void draw_game(GameState *game) {
for (int y = 0; y < game->board_size; y++) {
for (int x = 0; x < game->board_size; x++) {
world_set_cursor(x * 4 + 1, y * 2 + 1); // *
world_print("%c", game->board[y][x]); // *
}
}
world_set_cursor(0, game->board_size * 2 + 2); // *
world_print("Na rade je hrac: %c\n", game->symbols[game->current_player]); // *
}
void handle_input(GameState *game) {
int x = 0, y = 0;
while (1) {
world_set_cursor(x * 4 + 1, y * 2 + 1); // *
char key = world_read_key(); // *
if (key == 'w' && y > 0) y--;
else if (key == 's' && y < game->board_size - 1) y++;
else if (key == 'a' && x > 0) x--;
else if (key == 'd' && x < game->board_size - 1) x++;
else if (key == ' ') {
if (game->board[y][x] == ' ') {
game->board[y][x] = game->symbols[game->current_player];
game->moves_made++;
break;
}
}
}
}
void computer_move(GameState *game) {
for (int y = 0; y < game->board_size; y++) {
for (int x = 0; x < game->board_size; x++) {
if (game->board[y][x] == ' ') {
game->board[y][x] = game->symbols[game->current_player];
game->moves_made++;
return;
}
}
}
}
int check_winner(GameState *game) {
int max_line = 0;
int size = game->board_size;
for (int p = 0; p < game->num_players; p++) {
char sym = game->symbols[p];
int longest = 0;
// Kontrola horizontálne, vertikálne a diagonálne
for (int y = 0; y < size; y++) {
int row = 0, col = 0;
for (int x = 0; x < size; x++) {
row = (game->board[y][x] == sym) ? row + 1 : 0;
col = (game->board[x][y] == sym) ? col + 1 : 0;
if (row > longest) longest = row;
if (col > longest) longest = col;
}
}
int diag1 = 0, diag2 = 0;
for (int i = 0; i < size; i++) {
diag1 = (game->board[i][i] == sym) ? diag1 + 1 : 0;
diag2 = (game->board[i][size - 1 - i] == sym) ? diag2 + 1 : 0;
if (diag1 > longest) longest = diag1;
if (diag2 > longest) longest = diag2;
}
if (longest >= 3) {
game->current_player = p;
return 1;
}
if (longest > max_line) {
max_line = longest;
}
}
return 0;
}

23
du8/game.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef GAME_H
#define GAME_H
#define MAX_PLAYERS 4
#define MAX_BOARD_SIZE 10
typedef struct {
int board_size;
int num_players;
int mode; // 1 = PvP, 2 = PvE, 3 = AI vs Human
int current_player;
int moves_made;
char board[MAX_BOARD_SIZE][MAX_BOARD_SIZE];
char symbols[MAX_PLAYERS];
} GameState;
int select_game_mode();
void init_game(GameState *game, int mode);
void draw_game(GameState *game);
void handle_input(GameState *game);
void computer_move(GameState *game);
int check_winner(GameState *game);
#endif

BIN
du8/game.o Normal file

Binary file not shown.

37
du8/main.c Normal file
View File

@ -0,0 +1,37 @@
#include <stdio.h>
#include "game.h"
#include "world.h" // *
int main() {
world_init(); // * inicializácia world
GameState game;
int mode = select_game_mode();
init_game(&game, mode);
while (1) {
world_clear(); // * vyčistenie obrazovky
draw_game(&game); // * vykreslenie hracieho poľa
if (check_winner(&game)) {
world_print("\nVyhral hrac %c!\n", game.symbols[game.current_player]); // * výpis
break;
} else if (game.moves_made >= game.board_size * game.board_size) {
world_print("\nRemiza!\n"); // * výpis
break;
}
if (game.mode == 3 && game.current_player == 1) {
computer_move(&game);
} else {
handle_input(&game); // * ovládanie
}
game.current_player = (game.current_player + 1) % game.num_players;
}
world_print("Stlač akúkoľvek klávesu pre ukončenie...\n"); // * výpis
world_read_key(); // * caka na vstup
world_end(); // *
return 0;
}

BIN
du8/main.o Normal file

Binary file not shown.

BIN
du8/tictactoe Executable file

Binary file not shown.

39
du8/world.c Normal file
View File

@ -0,0 +1,39 @@
#include <ncurses.h>
#include <stdarg.h>
#include <stdio.h>
#include "world.h"
void world_init() {
initscr(); // inicializácia ncurses
raw(); // vypne linkový režim (bez enter)
keypad(stdscr, TRUE); // povolí šípky
noecho(); // nevypisuje znaky
curs_set(1); // viditeľný kurzor
}
void world_end() {
endwin(); // ukončí ncurses
}
void world_clear() {
clear(); // vyčistí obrazovku
refresh(); // prekreslí
}
void world_print(const char *fmt, ...) {
va_list args;
va_start(args, fmt);
vw_printw(stdscr, fmt, args);
va_end(args);
refresh();
}
void world_set_cursor(int x, int y) {
move(y, x);
refresh();
}
char world_read_key() {
return getch(); // načítanie jedného znaku
}

23
du8/world.h Normal file
View File

@ -0,0 +1,23 @@
#ifndef WORLD_H
#define WORLD_H
// Inicializuje (ncurses).
void world_init();
// Ukončí ncurses
void world_end();
// Vymaže obrazovku.
void world_clear();
// Vypíše ynak pozíciu kurzora.
void world_print(const char *fmt, ...);
// Presunie kurzor na (x, y).
void world_set_cursor(int x, int y);
// Prečíta jeden ynak
char world_read_key();
#endif

BIN
du8/world.o Normal file

Binary file not shown.