2000 /* Projet 5: Combat Naval * Par: Henry Ledoux (Groupe 5) */ #include #include #include #include "grilles.h" #include // Necessaire pour la fonction sleep() // Converti le caractère entré pour désigner la ligne (de A a J) en entier (de 0 à 9). int char2int(char c) { int res; if (c >= 'a' && c <= 'j') res = (int)(c - 'a'); else if (c >= 'A' && c <= 'J') res = (int)(c - 'A'); return res; } // Trie a et b, tel que a est plus petit que b. void minitri(int &a, int &b) { int Save; if (a > b) { Save = a; a = b; b = Save; } } /* La classe JoueurHumain propose diverses fonctions appelable par le corps de jeu. tir renvoie les coordonées entrée par l'utilisateur lorsqu'il désire tirer contre l'ordinateur. recevoir_tir prends en parametre les coordonnées du tir executé par l'ordinateur, et renvoie le résultat: 0 touché, 1 coulé, 2 dans l'eau. affiche() affiche les deux grilles de l'utilisateur a l'écran. place_bateaux demande a l'utilisateur l'emplacement de chacun de ses bateaux. */ class JoueurHumain { public: JoueurHumain(); // 1 void affiche(); // 2 void place_bateaux(); // 3 int recevoir_tir(int pos_x, int pos_y); // 4 void tir(int &pos_x, int &pos_y); // 5 void donner_resultat(int result, int pos_x, int pos_y); // 6 bool is_ended(); // 7 private: void posebateau(int pos_a_x, int pos_a_y, int pos_b_x, int pos_b_y, int type); // 8 int check_boat(int pos_a_x, int pos_a_y, int pos_b_x, int pos_b_y, int type); // 9 plan_de_jeu gr_bateaux; plan_de_jeu gr_tirs; int reste_boat[5]; }; /* La classe JoueurVirtuel propose les memes fonctions, mais d'un contenu différent, la fonction tir choisis automatiquement les coordonées. */ class JoueurVirtuel { public: JoueurVirtuel(); // 10 void tir(int &pos_x, int &pos_y); // 11 int recevoir_tir(int pos_x, int pos_y); // 12 void donner_resultat(int result, int pos_x, int pos_y); // 13 bool is_ended(); // 14 private: bool check_tir(int pos_x, int pos_y); // 15 plan_de_jeu gr_bateaux; plan_de_jeu gr_tirs; short int reste_boat[5]; short int dir; short int etape; short int cur; short int tir_p_y; short int tir_p_x; }; /* La classe jeu joue le role d'arbitre, elle s'occupe de gere les coups entre l'utilisateur et l'ordinateur */ class Jeu { public: void tour(); // 16 void init(); // 17 private: void tir_user_mach(); // 18 void tir_mach_user(); // 19 JoueurHumain User; JoueurVirtuel Machine; }; // 1 : Définitions des méthodes de la classe JoueurHumain, gere le jeu de l'utilisateur JoueurHumain::JoueurHumain() { for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) gr_bateaux[i][j] = 0; for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) gr_tirs[i][j] = 0; reste_boat[0] = 5; reste_boat[1] = 4; reste_boat[2] = 3; reste_boat[3] = 3; reste_boat[4] = 2; } // 2 : Fonction d'affichage des grilles utilisateur void JoueurHumain::affiche() { cout << char(0xDA) << char(0xC4); for (int i = 0; i < 10; ++i) cout << char(0xC2) << char(0xC4); cout << char(0xBF) << " "; cout << char(0xDA) << char(0xC4); for (int i = 0; i < 10; ++i) cout << char(0xC2) << char(0xC4); cout << char(0xBF) << endl; cout << char(0xB3) << '#'; for (int i = 0; i < 10; ++i) cout << char(0xB3) << (i+1)%10; cout << char(0xB3) << " "; cout << char(0xB3) << '@'; for (int i = 0; i < 10; ++i) cout << char(0xB3) << (i+1)%10; cout << char(0xB3); cout << endl; for (int i = 0; i < 10; ++i) { cout << char(0xC3) << char(0xC4); for (int j = 0; j < 10; ++j) cout << char(0xC5) << char(0xC4); cout << char(0xB4) << " " << char(0xC3) << char(0xC4); for (int j = 0; j < 10; ++j) cout << char(0xC5) << char(0xC4); cout << char(0xB4) << endl << char(0xB3) << char(i+'A'); for (int j = 0; j < 10; ++j) { cout << char(0xB3); if (gr_bateaux[i][j] == 0) cout << ' '; else if (gr_bateaux[i][j] == 6) cout << '~'; else if (gr_bateaux[i][j] == 7) cout << '*'; else cout << gr_bateaux[i][j]; } cout << char(0xB3) << " " << char(0xB3) << char(i+'A'); for (int j = 0; j < 10; ++j) { cout << char(0xB3); if (gr_tirs[i][j] == 0) cout << ' '; else if (gr_tirs[i][j] == 1) cout << '*'; else if (gr_tirs[i][j] == 2) cout << '~'; else cout << gr_tirs[i][j]; } cout << char(0xB3) << endl; } cout << char(0xC0) << char(0xC4); for (int j = 0; j < 10; ++j) cout << char(0xC1) << char(0xC4); cout << char(0xD9) << " " << char(0xC0) << char(0xC4); for (int j = 0; j < 10; ++j) cout << char(0xC1) << char(0xC4); cout << char(0xD9) << endl; } // 3 : Demande a l'utilisateur l'emplacement de ses bateaux void JoueurHumain::place_bateaux() { for (int i = 1; i <= 5; ++i) { char c_temp; bool recommencer; int pos_a_x, pos_a_y, pos_b_x, pos_b_y; do { affiche(); sleep(1); cout << "Entrez les deux extremites du "; switch (i) { case 1: cout << "porte-avions"; break; case 2: cout << "cuirasse"; break; case 3: cout << "croiseur"; break; case 4: cout << "sous-marin"; break; case 5: cout << "destroyer"; }; cout << " (longueur:" << reste_boat[i] << ")"; cout << ". (Entrez la ligne sous forme de lettre, la colonne sous forme de chiffre)" << endl << "Premiere extremite: "; cin >> c_temp >> pos_a_y; pos_a_x = char2int(c_temp); pos_a_y--; cout << "Seconde extremite du bateau: "; cin >> c_temp >> pos_b_y; pos_b_x = char2int(c_temp); pos_b_y--; switch (check_boat(pos_a_x, pos_a_y, pos_b_x, pos_b_y, i)) { case 0: cout << "ok" << endl; recommencer = false; break; case 1: cout << "Il faut entrer des coordonnees correctes" << endl; recommencer = true; break; case 2: cout << "Un bateau doit etre soit horizontal soit vertical!!" << endl; recommencer = true; break; case 3: cout << "Longueur du bateau incorrecte" << endl; recommencer = true; break; case 4: cout << "Position du bateau incorrecte" << endl; recommencer = true; }; sleep(1); } while (recommencer); // L'ordinateur redemandera l'eplacement // du bateau tant qu'il n'est pas correct. posebateau(pos_a_x, pos_a_y, pos_b_x, pos_b_y, i); } } // 4 : Recois les coordonées du tir de l'ordinateur, modifie la // grille utilisateur et renvoie le résultat. int JoueurHumain::recevoir_tir(int pos_x, int pos_y) { int result; if (gr_bateaux[pos_x][pos_y] == 0) { result = 2; gr_bateaux[po 1bd8 s_x][pos_y] = 6; } else { reste_boat[gr_bateaux[pos_x][pos_y] - 1]--; if (reste_boat[gr_bateaux[pos_x][pos_y] - 1] == 0) result = 1; else result = 0; gr_bateaux[pos_x][pos_y] = 7; } return result; } // 5 : Demande a l'utilisateur les coordonées de l'endroit vers lequel il veut tirer void JoueurHumain::tir(int &pos_x, int &pos_y) { char temp; affiche(); sleep(2); cout << "Entrez les coordonees de l'endroit ou vous voulez tirer" << endl; cin >> temp >> pos_y; pos_x = char2int(temp); pos_y--; } // 6 : Affiche le résultat a l'écran, modifie la grille de tir // et diminue le nombre de cases restante du bateau. void JoueurHumain::donner_resultat(int result, int pos_x, int pos_y) { if (result == 2) { cout << "Pas de chance! Dans l'eau."; gr_tirs[pos_x][pos_y] = 2; } else if (result == 0) { cout << "Bien! Touché."; gr_tirs[pos_x][pos_y] = 1; } else { cout << "Youhoo! Coulé."; gr_tirs[pos_x][pos_y] = 1; } } // 7 : Cette fonction retourne vrai si le joueur a perdu. bool JoueurHumain::is_ended() { int tot = 0; for (int i = 0; i < 5; ++i) tot += reste_boat[i]; return (tot == 0); } // 8 : Fonction privée, appelée par place_bateaux(), place un bateau sur la grille utilisateur. void JoueurHumain::posebateau(int pos_a_x, int pos_a_y, int pos_b_x, int pos_b_y, int type) { minitri(pos_a_x, pos_b_x); minitri(pos_a_y, pos_b_y); for (int i = pos_a_x; i <= pos_b_x; ++i) for (int j = pos_a_y; j <= pos_b_y; ++j) gr_bateaux[i][j] = type; } // 9 : Vérifie que le placement du bateau soit autorisé avant de le placer. int JoueurHumain::check_boat(int pos_a_x, int pos_a_y, int pos_b_x, int pos_b_y, int type) { minitri(pos_a_x, pos_b_x); minitri(pos_a_y, pos_b_y); int erreur_nb = 0; if (pos_a_x > 9 || pos_a_x < 0 || pos_a_y > 9 || pos_a_y < 0 || pos_b_x > 9 || pos_b_x < 0 || pos_b_y > 9 || pos_b_y < 0) erreur_nb = 1; else if (pos_a_x != pos_b_x && pos_a_y != pos_b_y) erreur_nb = 2; else if (pos_a_x == pos_b_x && abs(pos_a_y - pos_b_y) != (reste_boat[type-1] - 1)) erreur_nb = 3; else if (pos_a_y == pos_b_y && abs(pos_a_x - pos_b_x) != (reste_boat[type-1] - 1)) erreur_nb = 3; else if ((pos_a_x == pos_b_x) && (pos_a_x == 0 || pos_b_x == 9)) erreur_nb = 4; else if ((pos_a_y == pos_b_y) && (pos_a_y == 0 || pos_b_y == 9)) erreur_nb = 4; else { bool bonne_pos = true; if (pos_a_x == 0) pos_a_x++; else if (pos_b_x == 9) pos_b_x--; if (pos_a_y == 0) pos_a_y++; else if (pos_b_y == 9) pos_b_y--; for (int i = pos_a_x - 1; i <= pos_b_x + 1; ++i) for (int j = pos_a_y - 1; j <= pos_b_y + 1; ++j) if ((i >= pos_a_x && i <= pos_b_x) || (j >= pos_a_x && i <= pos_b_x)) bonne_pos = (bonne_pos && (gr_bateaux[i][j] == 0)); if (!bonne_pos) erreur_nb = 4; } return erreur_nb; } // 10 : Définitions méthodes classe JoueurVirtuel JoueurVirtuel::JoueurVirtuel() { int choix_grille; srand(time(0)); choix_grille = int(double(rand())/RAND_MAX*5); for (int i = 0; i < 10; ++i) for (int j = 0; j < 10; ++j) { gr_bateaux[i][j] = grilles[choix_grille][i][j]; gr_tirs[i][j] = 0; } reste_boat[0] = 5; reste_boat[1] = 4; reste_boat[2] = 3; reste_boat[3] = 3; reste_boat[4] = 2; etape = 0; dir = 0; } // 11 : Cette fonction retourne les coordonées choisies par l'ordinateur. void JoueurVirtuel::tir(int &pos_x, int &pos_y) { srand(time(0)); if (etape == 0) { do { pos_x = int(double(rand())/RAND_MAX*10); pos_y = int(double(rand())/RAND_MAX*10); tir_p_x = pos_x; tir_p_y = pos_y; } while (check_tir(pos_x, pos_y)); } else if (etape == 1) { do { dir = (dir + 1) % 4; switch (dir) { case 0: pos_x = tir_p_x - 1; pos_y = tir_p_y; break; case 1: pos_y = tir_p_y - 1; pos_x = tir_p_x; break; case 2: pos_x = tir_p_x + 1; pos_y = tir_p_y; break; case 3: pos_y = tir_p_y + 1; pos_x = tir_p_x; }; } while (check_tir(pos_x,pos_y)); } else if (etape >= 2) { do { if (etape == 2) { cur++; } else cur--; if (dir == 0 || dir == 2) { pos_x = tir_p_x + cur; pos_y = tir_p_y; } else { pos_x = tir_p_x; pos_y = tir_p_y + cur; } if (pos_x > 9 || pos_y > 9) etape = 3; } while (check_tir(pos_x,pos_y)); } } // 12 : Recois le tir de l'utilisateur et renvoie le résultat. int JoueurVirtuel::recevoir_tir(int pos_x, int pos_y) { int result; if (gr_bateaux[pos_x][pos_y] == 0) { result = 2; } else { reste_boat[gr_bateaux[pos_x][pos_y] - 1]--; if (reste_boat[gr_bateaux[pos_x][pos_y] - 1] == 0) result = 1; else result = 0; } return result; } // 13 : Modifie la grille de tir de l'ordinateur (afin de ne pas retirer au meme endroit). void JoueurVirtuel::donner_resultat(int result, int pos_x, int pos_y) { gr_tirs[pos_x][pos_y] = result + 1; if (result == 2) cout << "L'ordinateur a rate" << endl; else if (result == 0) cout << "L'ordinateur a touche" << endl; else cout << "L'ordinateur a coule" << endl; if (etape == 0 && result == 0) { etape = 1; dir = int(double(rand())/RAND_MAX*4); } else if (etape == 1 && result == 0) { cur = 0; etape = 2; } else if (etape == 2 && result == 3) { cur = 0; etape = 3; } else if (result == 1) { etape = 0; } } // 14 : Retourne vrai si l'ordinateur a perdu. bool JoueurVirtuel::is_ended() { int tot = 0; for (int i = 0; i < 5; ++i) tot += reste_boat[i]; return (tot == 0); } // 15 : Vérifie que la valeur choisie par l'ordinateur est correcte bool JoueurVirtuel::check_tir(int pos_x, int pos_y) { return (gr_tirs[pos_x][pos_y] != 0 || pos_x < 0 || pos_x > 9 || pos_y < 0 || pos_y > 9); } // 16 : Déroulement du jeu void Jeu::tour() { while(!User.is_ended() && !Machine.is_ended()) { tir_user_mach(); if (!User.is_ended()) tir_mach_user(); sleep(2); } if (User.is_ended()) cout << "Vous avez perdu!!" << endl; else cout << "Bravo! Vous avez gagne!!" << endl; sleep(2); } // 17 : Lance le jeu. void Jeu::init() { User.place_bateaux(); tour(); } // 18 : Tir de l'utilisateur contre la machine void Jeu::tir_user_mach() { int pos_x, pos_y, res; User.tir(pos_x, pos_y); res = Machine.recevoir_tir(pos_x, pos_y); User.donner_resultat(res, pos_x, pos_y); } // 19 : tir de la machine contre l'utilisateur void Jeu::tir_mach_user() { int pos_x, pos_y, res; Machine.tir(pos_x, pos_y); res = User.recevoir_tir(pos_x, pos_y); Machine.donner_resultat(res, pos_x, pos_y); } void main () { Jeu the_game; the_game.init(); sleep(2); } 0