Home > Enterprise >  Should I declare and create an instance of a class inside loop?
Should I declare and create an instance of a class inside loop?

Time:04-07

I wrote a simple console game (TicTacToe to be specific) for practice. After game over I need to reset the game so I am creating a new instance of the game class.

Is the old instance of class destroyed before creating the new one?

If not then it is getting stacked up in the memory which is not good. So what is the better practice here?


//main class
using System;

namespace TicTacToe
{
    internal class Program
    {
        static void Main(string[] args)
        {
            bool restart = true;  //stores decision whether to restart the game
            do
            {
                Game game = new Game();  //a simple console game
                game.start();            //start -> play -> game over
                restart = playAgain();   //playAgain returns a boolean
            } while (restart);

        }

        public static bool playAgain()
        {
            Console.WriteLine("Do you want to play again? (y/N): ");
            string input = Console.ReadLine();
            if (input == "y" || input == "Y")
                return true;
            else return false;
        }
    }
}


//game class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TicTacToe
{
    internal class Game
    {
        string[] values = new string[9] { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
        bool gameOver;
        int turns;
        public Game()
        {
            this.turns = 0;
            this.gameOver = false;
        }

        public void displayGameCard()
        {
            Console.Clear();
            Console.WriteLine( "     |     |     ");
            Console.WriteLine($"  {values[0]}  |  {values[1]}  |  {values[2]} ");
            Console.WriteLine("_____|_____|_____");
            Console.WriteLine("     |     |     ");
            Console.WriteLine($"  {values[3]}  |  {values[4]}  |  {values[5]} ");
            Console.WriteLine("_____|_____|_____");
            Console.WriteLine("     |     |     ");
            Console.WriteLine($"  {values[6]}  |  {values[7]}  |  {values[8]} ");
            Console.WriteLine("     |     |     ");
            //Console.WriteLine("-----------");
        }

        public void player1()
        {
            string strInput;
            int index;
            bool flag = true;
            do
            {
                Console.Write("\nPlayer 1: ");
                strInput = Console.ReadLine();
                if (values.Contains(strInput) && strInput != "O" && strInput != "X")
                {
                    flag = false;
                }
                else Console.WriteLine("Invalid Input! Try Again!");

            } while (flag == true);
            this.turns  ;
            index = int.Parse(strInput) - 1;
            values[index] = "O";
            displayGameCard();
            this.gameOver = checkResult();
        }

        public void player2()
        {
            string strInput;
            int index;
            bool flag = true;
            do
            {
                Console.Write("\nPlayer 2: ");
                strInput = Console.ReadLine();
                if (values.Contains(strInput) && strInput != "O" && strInput != "X")
                {
                    flag = false;
                }
                else Console.WriteLine("Invalid Input! Try Again!");
            } while (flag == true);
            this.turns  ;
            index = int.Parse(strInput) - 1;
            values[index] = "X";
            displayGameCard();
            this.gameOver = checkResult();
        }

        public bool checkResult()
        {
            bool flag = false;
            if (values[0] == values[1] && values[1] == values[2])
                flag = true;
            else if (values[3] == values[4] && values[4] == values[5])
                flag = true;
            else if (values[6] == values[7] && values[7] == values[8])
                flag = true;
            else if (values[0] == values[3] && values[3] == values[6])
                flag = true;
            else if (values[1] == values[4] && values[4] == values[7])
                flag = true;
            else if (values[2] == values[5] && values[5] == values[8])
                flag = true;
            else if (values[0] == values[4] && values[4] == values[8])
                flag = true;
            else if (values[2] == values[4] && values[4] == values[6])
                flag = true;
            return flag;
        }

        public void play()
        {
            displayGameCard();
            player1();
            if (this.turns == 9)
            {
                Console.WriteLine("It's a draw!");
                this.gameOver = true;
            }
            else if (this.gameOver)
            {
                Console.WriteLine("Player 1 won!");
            }
            else
            {
                player2();
                if (this.gameOver)
                    Console.WriteLine("Player 2 won!");
            }
            }

        public void start()
        {
            do
            {
                play();
            } while (this.gameOver == false);
        }
    }
}


The code is written in c# if that is relevant.

CodePudding user response:

As far as I know (because I'm relatively new to this) all variables that you declare in the do scope are local, and when the program is out of that scope those variables are destroyed. So, the instance of the game class that you declare in the do scope is local and will therefore be destroyed when the while loop checks the condition again.

CodePudding user response:

When you create a new instance of the Game class called game all you are doing is setting the variable game to a new instance. game is saved in memory so the next time you start a game it will take the variable game and regardless of what state it's in, will set it to a new instance. This means that there is never more than once instance of that class regardless of it being in a do/while loop because you are using the same variable.

CodePudding user response:

The short version:

Should I declare and create an instance of a class inside loop?

Yes, if you only need that instance inside the loop.


When we create an object

Game game = new Game();

...it "exists" in memory as long as there are references to it. When there are no longer any references to an object it becomes available for garbage collection.

So the question is, what references are there to the created Game object? It appears that there is only one reference, the game variable that you assign it to.

So now the question is, how long does that variable live? It lives as long as the scope within which it is defined. In this case you're defining it within a do loop. As soon as that execution of the loop is over (a few lines later) the variable goes out of scope. In other words, the scope within which it was defined no longer exists. In simpler terms, that variable no longer exists.

The variable is the only reference to that exact Game object. When the variable goes out of scope, there are no longer any references to that Game object. It will be garbage collected. (That doesn't happen instantly, but we don't have to worry about exactly when it happens. We don't usually care. That's something the framework worries about for us.)

What if the loop repeats? Think of the inside of that loop as a method that gets called over and over. When it gets called again, the game variable is new, because it's declared inside the loop. It doesn't "know" anything about the previous execution of the loop or the previous Game object. That variable went out of scope at the end of that iteration of the loop.

How do we tell what the scope of a variable is? One easy way is to see where we're allowed to use it.

If you tried to write this, using the game variable outside of the loop:

        static void Main(string[] args)
        {
            bool restart = true;  //stores decision whether to restart the game
            do
            {
                Game game = new Game();  //a simple console game
                game.start();            //start -> play -> game over
                restart = playAgain();   //playAgain returns a boolean
            } while (restart);

        }
        game.Start(); // <-- Outside the loop where it was declared

...it wouldn't compile. That's because the variable is declared inside the loop, so it's not available outside the loop. Just like if we declare a local variable inside one method it's not visible or accessible inside another method.

  • Related