Skip to content
Snippets Groups Projects
puissance4.c 12.14 KiB
#include "puissance4.h"
#include <stdint.h>
#include <stdio.h>

grid game;

/***********************************
 * function     : Create_grid2D
 * arguments    : taille de grille hauteur x largeur
 *
 * return value : cell_t** -> la grille mise à jour et allouée
 * 		initialise les valeurs de la grille
 * 		et alloue la mémoire dynamiquement
 ***********************************/
struct cell **Create_grid2D(){
	struct cell** cells = malloc(game.width*sizeof(struct cell*));
	for(int k =0; k<game.width; k++){
		cells[k] = malloc(game.height*sizeof(struct cell));
	}
	//initialise les positions et les valeurs de base
	for(int i = 0; i<game.width; i++){
		for(int j=0; j<game.height; j++){
			cells[i][j].symbol = EMPTY;
			cells[i][j].i_pos = i;
			cells[i][j].j_pos = j;
		}
	}
	return cells;
}

void print_cells(struct cell **cell){
	for(int i=0; i<game.width; i++){
		for(int j=0; j<game.height; j++){
			printf("%d, ", cell[i][j].symbol);
		}
		printf("\n");
	}
}
void print_gameCells(){
	print_cells(game.cells);
}

void init_puissance4(int height, int width){
	game.players[1].check_win = 0;
	game.players[1].score = 0;
	game.players[1].symbol = CIRCLE;

	game.players[0].check_win = 0;
	game.players[0].score = 0;
	game.players[0].symbol = CROSS;

	game.curr_player = 0;
	game.height = height;
	game.width = width;
	game.gamePlayed = height*width;
	game.cells = Create_grid2D();
}

void cell_destroy(struct cell **cells, int height){
	for(int i=0; i<height; i++){
		free(cells[i]);
	}
	free(cells);
}
int kill_game(){
	cell_destroy(game.cells, game.height);
	return EXIT_SUCCESS;
}

int put_free_cell(int j_p, symbol_t symbol){
	int i=0;
	if((i = is_cell_free(j_p, 0, game.players[game.curr_player].symbol)) != -1){
		game.cells[j_p][i].symbol = symbol;
	}
	return i;
}

/*
retourne la ligne d'une cellule de libre dans une 
colonne donnée 
(si il y en a une, retourn -1 si il n'y en a aucune)
*/
int is_cell_free(int j_p, int i, symbol_t symbol){
	if(game.cells[j_p][i].symbol == EMPTY){
		//retourne la ligne disponible
		return i;
	}else{
		if(i<(game.height-1)){
			return is_cell_free(j_p, i+1, symbol);
		}else{
			printf("il n'y a plus de case de disponible sur cette colonne\n");
			return -1;
		}
	}
}

int Launch_puissance4(){
	symbol_t winner=EMPTY;
	int chiffre=0;

	while(winner==EMPTY){
		print_game();
		printf("Column number? (starts at 1):\n");
		do{
			scanf("%d",&chiffre);
			chiffre-=1; //gestion des chiffres de 1 à n et non de 0 à n-1
			if(chiffre >= game.width || chiffre < 0){
				printf("HEP HEPHEP !! donne un chiffre dans la plage de chiffres indiquée !\n");
			}
		}while((chiffre >= game.width) || (chiffre < 0) || is_cell_free(chiffre, 0, game.players[game.curr_player].symbol)<0);

		game.gamePlayed -= 1; //Complément de verbe du code
		int i = 0;
		//verifier que put free cell fonctionne
		if((i = put_free_cell(chiffre, game.players[game.curr_player].symbol))<0){
			if(Is_Grid_full()){
				//print egalite mais y a probablement eu un bug
				printf("y a un egalite mais probablement un bug\n");
				//fin du jeu
				return EQUAL;
			}else{
				printf("la y a un bug, faut check ca \n");
				print_game();
				//fin du jeu
				return -1; //retourne une erreur
			}
		}
		//check le winner
		winner = Find_winner(game.cells, game.cells[chiffre][i]);
		if( winner != EMPTY){
			if(winner==CROSS){
				//reset du jeu + mise a jour des scores (scores optionels)
				print_game();
				printf("Player one won!\n");
				return CROSS;
			}
			if(winner==CIRCLE){
				//reset du jeu + mise a jour des scores (scores optionels)
				print_game();
				printf("Player two won!\n");
				return CIRCLE;
			}
		}else{
			//sois le jeu est plein, sois y a juste pas encore de winner
			if(Is_Grid_full()){
				//la grille est pleine
				print_game();
				printf("It is a draw.\n");
				return EQUAL;
			}
			//y a juste pas encore de winner ducoup...
			game.curr_player ^= 1; //switch de joueur
		}
	}
	return winner;
}

