using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;


namespace Navale
{
    class Program
    {
        static void Main(string[] args)
        {
            int[,] GrilleJoueur1 = new int[10, 10]; // Contient les emplacements des navires du joueur 1.
            int[,] GrilleJoueur2 = new int[10, 10]; // Contient les emplacements des navires du joueur 2.
            int[,] FrappesJoueur1 = new int[10, 10];// Contient les cases frappées par le joueur 1.
            int[,] FrappesJoueur2 = new int[10, 10]; // Contient les cases frappées par le joueur 2.



            // Préparation des tableaux
            InitGrille(GrilleJoueur1);
            InitGrille(GrilleJoueur2);
            InitGrille(FrappesJoueur1);
            InitGrille(FrappesJoueur2);


            int nbrnavires = NombresNavires();


            string[] Noms = new string[nbrnavires];
            int[] nombrecase1 = new int[nbrnavires];
            int[] nombrecase2 = new int[nbrnavires];




            for (int n = 0; n < nbrnavires; n++)
            {
                Console.WriteLine("Nommez le navire " + (n + 1) + "!");
                Noms[n] = Console.ReadLine();
                Console.WriteLine("Choisir une taille pour votre navire (1 à 4 cases) !");
                nombrecase1[n] = int.Parse(Console.ReadLine());
                nombrecase2[n] = nombrecase1[n];
            }






            // Placement des bateaux du joueur 1
            Placement(GrilleJoueur1, 1, nbrnavires, Noms, nombrecase1);
            Console.Clear();
            // Placement des bateaux du joueur 2
            Placement(GrilleJoueur2, 2, nbrnavires, Noms, nombrecase1);
            Console.Clear();

            // Jeu
            int Gagnant; // O:A l'eau, 1:Touché, 2:Gagné
            do
            {
                do
                {
                    Gagnant = Attaque(GrilleJoueur2, FrappesJoueur1, 1, Noms);
                } while (Gagnant == 1);
                if (Gagnant < 2)
                    do
                    {
                        Gagnant = Attaque(GrilleJoueur1, FrappesJoueur2, 2, Noms);
                    } while (Gagnant == 1);

            } while (Gagnant < 2);

        }

        // Procédure de ralentissement de l'affichage
        static void attente()
        {
            for (long val = 0; val < 20; val++)
                for (long val2 = 0; val2 < 50000000; val2++) ;
        }

        // Initialise à la valeur 0 toutes les valeurs du tableau (grille) passé en paramètre.
        static void InitGrille(int[,] Grille)
        {
            for (int l = 0; l < 10; l++)
                for (int c = 0; c < 10; c++)
                    Grille[l, c] = 0;
        }

        //////////////////// Procédures de dessin de la grille dans la console. ////////////////////


        static void LigneHaut()
        {
            Console.Write("\n  |-");
            for (int elem = 2; elem <= 10; elem++)
                Console.Write("|-");
            Console.Write("|");
        }
        static void LigneMilieu()
        {
            Console.Write("\n  |-")
            for (int elem = 2; elem <= 10; elem++)
                Console.Write("|-");
            Console.Write("|");
        }
        static void LigneBas()
        {
            Console.Write("\n  |-");
            for (int elem = 2; elem <= 10; elem++)
                Console.Write("|-");
            Console.Write("| \n\n");
        }

        static void AfficheGrille(int[,] Grille, string Message)
        {             Console.Clear();
            Console.Write("\n   0 1 2 3 4 5 6 7 8 9");
            LigneHaut();
            for (int l = 0; l < 10; l++)
            {
                Console.Write("\n" + l + " " + (char)(124));
                for (int c = 0; c < 10; c++)
                {
                    if (Grille[l, c] == 0)
                        Console.Write(" |");
                    if (Grille[l, c] > 0)
                        Console.Write("X|");
                    if (Grille[l, c] < 0)
                        Console.Write("-|");
                }
                if (l < 9)
                    LigneMilieu();
                else
                    LigneBas();
            }
            // Affichage d'un eventuel message sous la grille de jeu.
            Console.Write(Message + "\n");

        }

