Knocks the error <Process is terminated due to StackOverflowException> in the console when the game supposedly comes to an end.

class X_O { static char One, Two, Three, Four, Five, Six, Seven, Eight, Nine; static int Enter; static int PCEnter; static void Main() { Console.Clear(); Monitor(); Enters(); } static void Monitor() { Console.OutputEncoding = Encoding.UTF8; Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(); Console.WriteLine(" --- --- --- "); Console.WriteLine(" ┆ {0} ┆ {1} ┆ {2} ┆", One, Two, Three); Console.WriteLine(" --- --- --- "); Console.WriteLine(" ┆ {0} ┆ {1} ┆ {2} ┆", Four, Five, Six); Console.WriteLine(" --- --- --- "); Console.WriteLine(" ┆ {0} ┆ {1} ┆ {2} ┆", Seven, Eight, Nine); Console.WriteLine(" --- --- --- "); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.White; } static void PC() { Random Num = new Random(); PCEnter = Num.Next(1,9); switch (PCEnter) { case 1: { if (One == 'X' || One == 'O') PC(); else One = 'O'; Main(); break; } case 2: { if (Two == 'X' || Two == 'O') PC(); else Two = 'O'; Main(); break; } case 3: { if (Three == 'X' || Three == 'O') PC(); else Three = 'O'; Main(); break; } case 4: { if (Four == 'X' || Four == 'O') PC(); else Four = 'O'; Main(); break; } case 5: { if (Five == 'X' || Five == 'O') PC(); else Five = 'O'; Main(); break; } case 6: { if (Six == 'X' || Six == 'O') PC(); else Six = 'O'; Main(); break; } case 7: { if (Seven == 'X' || Seven == 'O') PC(); else Seven = 'O'; Main(); break; } case 8: { if (Eight == 'X' || Eight == 'O') PC(); else Eight = 'O'; Main(); break; } case 9: { if (Nine == 'X' || Nine == 'O') PC(); else Nine = 'O'; Main(); break; } } Main(); } static void Enters() { Console.Write(" X_O ВАШ ХОД : "); try { Enter = Convert.ToInt32(Console.ReadLine()); switch (Enter) { case 1: { if (One == 'X' || One == 'O') Console.Beep(); else One = 'X'; PC(); break; } case 2: { if (Two == 'X' || Two == 'O') Console.Beep(); else Two = 'X'; PC(); break; } case 3: { if (Three == 'X' || Three == 'O') Console.Beep(); else Three = 'X'; PC(); break; } case 4: { if (Four == 'X' || Four == 'O') Console.Beep(); else Four = 'X'; PC(); break; } case 5: { if (Five == 'X' || Five == 'O') Console.Beep(); else Five = 'X'; PC(); break; } case 6: { if (Six == 'X' || Six == 'O') Console.Beep(); else Six = 'X'; PC(); break; } case 7: { if (Seven == 'X' || Seven == 'O') Console.Beep(); else Seven = 'X'; PC(); break; } case 8: { if (Eight == 'X' || Eight == 'O') Console.Beep(); else Eight = 'X'; PC(); break; } case 9: { if (Nine == 'X' || Nine == 'O') Console.Beep(); else Nine = 'X'; PC(); break; } default: Console.Beep(); Main(); break; } Main(); } catch { Console.Beep(); Main(); } } } 

Keek

  • one
    And no wonder, you call Enters from Main , and call Main from Enters . The recursion however ...... And by the way it is impossible to cause Main from something. This is the entry point. - Alexey Shimansky
  • Aw .. I never thought about it; d Thank you very much) - SDst
  • How is it then possible to implement a re-call? ; d - SDst

2 answers 2

As correctly noted @Alexey Shimansky, you use a recursive call without the condition of stopping the recursion, which causes the stack to overflow at a certain stage.

At all. if there is an opportunity to do without recursion, it is better to do without it, because when you call a function, the current state of the program is stored in the stack, and with deep recursion the stack ends sooner or later. In your case, you need to remove the Main and PC calls from your functions, and change the Main function so that your functions are executed in a cycle to a certain state: victory, defeat, no free cells or while there are available moves. In the same cycle we set the sequence of moves - who walks first, who walks second, like this:

 static void Main() { while(можно_сделать_ход) { //первый ход, в данном случае игрока Console.Clear(); Monitor(); Enters(); //Для второго игрока придется дополнительно проверить возможность //хода, т.к. во-первых, максимальное количество ходов нечетное, //во-вторых, первый игрок мог выиграть своим ходом и дальнейшие //ходы не имеют смысла. if(можно_сделать_ход) { //второй ход Console.Clear(); Monitor(); PC(); } } } 

Replace can be можно_сделать_ход on a suitable condition.

Thus, the loop will provide alternation of moves without the need to make recursive function calls and stack overflows as a result.

It is also worth thinking about changing the PC function. You use a random number generator, which selects the course of all the cells on the field, not taking into account the employment of the cell. This will lead to the fact that each next move will be chosen longer, because the generator will more often issue the numbers of occupied cells. You can solve it by making a list of available cells and delete the used cell from it at each turn, and adjust the random number generator to select a number from the range 0 - the длина_списка_неиспользованных_ячеек .

  • Thank you for so many good ideas, I will redo the crutch) - SDst
  • @SDst please. If you are just learning, then find the problem book A. Shen Programming theorems and problems will be useful for learning programming in principle. And then you can connect heavier artillery as needed. Here on Sharp a whole list lies with the gradation of the complexity of the material. - rdorn
  • Yes, that's just learning, according to the video tutorials - youtube.com/playlist?list=PLnV3K-pmuXwjSI_k3NrPBENNds35G72h2 (Someone merged this course from disk to channel), while only at 34 lesson, there is little I know, there are so few basics. Here I think I'll start reading more "The Bible C #", and I’ll definitely look at the problem book of A.Shen) - SDst
  • one
    @SDst here look at .NET books ru.stackoverflow.com/a/416585/198316 - rdorn