int Launch_puissance4_randBot(int seed){
	symbol_t winner=EMPTY;
	int chiffre=0;
	srand(seed);

	while(winner==EMPTY){
		print_game();
		if(game.curr_player == 1){
			do{
				chiffre = rand()%game.width;
			}while((is_cell_free(chiffre, 0, game.players[game.curr_player].symbol))<0);
		}else{
			printf("Column number? (starts at 1):\n");
			do{
				scanf("%d",&chiffre);
				chiffre-=1; //gestion des chiffres de 1 à n et non de 0 à n-1
				if(chiffre >= game.width || chiffre < 0){
					printf("HEP HEPHEP !! donne un chiffre dans la plage de chiffres indiquée !\n");
				}
			}while((chiffre >= game.width) || (chiffre < 0) || is_cell_free(chiffre, 0, game.players[game.curr_player].symbol)<0);
		}
		game.gamePlayed -= 1;
		int i = 0;
		//verifier que put free cell fonctionne
		if((i = put_free_cell(chiffre, game.players[game.curr_player].symbol))<0){
			if(Is_Grid_full()){
				printf("y a un egalite mais probablement un bug\n");
				return EQUAL; //jeu egal ou retourner un bug ... a voir..
			}else{
				printf("ok la y a un bug de zinzin check ca \n");
				print_game();
				//fin du jeu
				return -1; //erreur
			}
		}
		//check de la win
		winner = Find_winner(game.cells, game.cells[chiffre][i]);
		if( winner != EMPTY){
			if(winner==CROSS){
				print_game();
				printf("Player one won!\n");
				//fin du jeu
				return CROSS;
			}
			if(winner==CIRCLE){
				print_game();
				printf("Computer won!\n");
				//fin du jeu
				return CIRCLE;
			}
		}else{
			//sois le jeu est plein, sois y a juste pas encore de winner
			if(Is_Grid_full()){
				print_game();
				printf("It is a draw.\n");
				//fin du jeu
				return EQUAL;
			}
			//y a juste pas encore de winner ducoup...
			game.curr_player ^= 1; //switch de joueur
		}
	}
	return winner;
}

int Launch_puissance4_smartBot(int seed){
	symbol_t winner=EMPTY;
	int chiffre=0;
	srand(seed);

	while(winner==EMPTY){
		print_game();
		if(game.curr_player == 1){
			chiffre = SmartBot();
		}else{
			printf("Column number? (starts at 1):\n");
			do{
				scanf("%d",&chiffre);
				chiffre-=1; //gestion des chiffres de 1 à n et non de 0 à n-1
				if(chiffre >= game.width || chiffre < 0){
					printf("HEP HEPHEP !! donne un chiffre dans la plage de chiffres indiquée !\n");
				}
			}while((chiffre >= game.width) || (chiffre < 0) || is_cell_free(chiffre, 0, game.players[game.curr_player].symbol)<0);
		}
		game.gamePlayed -= 1;
		int i = 0;
		//verifier que put free cell fonctionne
		if((i = put_free_cell(chiffre, game.players[game.curr_player].symbol))<0){
			if(Is_Grid_full()){
				printf("y a un egalite mais probablement un bug\n");
				//fin du jeu
				return EQUAL; //jeu egal ou retourner un bug ... a voir..
			}else{
				printf("il y a un bug, faut check ca \n");
				print_game();
				//fin du jeu
				return -1; //erreur
			}
		}
		//check de la win
		winner = Find_winner(game.cells, game.cells[chiffre][i]);
		if( winner != EMPTY){
			if(winner==CROSS){
				print_game();
				printf("Player one won!\n");
				return CROSS;
			}
			if(winner==CIRCLE){
				print_game();
				printf("Computer won!\n");
				return CIRCLE;
			}
		}else{
			//sois le jeu est plein, sois y a juste pas encore de winner
			if(Is_Grid_full()){
				print_game();
				printf("It is a draw.\n");
				return EQUAL;
			}
			//y a juste pas encore de winner ducoup...
			game.curr_player ^= 1; //switch de joueur
		}
	}
	return winner;
}

int SmartBot(){
	int pos=0;
	int chfr1 = -1, chfr2 = -1;
	for(int chfr=0; chfr<game.width; chfr++){
		//verifie que le coup est jouable
		if((pos = put_free_cell(chfr, game.players[game.curr_player].symbol))>=0){
			struct cell *tempCell = &game.cells[chfr][pos];
			tempCell->symbol = game.players[game.curr_player].symbol;
			if (Find_winner(game.cells, game.cells[chfr][pos]) == game.players[game.curr_player].symbol){
				 //1er cas : a trouvé le bon coup à jouer pour gagner
				tempCell->symbol = EMPTY;
				chfr1 = chfr;
			}
			//tente de chercher si l'autre joueur a un coup gagnant
			tempCell->symbol = game.players[game.curr_player^1].symbol;
			if (Find_winner(game.cells, game.cells[chfr][pos]) == game.players[game.curr_player^1].symbol){
				//2e cas : joue le coup gagnant de l'autre joueur pour le bloquer
				tempCell->symbol = EMPTY;
				chfr2 = chfr;
			}
			tempCell->symbol = EMPTY;
		}
	}
	if(chfr1 != -1){
		return chfr1;
	}else if(chfr2 != -1){
		return chfr2;
	}else{
		//3e cas : joue un coup au hasard
		int randomchfr=0;
		do{
			randomchfr = rand()%game.width;
		}while((is_cell_free(randomchfr, 0, game.players[game.curr_player].symbol))<0);
		return randomchfr;
	}
}