        //////////////////// Fin de procédures de dessin de la grille ////////////////////

        // Fonction de vérification de saisie d'un chiffre.
        static int Chiffre()
        {
            char val;
            val = Convert.ToChar(Console.ReadLine());
            if (val < '0' || val > '9')
                return -1;
            else
                return (int)val - 48;

        }

        // Saisie d'une coordonnée
        static int SaisieCoord(string Message)
        {
            int coord;
            do
            {
                Console.Write(Message);
                coord = Chiffre(); // astuce au cas où un caractère non numérique est saisie
            } while (coord < 0 || coord > 9);
            return coord;
        }

        // Saisie de la position horizontale ou verticale d'un navire
        static char SaisiePosition()
        {
            char position;
            do
            {
                Console.Write("Position horizontale (h) ou verticale  (v) : ");
                position = Convert.ToChar(Console.ReadLine());
                if (position == 'H')
                    position = 'h';
                if (position == 'V')
                    position = 'v';
            } while (position != 'h' && position != 'v');
            return position;
        }

        // Vérification de la possibilité de placer un navire aux coordonnées souhaitées
        static string VerifPlace(int[,] Grille, int l, int c, char p, int n, int[] nombrecase1)
        {
            int i = c;
            string Message = "";
            // Cas d'un placement horizontal
            if (p == 'h')
            {
                // Si ce n'est pas la dernière colonne à droite ...
                if (c + nombrecase1[n - 1] <= 9)
                {
                    while (i < ((c + nombrecase1[n - 1]) - 1))
                    {
                        // Si les deux cases de l'emplacement du navire sont libres ...

                        if (Grille[l, c] == 0 && Grille[l, c + 1] == 0)
                        {
                            Message = "";
                            i++;

                        }
                        else
                        {
                            Message = "Il y a déjà un navire à cette emplacement.\n";
                            i = 10;
                        }
                    }
                }
                else
                    Message = "Vous ne pouvez pas placer votre navire horizontalel !!\n";
                return Message;
            }
            // Cas d'un placement vertical
            else
            {
                // Si ce n'est pas la dernière ligne en bas
                if (c + nombrecase1[n - 1] <= 9)
                {
                    while (i < ((c + nombrecase1[n - 1]) - 1))
                    {
                        // Si les deux cases de l'emplacement du navire sont libres ...
                        if (Grille[l, c] == 0 && Grille[i + 1, c] == 0)
                        {
                            Message = "";
                            i++;
                        }
                        else
                        {
                            Message = "Il y a déjà un navire à cette emplacement.\n";
                            i = 10;
                        }
                    }
                }
                else
                {
                    Message = "Vous ne pouvez pas placer votre navire verticalement !!\n";

                }
                return Message;
            }

        }



        // Placement effectif du navire dans la grille
        static void PoserNavire(int[,] Grille, int n, int l, int c, char p, int[] nombrecase1)
        {
 
                        // n est la valeur placée dans la grille pour identifier le navire
            Grille[l, c] = n;
            if (p == 'h')
                for(int i=0;i < nombrecase1[n-1]-1;i++)
                {
                    Grille[l, i + 1 + c] = n;
                }
            else
                for (int i=0; i < nombrecase1[n-1]-1;i++)
                {
                    Grille[i + 1 + l, c] = n;
                }
        }

        static int NombresNavires()
        {
            int nbrnavires;
            Console.WriteLine("Combien de navires voulez vous placez ? (entre 2 et 5)");
            nbrnavires = int.Parse(Console.ReadLine());

            return nbrnavires;

       }

      
    