In general, somehow I have already implemented everything, thanks to those who helped with errors;)

 class X_O { static char One, Two, Three, Four, Five, Six, Seven, Eight, Nine; static bool Cicle = true; static int PCEnter; static int Enter; static void Main() { while (Cicle) { Console.Clear(); Monitor(); Entry(); EntryWin(); PCEntry(); PCEntryWin(); } } static void Monitor() { Console.OutputEncoding = Encoding.UTF8; Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine(); Console.WriteLine(" --- --- --- "); Console.WriteLine(" ┆ {0} ┆ {1} ┆ {2} ┆", One, Two, Three); Console.WriteLine(" --- --- --- "); Console.WriteLine(" ┆ {0} ┆ {1} ┆ {2} ┆", Four, Five, Six); Console.WriteLine(" --- --- --- "); Console.WriteLine(" ┆ {0} ┆ {1} ┆ {2} ┆", Seven, Eight, Nine); Console.WriteLine(" --- --- --- "); Console.WriteLine(); Console.ForegroundColor = ConsoleColor.White; Console.Write(" X_O ВАШ ХОД : "); } static void Entry() { try { Console.Clear(); Monitor(); Enter = Convert.ToInt32(Console.ReadLine()); switch (Enter) { case 1: if (One == 'X' || One == 'O') { Console.Beep(); Entry(); } else One = 'X'; break; case 2: if (Two == 'X' || Two == 'O') { Console.Beep(); Entry(); } else Two = 'X'; break; case 3: if (Three == 'X' || Three == 'O') { Console.Beep(); Entry(); } else Three = 'X'; break; case 4: if (Four == 'X' || Four == 'O') { Console.Beep(); Entry(); } else Four = 'X'; break; case 5: if (Five == 'X' || Five == 'O') { Console.Beep(); Entry(); } else Five = 'X'; break; case 6: if (Six == 'X' || Six == 'O') { Console.Beep(); Entry(); } else Six = 'X'; break; case 7: if (Seven == 'X' || Seven == 'O') { Console.Beep(); Entry(); } else Seven = 'X'; break; case 8: if (Eight == 'X' || Eight == 'O') { Console.Beep(); Entry(); } else Eight = 'X'; break; case 9: if (Nine == 'X' || Nine == 'O') { Console.Beep(); Entry(); } else Nine = 'X'; break; default: Console.Beep(); break; } } catch { Console.Beep(); Entry(); } } static void PCEntry() { Console.Clear(); Monitor(); Random Num = new Random(); PCEnter = Num.Next(1,9); switch (PCEnter) { case 1: if (One == 'X' || One == 'O') PCEntry(); else One = 'O'; break; case 2: if (Two == 'X' || Two == 'O') PCEntry(); else Two = 'O'; break; case 3: if (Three == 'X' || Three == 'O') PCEntry(); else Three = 'O'; break; case 4: if (Four == 'X' || Four == 'O') PCEntry(); else Four = 'O'; break; case 5: if (Five == 'X' || Five == 'O') PCEntry(); else Five = 'O'; break; case 6: if (Six == 'X' || Six == 'O') PCEntry(); else Six = 'O'; break; case 7: if (Seven == 'X' || Seven == 'O') PCEntry(); else Seven = 'O'; break; case 8: if (Eight == 'X' || Eight == 'O') PCEntry(); else Eight = 'O'; break; case 9: if (Nine == 'X' || Nine == 'O') PCEntry(); else Nine = 'O'; break; default: Console.Beep(); break; } } static void EntryWin() { if (One == 'X' && Two == 'X' && Three == 'X') Win(); if (Four == 'X' && Five == 'X' && Six == 'X') Win(); if (Seven == 'X' && Eight == 'X' && Nine == 'X') Win(); if (One == 'X' && Four == 'X' && Seven == 'X') Win(); if (Two == 'X' && Five == 'X' && Eight == 'X') Win(); if (Three == 'X' && Six == 'X' && Nine == 'X') Win(); if (One == 'X' && Five == 'X' && Nine == 'X') Win(); if (Three == 'X' && Five == 'X' && Seven == 'X') Win(); } static void PCEntryWin() { if (One == 'O' && Two == 'O' && Three == 'O') Lose(); if (Four == 'O' && Five == 'O' && Six == 'O') Lose(); if (Seven == 'O' && Eight == 'O' && Nine == 'O') Lose(); if (One == 'O' && Four == 'O' && Seven == 'O') Lose(); if (Two == 'O' && Five == 'O' && Eight == 'O') Lose(); if (Three == 'O' && Six == 'O' && Nine == 'O') Lose(); if (One == 'O' && Five == 'O' && Nine == 'O') Lose(); if (Three == 'O' && Five == 'O' && Seven == 'O') Lose(); } static void Win() { Cicle = false; Console.Clear(); Console.WriteLine(); Console.WriteLine(" ВЫ ПОБЕДИЛИ!!!"); Console.ReadKey(); } static void Lose() { Cicle = false; Console.Clear(); Console.WriteLine(); Console.WriteLine(" ВЫ ПРОИГРАЛИ!!!"); Console.ReadKey(); } } 

}