Skip to content

Commit

Permalink
Merge pull request #2 from BrinzaBezrukoff/dev
Browse files Browse the repository at this point in the history
Rewrited some shit
  • Loading branch information
brinza888 authored Oct 26, 2021
2 parents 4afeb0d + f93d93f commit c3f3885
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 209 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
binaries/
bin/
tictactoe
*.o
*.vim
Expand Down
25 changes: 15 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
all: tictactoe
all: outdir tictactoe

tictactoe: main.o tictactoe.o minimax.o
gcc -o tictactoe main.o tictactoe.o minimax.o
tictactoe: bin/main.o bin/tictactoe.o bin/ai.o
gcc -o tictactoe bin/main.o bin/tictactoe.o bin/ai.o

main.o: main.c
gcc -c main.c
bin/main.o: main.c
gcc -c main.c -o bin/main.o

tictactoe.o: tictactoe.c
gcc -c tictactoe.c
bin/tictactoe.o: tictactoe.c
gcc -c tictactoe.c -o bin/tictactoe.o

minimax.o: minimax.c
gcc -c minimax.c
bin/ai.o: ai.c
gcc -c ai.c -o bin/ai.o

clean:
rm -rf *.o tictactoe
rm -rf bin tictactoe

outdir: bin

bin:
mkdir -p bin

107 changes: 107 additions & 0 deletions ai.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#include <stdlib.h>
#include <stdio.h>

#include "tictactoe.h"
#include "ai.h"


static int depthMode = MODE_EXPERT;


int randrange(int a, int b) {
return rand() % (b - a + 1) + a;
}


int getMode() {
return depthMode;
}

void setMode(int value) {
depthMode = value;
}


int getMoves(FieldT (*map)[SIZE][SIZE], Cell** moves, size_t* n) {
if (*n < 1 || *moves == NULL) {
*n = sizeof(Cell);
*moves = (Cell*) malloc(*n);
}
int count = 0;
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if ((*map)[i][j] != EMPTY) {
continue;
}
count++;
if (*n < count * sizeof(Cell)) {
*n += sizeof(Cell);
*moves = (Cell*) realloc(*moves, *n);
if (!moves) {
fprintf(stderr, "Not enough memory!\n");
exit(1);
}
}
(*moves)[count - 1] = Cell_create(i, j);
}
}
return count;
}


int ai_minimax(FieldT (*map)[SIZE][SIZE], Cell* turn, FieldT player, int depth) {
turn->row = -1;
turn->col = -1;

FieldT winner = check_winner(*map);
if (winner != EMPTY) {
return (winner == ZERO) ? 10 : -10;
}
if (is_draw(*map) || (depthMode != 0 && depth > depthMode)) {
return 0;
}

Cell* moves;
int count = 0;
size_t allocated = 0;
count = getMoves(map, &moves, &allocated);

Cell* ch_move;
int mnmx = (player == ZERO) ? -20 : 20; // optimized value
int res = 0; // last minimax value
int rw, cl; // make move

for (int i = 0; i < count; i++) {
rw = moves[i].row;
cl = moves[i].col;

(*map)[rw][cl] = player;

res = ai_minimax(map, turn, switch_player(player), depth + 1);

if ((player == ZERO && res > mnmx) || (player == CROSS && res < mnmx)) {
mnmx = res;
ch_move = moves + i;
}

(*map)[rw][cl] = EMPTY;
}

turn->row = ch_move->row;
turn->col = ch_move->col;

free(moves);

return mnmx;
}


void ai_random(FieldT (*map)[SIZE][SIZE], Cell* turn) {
Cell* moves;
size_t allocated = 0;
int count = 0;
count = getMoves(map, &moves, &allocated);
int r_i = randrange(0, count - 1);
*turn = moves[r_i];
}

27 changes: 27 additions & 0 deletions ai.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef AI_H
#define AI_H

#include "tictactoe.h"

#define MODE_EASY 1
#define MODE_MEDIUM 2
#define MODE_HARD 3
#define MODE_EXPERT 0


// random integer from a to b
int randrange(int a, int b);

// minimax depth control
int getMode();
void setMode(int value);

// service functions
int getMoves(FieldT (*map)[SIZE][SIZE], Cell** moves, size_t* n);

// turns functions
int ai_minimax(FieldT (*map)[SIZE][SIZE], Cell* turn, FieldT player, int depth);
void ai_random(FieldT (*map)[SIZE][SIZE], Cell* turn);

#endif

42 changes: 19 additions & 23 deletions main.c
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

#include "tictactoe.h"
#include "minimax.h"
#include "ai.h"


const char loadingS[] = {'-', '\\', '|', '/'};

void print_turn(enum field map[SIZE][SIZE], int turn, char ch) {
printf("===== %d TURN (%c) =====\n\n", turn, ch);
print_map(map);
printf("\n");
}

int main(int argc, char** argv){
enum field map[SIZE][SIZE];

Expand All @@ -28,7 +21,7 @@ int main(int argc, char** argv){
char current_ch; // current player char
printf("Who is the first? [X/O]: ");
scanf("%c", &current_ch);
enum field current = char2field(current_ch);
FieldT current = char2field(current_ch);

char ai_mode_ch;
int ai_mode;
Expand All @@ -55,38 +48,41 @@ int main(int argc, char** argv){

int turns_count = 1;

int row, column; // inputed cell
Cell turn = Cell_create(-1, -1); // turn cell
int ipt_r; // result of cell input

enum field winner = EMPTY;
enum bool is_running = TRUE;
FieldT winner = EMPTY;
bool is_running = true;

while (is_running) {
system("clear"); // clear last output

current_ch = field2char(current); // get char representation of player

print_turn(map, turns_count, current_ch); // print map and turn header
printf("===== %d TURN (%c) =====\n\n", turns_count, current_ch);
print_map(map);
printf("\n");

if (current == CROSS) { // Human turn
ipt_r = OK;
ipt_r = INPUT_OK;
do {
switch (ipt_r) {
case NOTONMAP: printf("Not on map!\n"); break;
case NOTEMPTY: printf("Already taken!\n"); break;
}
printf("Choose row and column to make turn:\n");
scanf("%d %d", &row, &column);
} while ((ipt_r = check_input(map, --row, --column)) != OK);
scanf("%d %d", &turn.row, &turn.col);
turn.row--;
turn.col--;
} while ((ipt_r = check_input(map, turn)) != INPUT_OK);
}
if (current == ZERO) { // AI turn
int val = minimax(&map, &row, &column, current, 0);
printf("Better %d turn: (%d, %d)\n", val, row+1, column+1);
else if (current == ZERO) { // AI turn
ai_minimax(&map, &turn, current, 0);
// ai_random(&map, &turn);
}

map[row][column] = current; // fill cell with player's symbol

print_map(map);
map[turn.row][turn.col] = current; // fill cell with player's symbol

winner = check_winner(map); // check winner

if (winner != EMPTY) { // if winner exists
Expand Down
101 changes: 0 additions & 101 deletions minimax.c

This file was deleted.

25 changes: 0 additions & 25 deletions minimax.h

This file was deleted.

Loading

0 comments on commit c3f3885

Please sign in to comment.