    // Placement des navires d'un joueur
    static void Placement(int[,] Grille, int Joueur, int unNombreNavire, string[] Noms, int[] nombrecase1)
        {
            int l, c;
            char p;
            string ok;
            int nbrnavires = unNombreNavire;
 
          

            // Pour chaque navire
            if (nbrnavires >= 2 && nbrnavires <= 5)
            {

                                for (int n = 1; n <= nbrnavires; n++)
                {
                    ok = "";
                    do
                    {
                        // Affichage des navires déjà placés.
                        AfficheGrille(Grille, ok);
                        // Placement des navires
                        Console.Write("Placement des navires.\n");
                        Console.Write("----------------------\n");
                        Console.Write("\nJoueur " + Joueur + " :\n");
                        Console.Write("Coordonnées du navire " + Noms[n-1] + " : \n");
                        Console.Write("\tCase supérieur gauche : \n");
                        l = SaisieCoord("\t\tLigne : ");
                        c = SaisieCoord("\t\tColonne : ");
                        p = SaisiePosition();
                        ok = VerifPlace(Grille, l, c, p, n, nombrecase1);
                    } while (ok != "");
                    PoserNavire(Grille, n, l, c, p, nombrecase1);

                }
            }
            else if (nbrnavires < 2)
            {
                Console.WriteLine("Vous n'avez pas assez de bateaux !");
            }
            else if (nbrnavires > 5)
            {
                Console.WriteLine("Vous avez trop de bateaux !");
            }



            // Affichage des navires déjà placés.
            AfficheGrille(Grille, "Tous vos navires sont placés.");



        }



        // Tous les navires sont-ils coulés ?
        static bool ToutCoule(int[,] Grille)
        {
            bool Reponse = true;
            for (int l = 0; l < 10; l++)
                for (int c = 0; c < 10; c++)
                    if (Grille[l, c] != 0)
                        Reponse = false;

            return Reponse;
        }

        // Un navire touché est-il coulé ?
        static bool Coule(int[,] Grille, int n, int l, int c, string[] Noms)
        {
            // On vérife que les 4 cases autour ne contiennent pas le numéro de navire
            if (l < 9 && Grille[l + 1, c] == n)
                return false;
            if (l > 0 && Grille[l - 1, c] == n)
                return false;
            if (c < 9 && Grille[l, c + 1] == n)
                return false;
            if (c > 0 && Grille[l, c - 1] == n)
                return false;

            // Si les 4 conditions sont fausses, le navire est coulé
            return true;
        }

        // Lancement d'une torpille
        static int Attaque(int[,] Grille, int[,] Frappes, int Joueur, string[] Noms)
        {
            int ligne, colonne, Resultat;
            // Affichage du résultat des torpilles précédentes
            AfficheGrille(Frappes, "- : torpilles à l'eau   X : navires touchés\n");
            // Coordonées de la torpille
            Console.Write("Joueur " + Joueur + ", coordonnées d envoi de votre torpille :\n");
            ligne = SaisieCoord("Ligne (0 à 9) : ");
            colonne = SaisieCoord("Colonne (0 à 9) : ");

            // Résultat de l'attaque
            if (Grille[ligne, colonne] == 0)
            {
                Console.Write("La torpille est à l eau, aucun navire touché.\n\n");
                Frappes[ligne, colonne] = -1; // Mémorisation du résultat
                Resultat = 0;
            }
            else
            {

                Frappes[ligne, colonne] = 1; // Mémorisation du résultat
                Resultat = 1; // Touché
                int Navire = Grille[ligne, colonne];
                Grille[ligne, colonne] = 0;
                // Touché, d'accord ... mais coulé ?
                if (Coule(Grille, Navire, ligne, colonne, Noms))
                {

                  
                                        Console.Write("Vous venez de couler le navire " + Noms[Navire-1] + "! \n\n");


                                         // Tous coulés ?
                    if (ToutCoule(Grille))
                    {
                        Console.Write("Vous avez coulé tous le navires adverses. Vous avez gagné !\n\n");
                        Resultat = 2; // C'est gagné !!
                    }
                }
                else  // Juste touché
                {
                    Console.Write("Vous avez touché le navire " + Noms[Navire - 1] + "! \n\n");
                }

            }
            // Attente le temps de lire le résultat de l'attaque
            attente();
            return Resultat;
        }
    }
}