private static void Main(string[] args)
        {
            Środowisko srodowisko = new Środowisko();

            srodowisko.Populacja = new Populacja();
            srodowisko.Populacja.GenerujPierwsząPopulację();

            // Tutaj mamy się kręcić w pętli przez 1000 pokoleń tak czy tak, więc wywalone
            //if (srodowisko.WarunekStopu())
            //    Stop();

            for (int i = 0; i < 1000; i++)
            {
                if (i % 50 == 0)
                {
                    Console.WriteLine("x=" + Populacja.NajlepszyWHistorii.Fenotyp + ", f(x)=" + Środowisko.Funkcja(Populacja.NajlepszyWHistorii.Fenotyp));
                }

                srodowisko.Populacja.GenerujNowąPopulację_Turniej();
            }
            Osobnik x = Populacja.NajlepszyWHistorii;

            Console.WriteLine("x=" + x.Fenotyp + ", f(x)=" + Środowisko.Funkcja(x.Fenotyp));

            Console.ReadKey();
        }
        public Osobnik Selekcja_Turniej()
        {
            Random rng = new Random();

            Osobnik[] turniej = new Osobnik[RozmiarTurnieju];
            for (int i = 0; i < RozmiarTurnieju; i++)
            {
                turniej[i] = Osobniki[rng.Next(RozmiarPopulacji)];
            }
            return(turniej.OrderByDescending(x => Środowisko.Funkcja(x.Fenotyp)).First()); // zwraca najlepszego z turnieju`
        }
        public Osobnik NajlepszyWPopulacji()
        {
            Osobnik najlepszy = Osobniki[0];

            for (int i = 1; i < RozmiarPopulacji; i++)
            {
                najlepszy = Środowisko.Lepszy(najlepszy, Osobniki[i]);
            }

            NajlepszyWHistorii = Środowisko.Lepszy(najlepszy, NajlepszyWHistorii);

            return(najlepszy);
        }
        public void GenerujNowąPopulację_Turniej()
        {
            Populacja nowePokolenie = new Populacja();

            for (int i = 0; i < RozmiarPopulacji; i++)
            {
                do
                {
                    Osobnik mama = Selekcja_Turniej();
                    Osobnik tata = Selekcja_Turniej();

                    nowePokolenie.Osobniki[i] = Osobnik.Krzyżowanie(mama, tata);
                    nowePokolenie.Osobniki[i].Mutacja();
                } while(nowePokolenie.Osobniki[i].ŚmiertelnieZmutowany()); // Niektóre osobniki mogą być niedopuszczalne do rozwiązania
            }

            NajlepszyWHistorii = Środowisko.Lepszy(NajlepszyWHistorii, nowePokolenie.NajlepszyWPopulacji());
        }
        public static Osobnik Lepszy(Osobnik x1, Osobnik x2)
        {
            //if (Funkcja(x1.Fenotyp) > Funkcja(x2.Fenotyp))
            //{
            //    return x1;
            //}
            //else return x2;
            if (x1 == null)
            {
                return(x2);
            }
            if (x2 == null)
            {
                return(x1);
            }
            Osobnik lepszy = Funkcja(x1.Fenotyp) > Funkcja(x2.Fenotyp) ? x1 : x2;

            return(lepszy);
        }
        public void GenerujPierwsząPopulację()
        {
            Random rng = new Random();

            for (int i = 0; i < RozmiarPopulacji; i++)
            {
                // LOSOWO
                //Osobniki[i] = new Osobnik()
                //{
                //    Genotyp = (uint) (0 | rng.Next(int.MaxValue))
                //};
                do
                {
                    Osobniki[i] = new Osobnik()
                    {
                        Genotyp = (uint)i * (UInt32.MaxValue / RozmiarPopulacji) + (uint)rng.Next() //Populacja równomiernie rozłożona + spora losowość
                    };
                } while(Osobniki[i].ŚmiertelnieZmutowany());                                        // Niektóre osobniki mogą być niedopuszczalne jako rozwiązania
            }

            NajlepszyWHistorii = NajlepszyWPopulacji();
        }
        public static Osobnik Krzyżowanie(Osobnik mama, Osobnik tata)
        {
            Random rng = new Random();
            // Tata = 0 1 0 | 1 0 1 0 1
            // Mama = 0 1 0 | 0 1 1 0 1

            // Dzi1 = 0 1 0 | 1 0 1 0 1
            // Dzi2 = 0 1 0 | 0 1 1 0 1

            int punktPodziału = rng.Next(1, 31); // od 0 do liczby bitów genotypu (tutaj 32)
                                                 //od 1, żeby nie wziąć któregoś z rodziców w całości


            uint maska = uint.MaxValue; // 11111111   ~0u (same jedynki)

            maska = maska << punktPodziału;
            // dla punktPodziału=2:
            // 11111100
            // Dzi1 = Tata & maska
            // 0 1 0 | 1 0 1 0 1
            // 1 1 1 | 0 0 0 0 0
            // 0 1 0 | 0 0 0 0 0

            // Dzi1 += Mama & !maska
            // 0 1 0 | 0 1 1 0 1
            // 0 0 0 | 1 1 1 1 1
            // 0 0 0 | 0 1 1 0 1

            // 0 1 0 | 0 1 1 0 1

            Osobnik dziecko = new Osobnik()
            {
                Genotyp = (tata.Genotyp & maska) | (mama.Genotyp & ~maska)
            };

            return(dziecko);
        }