bool Is_Grid_full(){
	return game.gamePlayed == 0;
}

/***********************************
 * function     : Find_winner
 * arguments    : grid[][],
 * 				  cellule jouée,
 * 				  taille de grille (ex: 3 pour 3x3)
 *
 * return value : symbole -> gagnant ou EMPTY
 *   Cherche si il y a un gagnant,
 *   (cherche des suites de cases gagnantes)
 *   !!! Fonctionne avec CheckWin_in_a_direction !!!
 ***********************************/
symbol_t Find_winner(struct cell **grid, struct cell cellPlayed){
	//int grid_len = game.height*game.width;
	int k[4][2]={
			{0,1},
			{1,0},
			{1,-1},
			{1,1}
	};
	int k2[4][2]={
			{0,-1},
			{-1,0},
			{-1,1},
			{-1,-1}
	};
	symbol_t result;
	for(int i=0; i<4; i++){
		//à savoir, il est impossible que le cellPlayed soit empty !!
		result = CheckWin_in_a_direction(k[i], grid, grid[cellPlayed.i_pos][cellPlayed.j_pos]);
		if(result != EMPTY){return result;}
		result = CheckWin_in_a_direction(k2[i], grid, grid[cellPlayed.i_pos][cellPlayed.j_pos]);
		game.players[0].check_win = 0;
		game.players[1].check_win = 0;
		if(result != EMPTY){
			return result; //si il trouve un winner, alors il stoppe la fonction :)
		}
	}
	return EMPTY; // pas de winner pour l'instant
}

/***********************************
 * function     : CheckWin_in_a_direction
 * arguments    : grid[][],
 * 				  cellule jouée,
 * 				  taille de grille (ex: 3 pour 3x3)
 *
 * return value : symbole -> gagnant ou EMPTY si non
 *
 *   Va chercher des suites de cases gagnantes
 *   recursivement, dans une seule direction
 *   à l'aide des var globale cross et circle
 ***********************************/
symbol_t CheckWin_in_a_direction(int dir[2], struct cell **grid, struct cell cell){
	int x1 = cell.i_pos+dir[0];
	int x2 = cell.j_pos+dir[1];
	symbol_t result = EMPTY;

	if(x1<game.width && x1>=0 && x2<game.height && x2>=0){
		if(grid[x1][x2].symbol==cell.symbol){
			if(cell.symbol == CIRCLE){
				game.players[0].check_win += 1;
			}else{
				game.players[1].check_win += 1;
			}
			if(game.players[0].check_win>=3){
				return CIRCLE;	//circle win
			}
			else if(game.players[1].check_win>=3){
				return CROSS;   //cross win
			}else{
				result = CheckWin_in_a_direction(dir, grid, grid[x1][x2]);
			}
		}
	}
	return result;
}

void print_game(){
	//printf("h:%d, w:%d\n", game.height, game.width);
	//affiche ┌─┬─┬─┬─┬─┬─┬─┐
	for(int i=0; i<(game.width*2)+1; i++){
		if(i%2){
			printf("─");
		}else{
			if(i==0){
				printf("┌");
			}
			else if(i == (game.width*2)){
				printf("┐");
			}
			else{
				printf("┬");
			}
		}
	}
	printf("\n");

	//affiche le jeu-> │ │ │X│O│ │ │ │
	for(int i=0; i<game.height; i++){
		printf("│");
		for(int j=0; j<game.width; j++){
			if(game.cells[j][(game.height-i)-1].symbol==EMPTY){
				printf(" ");
			}
			else if(game.cells[j][(game.height-i)-1].symbol==CROSS){
				printf("X");
			}else if(game.cells[j][(game.height-i)-1].symbol==CIRCLE){
				printf("O");
			}else{
				printf("E");
			}
			printf("│");
		}
		printf("\n");
		if(i<game.height-1){
			//Dessine ├─┼─┼─┼─┼─┼─┼─┤ ...
			for(int cnt=0; cnt<((game.width*2)+1); cnt++){
				if(cnt%2){
					printf("─");
				}else{
					if(cnt == 0){
						printf("├");
					}
					else if(cnt == (game.width*2)){
						printf("┤");
					}
					else{
						printf("┼");
					}
				}
			}
			printf("\n");
		}
	}

	//Affiche └─┴─┴─┴─┴─┴─┴─┘
	for(int i=0; i<(game.width*2)+1; i++){
		if(i%2){
			printf("─");
		}else{
			if(i==0){
				printf("└");
			}
			else if(i == (game.width*2)){
				printf("┘");
			}
			else{
				printf("┴");
			}
		}
	}
	printf("\n");

	//affiche les numéros
	int cnt = 0;
	for(int i=0; i<(game.width*2); i++){
		if(i%2){
			printf("%d",++cnt);
		}else{
			printf(" ");
		}
	}
	printf("\n");
}