-
remi.greub authoredremi.greub authored
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");
}