Advertisement
PIBogdanov

TicTacToeC#

Jul 3rd, 2023
90
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 20.80 KB | None | 0 0
  1. using System.Runtime.InteropServices;
  2.  
  3. namespace TicTacToeFP;
  4.  
  5. public partial class TicTacToe
  6. {
  7.  
  8. /*
  9. ************************************************************
  10.     C# CONSOLE APPLICATION
  11.     THIS PROJECT IS ABOUT A
  12.     TIC TAC TOE GAME
  13.     FOR THIS PROJECT IS USED FUNCTIONAL PROGRAMMING (FP)
  14. ************************************************************
  15. */
  16.  
  17. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  18.  
  19. /*
  20. ************************************************************
  21.                     START OF THE PROJECT
  22. ************************************************************
  23. */
  24.  
  25. /*
  26. ************************************************************
  27.     THIS PART OF THE CODE IS TO MAKE
  28.     THE CONSOLE WINDOW IN FULL SCREEN AUTOMATICALLY,
  29.     WHEN CALLED
  30. ************************************************************
  31. */
  32.  
  33. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  34.  
  35.     [LibraryImport("kernel32.dll")]
  36.  
  37.     private static partial IntPtr GetConsoleWindow();
  38.  
  39.     private static readonly IntPtr ThisCon = GetConsoleWindow();
  40.  
  41.     [LibraryImport("user32.dll", SetLastError = true)]
  42.  
  43.     [return: MarshalAs(UnmanagedType.Bool)]
  44.  
  45.     private static partial bool ShowWindow(IntPtr hWnd, int nCmdShow);
  46.  
  47.     private const int MAXIMIZE = 3;
  48.  
  49. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  50.  
  51. /*
  52. ************************************************************
  53.     THIS PART OF THE CODE IS TO HELP
  54.     THE "WriteCentered" METHOD TO CENTER THE TEXT
  55.     IN THE MIDDLE OF THE CONSOLE
  56. ************************************************************
  57. */
  58.  
  59. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  60.  
  61.     [LibraryImport("kernel32.dll")]
  62.  
  63.     private static partial IntPtr GetStdHandle(int nStdHandle);
  64.  
  65.     [StructLayout(LayoutKind.Sequential)]
  66.  
  67.     struct COORD
  68.     {
  69.         public short X;
  70.  
  71.         public short Y;
  72.     }
  73.  
  74.     [LibraryImport("kernel32.dll")]
  75.  
  76.     [return: MarshalAs(UnmanagedType.Bool)]
  77.  
  78.     private static partial bool GetConsoleScreenBufferInfo(IntPtr hConsoleOutput, out CONSOLE_SCREEN_BUFFER_INFO lpConsoleScreenBufferInfo);
  79.  
  80.     [StructLayout(LayoutKind.Sequential)]
  81.  
  82.     struct CONSOLE_SCREEN_BUFFER_INFO
  83.     {
  84.         public COORD dwSize;
  85.  
  86.         public COORD dwCursorPosition;
  87.  
  88.         public ushort wAttributes;
  89.  
  90.         public SMALL_RECT srWindow;
  91.  
  92.         public COORD dwMaximumWindowSize;
  93.     }
  94.  
  95.     [StructLayout(LayoutKind.Sequential)]
  96.  
  97.     struct SMALL_RECT
  98.     {
  99.         public short Left;
  100.  
  101.         public short Top;
  102.  
  103.         public short Right;
  104.  
  105.         public short Bottom;
  106.     }
  107.  
  108. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  109.  
  110.     static void Main(string[] args)
  111.     {
  112.         ShowWindow(ThisCon, MAXIMIZE); // FULL SCREEN
  113.  
  114.         Console.CursorVisible = false; // TURN THE VISIBILITY OF THE CURSOR TO OFF
  115.  
  116.         MainMenu();
  117.     }
  118.  
  119. /*
  120. ************************************************************
  121.     CREATING A METHOD,
  122.     WHICH DOESN'T TAKE ANY PARAMETERS
  123.     AND TAKES METHODS AS ELEMENTS,
  124.     WHICH DON'T RETURN ANYTHING
  125. ************************************************************
  126. */
  127.  
  128.     delegate void menuOption();
  129.  
  130. /*
  131. ************************************************************
  132.     USING THE CREATED METHOD TO CREATE AN ARRAY
  133. ************************************************************
  134. */
  135.  
  136.     static menuOption[] mainMenuOptions = { GameStart, ExitGame };
  137.  
  138. /*
  139. ************************************************************
  140.     METHOD TO DISPLAY THE MAIN MENU
  141. ************************************************************
  142. */
  143.  
  144.     static void MainMenu()
  145.     {
  146.         string[] mainMenu = { "Start Game", "Exit" };
  147.  
  148.         int pointer = 0;
  149.  
  150.         bool arrowVisible = true;
  151.  
  152.         while (true)
  153.         {
  154.             Console.Clear();
  155.  
  156.             Console.ForegroundColor = ConsoleColor.Red;
  157.  
  158.             for (int i = 0; i < 16; i++)
  159.             {
  160.                 Console.WriteLine();
  161.             }
  162.  
  163.             WriteCentered("Tic Tac Toe");
  164.  
  165.             for (int i = 0; i < 3; i++)
  166.             {
  167.                 Console.WriteLine();
  168.             }
  169.  
  170.             WriteCentered("Main Menu");
  171.  
  172.             for (int i = 0; i < 3; i++)
  173.             {
  174.                 Console.WriteLine();
  175.             }
  176.  
  177.             for (int i = 0; i < mainMenu.Length; i++)
  178.             {
  179.                 if (i == pointer)
  180.                 {
  181.                     Console.ForegroundColor = ConsoleColor.Green;
  182.  
  183.                     if (arrowVisible)
  184.                     {
  185.                         WriteCentered("-> " + mainMenu[i]);
  186.  
  187.                         Console.WriteLine();
  188.  
  189.                         arrowVisible = false;
  190.                     }
  191.  
  192.                     else
  193.                     {
  194.                         WriteCentered("   ");
  195.  
  196.                         Console.WriteLine();
  197.  
  198.                         arrowVisible = true;
  199.                     }
  200.                 }
  201.  
  202.                 else
  203.                 {
  204.                     Console.ForegroundColor = ConsoleColor.Red;
  205.  
  206.                     WriteCentered(mainMenu[i]);
  207.  
  208.                     Console.WriteLine();
  209.                 }
  210.             }
  211.  
  212.             if (Console.KeyAvailable)
  213.             {
  214.                 ConsoleKeyInfo inputKey = Console.ReadKey(true);
  215.  
  216.                 bool upKeyState = inputKey.Key == ConsoleKey.UpArrow;
  217.  
  218.                 if (upKeyState)
  219.                 {
  220.                     pointer--;
  221.  
  222.                     if (pointer == -1)
  223.                     {
  224.                         pointer = mainMenu.Length - 1;
  225.                     }
  226.  
  227.                     continue;
  228.                 }
  229.  
  230.                 bool downKeyState = inputKey.Key == ConsoleKey.DownArrow;
  231.  
  232.                 if (downKeyState)
  233.                 {
  234.                     pointer++;
  235.  
  236.                     if (pointer == mainMenu.Length)
  237.                     {
  238.                         pointer = 0;
  239.                     }
  240.  
  241.                     continue;
  242.                 }
  243.  
  244.                 bool returnKeyState = inputKey.Key == ConsoleKey.Enter;
  245.  
  246.                 if (returnKeyState)
  247.                 {
  248.                     mainMenuOptions[pointer]();
  249.                 }
  250.             }
  251.  
  252.             Thread.Sleep(200);
  253.         }
  254.     }
  255.  
  256. /*
  257. ************************************************************
  258.     METHOD TO CALL THE NEEDED METHODS,
  259.     SO THE PLAYER / PLAYERS CAN PLAY
  260. ************************************************************
  261. */
  262.  
  263.     static void GameStart()
  264.     {
  265.         string[] names = new string [2];
  266.  
  267.         string choice = ChoiceMenu();
  268.  
  269.         if (choice == "yes")
  270.         {
  271.             char[] marks = { 'X', 'O' };
  272.  
  273.             Console.Clear();
  274.  
  275.             for (int i = 0; i < 20; i++)
  276.             {
  277.                 Console.WriteLine();
  278.             }
  279.  
  280.             for (int i = 0; i < names.Length; i++)
  281.             {
  282.                 Console.WriteLine();
  283.  
  284.                 WriteCentered("Enter a name for Player " + (i + 1).ToString() + ", who will be with the symbol '" + marks[i] + "': ");
  285.  
  286.                 names[i] = EnterName();
  287.             }
  288.         }
  289.  
  290.         else if (choice == "no")
  291.         {
  292.             Console.ForegroundColor = ConsoleColor.Red;
  293.  
  294.             names[0] = "Player 1";
  295.  
  296.             names[1] = "Player 2";
  297.         }
  298.  
  299.         GamePlay(names);
  300.     }
  301.  
  302. /*
  303. ************************************************************
  304.     METHOD TO EXIT THE GAME
  305. ************************************************************
  306. */
  307.  
  308.     static void ExitGame()
  309.     {
  310.         Console.Clear();
  311.  
  312.         Console.ForegroundColor = ConsoleColor.Red;
  313.  
  314.         Environment.Exit(0);
  315.     }
  316.  
  317. /*
  318. ************************************************************
  319.     CREATING A METHOD,
  320.     WHICH DOESN'T TAKE ANY PARAMETERS
  321.     AND TAKES METHODS AS ELEMENTS,
  322.     WHICH RETURN A STRING
  323. ************************************************************
  324. */
  325.  
  326.     delegate string ChoiceOption();
  327.  
  328. /*
  329. ************************************************************
  330.     USING THE CREATED METHOD TO CREATE AN ARRAY
  331. ************************************************************
  332. */
  333.  
  334.     static ChoiceOption[] choiceMenuOptions = { ChoiceIsYes, ChoiceIsNo };
  335.  
  336. /*
  337. ************************************************************
  338.     METHOD TO DISPLAY THE CHOICE MENU
  339. ************************************************************
  340. */
  341.  
  342.     static string ChoiceMenu()
  343.     {
  344.         string[] choiceMenu = { "Yes", "No" };
  345.  
  346.         int pointer = 0;
  347.  
  348.         bool arrowVisible = true;
  349.  
  350.         while (true)
  351.         {
  352.             Console.Clear();
  353.  
  354.             Console.ForegroundColor = ConsoleColor.Red;
  355.  
  356.             for (int i = 0; i < 20; i++)
  357.             {
  358.                 Console.WriteLine();
  359.             }
  360.  
  361.             WriteCentered("Do you want to change the names from \"Player 1\" and \"Player 2\" to something different?");
  362.  
  363.             for (int i = 0; i < 3; i++)
  364.             {
  365.                 Console.WriteLine();
  366.             }
  367.  
  368.             for (int i = 0; i < choiceMenu.Length; i++)
  369.             {
  370.                 if (i == pointer)
  371.                 {
  372.                     Console.ForegroundColor = ConsoleColor.Green;
  373.  
  374.                     if (arrowVisible)
  375.                     {
  376.                         WriteCentered("-> " + choiceMenu[i]);
  377.  
  378.                         Console.WriteLine();
  379.  
  380.                         arrowVisible = false;
  381.                     }
  382.  
  383.                     else
  384.                     {
  385.                         WriteCentered("   ");
  386.  
  387.                         Console.WriteLine();
  388.  
  389.                         arrowVisible = true;
  390.                     }
  391.                 }
  392.  
  393.                 else
  394.                 {
  395.                     Console.ForegroundColor = ConsoleColor.Red;
  396.  
  397.                     WriteCentered(choiceMenu[i]);
  398.  
  399.                     Console.WriteLine();
  400.                 }
  401.             }
  402.  
  403.             if (Console.KeyAvailable)
  404.             {
  405.                 ConsoleKeyInfo inputKey = Console.ReadKey(true);
  406.  
  407.                 bool upKeyState = inputKey.Key == ConsoleKey.UpArrow;
  408.  
  409.                 if (upKeyState)
  410.                 {
  411.                     pointer--;
  412.  
  413.                     if (pointer == -1)
  414.                     {
  415.                         pointer = choiceMenu.Length - 1;
  416.                     }
  417.  
  418.                     continue;
  419.                 }
  420.  
  421.                 bool downKeyState = inputKey.Key == ConsoleKey.DownArrow;
  422.  
  423.                 if (downKeyState)
  424.                 {
  425.                     pointer++;
  426.  
  427.                     if (pointer == choiceMenu.Length)
  428.                     {
  429.                         pointer = 0;
  430.                     }
  431.  
  432.                     continue;
  433.                 }
  434.  
  435.                 bool returnKeyState = inputKey.Key == ConsoleKey.Enter;
  436.  
  437.                 if (returnKeyState)
  438.                 {
  439.                     return choiceMenuOptions[pointer]();
  440.                 }
  441.  
  442.                 BackToMainMenu(inputKey);
  443.             }
  444.  
  445.             Thread.Sleep(200);
  446.         }
  447.     }
  448.  
  449. /*
  450. ************************************************************
  451.     METHOD TO RETURN "yes",
  452.     SO THE USER CAN INPUT DIFFERENT NAMES
  453. ************************************************************
  454. */
  455.  
  456.     static string ChoiceIsYes()
  457.     {
  458.         return "yes";
  459.     }
  460.  
  461. /*
  462. ************************************************************
  463.     METHOD TO RETURN "no",
  464.     SO THE NAMES WON'T BE CHANGED
  465. ************************************************************
  466. */
  467.  
  468.     static string ChoiceIsNo()
  469.     {
  470.         return "no";
  471.     }
  472.  
  473. /*
  474. ************************************************************
  475.     METHOD TO INPUT A NAME
  476. ************************************************************
  477. */
  478.  
  479.     static string EnterName()
  480.     {
  481.         string name = Console.ReadLine();
  482.  
  483.         return name;
  484.     }
  485.  
  486. /*
  487. ************************************************************
  488.     METHOD TO ALLOW THE PLAYER / PLAYERS TO PLAY
  489. ************************************************************
  490. */
  491.  
  492.     static void GamePlay(string[] names)
  493.     {
  494.         string[] square = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
  495.  
  496.         int sizeOfTheArray = square.Length;
  497.  
  498.         int player = 1, gameState = -1;
  499.  
  500.         char mark;
  501.  
  502.         while ( (gameState == -1) && (player != 6) )
  503.         {
  504.             player = (player % 2 == 1) ? 1 : 2;
  505.  
  506.             mark = (player == 1) ? 'X' : 'O';
  507.  
  508.             Board(square, names, sizeOfTheArray);
  509.  
  510.             WriteCentered("It's " + names[player - 1] + "'s turn.");
  511.  
  512.             player = ActionChoice(square, player, mark, sizeOfTheArray);
  513.  
  514.             gameState = GameState(square);
  515.         }
  516.  
  517.         if ( (gameState == 0) || (gameState == 1) )
  518.         {
  519.             Board(square, names, sizeOfTheArray);
  520.  
  521.             if (gameState == 1)
  522.             {
  523.                 int index = (--player == 1) ? 0 : 1;
  524.  
  525.                 WriteCentered("==> " + names[index] + " won! <==");
  526.             }
  527.  
  528.             else if (gameState == 0)
  529.             {
  530.                 WriteCentered("==> Game draw <==");
  531.             }
  532.  
  533.             for (int i = 0; i < 2; i++)
  534.             {
  535.                 Console.WriteLine();
  536.             }
  537.  
  538.             PressEnterToContinue();
  539.         }
  540.     }
  541.  
  542. /*
  543. ************************************************************
  544.     METHOD TO DRAW THE TIC TAC TOE BOARD
  545.     WITH THE PLAYERS MARK
  546. ************************************************************
  547. */
  548.  
  549.     static void Board(string[] square, string[] names, int size)
  550.     {
  551.         Console.Clear();
  552.  
  553.         for (int i = 0; i < 14; i++)
  554.         {
  555.             Console.WriteLine();
  556.         }
  557.  
  558.         WriteCentered("Tic Tac Toe");
  559.  
  560.         for (int i = 0; i < 4; i++)
  561.         {
  562.             Console.WriteLine();
  563.         }
  564.  
  565.         WriteCentered(names[0] + " (X)  -  " + names[1] + " (O)");
  566.  
  567.         for (int i = 0; i < 4; i++)
  568.         {
  569.             Console.WriteLine();
  570.         }
  571.  
  572.         WriteCentered("     |     |     ");
  573.  
  574.         Console.WriteLine();
  575.  
  576.         for (int i = 0; i < size - 2; i += 3)
  577.         {
  578.             WriteCentered(square[i] + "  |  " + square[i + 1] + "  |  " + square[i + 2]);
  579.  
  580.             Console.WriteLine();
  581.  
  582.             if (i != 6)
  583.             {
  584.                 WriteCentered("_____|_____|_____");
  585.  
  586.                 Console.WriteLine();
  587.  
  588.                 WriteCentered("     |     |     ");
  589.  
  590.                 Console.WriteLine();
  591.             }
  592.         }
  593.  
  594.         WriteCentered("     |     |     ");
  595.  
  596.         for (int i = 0; i < 4; i++)
  597.         {
  598.             Console.WriteLine();
  599.         }
  600.     }
  601.  
  602. /*
  603. ************************************************************
  604.     METHOD TO ALLOW THE PLAYERS TO PRESS
  605.      A NUMBER 1 TO 9 AND CHANGE IT TO EITHER 'X' OR 'O'
  606.     "R" / "r" TO RESTART THE GAME
  607.     "Q" / "q" TO GO BACK TO THE MAIN MENU
  608. ************************************************************
  609. */
  610.  
  611.     static int ActionChoice(string[] square, int player, char mark, int size)
  612.     {
  613.         while (true)
  614.         {
  615.             ConsoleKeyInfo inputKey = Console.ReadKey(true);
  616.  
  617.             int key = inputKey.KeyChar - '0';
  618.  
  619.             if ( ( (key > 0) && (key < 10) ) && (square[key - 1] == key.ToString()))
  620.             {
  621.                 CheckActionChoice(square, mark, key, size);
  622.  
  623.                 player++;
  624.  
  625.                 break;
  626.             }
  627.  
  628.             else if ( (inputKey.KeyChar == 'R') || (inputKey.KeyChar == 'r') ) // Check for 'R' or 'r' key press
  629.             {
  630.                 for (int i = 0; i < size; i++)
  631.                 {
  632.                     if ( (square[i] == "X") || (square[i] == "O") )
  633.                     {
  634.                         square[i] = (i + 1).ToString();
  635.                     }
  636.                 }
  637.  
  638.                 player = 1;
  639.  
  640.                 break;
  641.             }
  642.  
  643.             else if ( (inputKey.KeyChar == 'Q') || (inputKey.KeyChar == 'q') ) // Check for 'Q' or 'q' key press
  644.             {
  645.                 player = 6; // It takes this value, so in the loop in the GamePlay function can break and go back to the Main Menu
  646.  
  647.                 break;
  648.             }
  649.  
  650.             else
  651.             {
  652.                 Console.Clear();
  653.  
  654.                 for (int i = 0; i < 20; i++)
  655.                 {
  656.                     Console.WriteLine();
  657.                 }
  658.                
  659.                 WriteCentered("Invalid move!");
  660.  
  661.                 for (int i = 0; i < 4; i++)
  662.                 {
  663.                     Console.WriteLine();
  664.                 }
  665.  
  666.                 PressEnterToContinue();
  667.  
  668.                 break;
  669.             }
  670.         }
  671.  
  672.         return player;
  673.     }
  674.  
  675. /*
  676. ************************************************************
  677.     METHOD TO CHECK THE PRESSED NUMBER,
  678.        IF IT CAN BE CHANGED TO EITHER
  679.                  'X' OT 'O'                
  680. ************************************************************
  681. */
  682.  
  683.     static void CheckActionChoice(string[] square, char mark, int key, int size)
  684.     {
  685.         for (int i = 0; i < size; i++)
  686.         {
  687.             if (key.ToString() == square[i])
  688.             {
  689.                 square[i] = mark.ToString();
  690.  
  691.                 break;
  692.             }
  693.         }
  694.     }
  695.  
  696. /*
  697. ************************************************************
  698.     METHOD TO RETURN THE GAME STATUS:
  699.      1 ==> GAME IS OVER WITH A RESULT
  700.     -1 ==> GAME IS IN PROGRESS
  701.      O ==> GAME IS OVER AND NO RESULT
  702. ************************************************************
  703. */
  704.  
  705.     static int GameState(string[] square)
  706.     {
  707.         if ( (square[0] == square[1]) && (square[1] == square[2]) )
  708.         {
  709.             return 1;
  710.         }
  711.  
  712.         else if ( (square[3] == square[4]) && (square[4] == square[5]) )
  713.         {
  714.             return 1;
  715.         }
  716.  
  717.         else if ( (square[6] == square[7]) && (square[7] == square[8]) )
  718.         {
  719.             return 1;
  720.         }
  721.  
  722.         else if ( (square[0] == square[3]) && (square[3] == square[6]) )
  723.         {
  724.             return 1;
  725.         }
  726.  
  727.         else if ( (square[1] == square[4]) && (square[4] == square[7]) )
  728.         {
  729.             return 1;
  730.         }
  731.  
  732.         else if ( (square[2] == square[5]) && (square[5] == square[8]) )
  733.         {
  734.             return 1;
  735.         }
  736.  
  737.         else if ( (square[0] == square[4]) && (square[4] == square[8]) )
  738.         {
  739.             return 1;
  740.         }
  741.  
  742.         else if ( (square[2] == square[4]) && (square[4] == square[6]) )
  743.         {
  744.             return 1;
  745.         }
  746.  
  747.         else if ( (square[0] != "1") && (square[1] != "2") && (square[2] != "3") &&
  748.                   (square[3] != "4") && (square[4] != "5") && (square[5] != "6") &&
  749.                   (square[6] != "7") && (square[7] != "8") && (square[8] != "9") )
  750.         {
  751.             return 0;
  752.         }
  753.  
  754.         return -1;
  755.     }
  756.  
  757. /*
  758. ************************************************************
  759.     METHOD TO ALLOW THE USER
  760.     TO GO BACK TO THE MAIN MENU,
  761.     IF THE "ESCAPE" BUTTON IS PRESSED
  762. ************************************************************
  763. */
  764.  
  765.     static void BackToMainMenu(ConsoleKeyInfo inputKey)
  766.     {
  767.         if (inputKey.Key == ConsoleKey.Escape)
  768.         {
  769.             MainMenu();
  770.         }
  771.     }
  772.  
  773. /*
  774. ************************************************************
  775.     METHOD TO ALLOW THE USER TO INPUT AGAIN,
  776.     IF THE "ENTER" BUTTON IS PRESSED
  777. ************************************************************
  778. */
  779.  
  780.     static void PressEnterToContinue()
  781.     {
  782.         WriteCentered("Press \"ENTER\" to continue!");
  783.  
  784.         while (Console.ReadKey(true).Key != ConsoleKey.Enter);
  785.     }
  786.  
  787. /*
  788. ************************************************************
  789.     METHOD TO CENTER THE TEXT
  790.     IN THE MIDDLE OF THE CONSOLE
  791. ************************************************************
  792. */
  793.  
  794.     static void WriteCentered(string text)
  795.     {
  796.  
  797.         int consoleWidth = Console.WindowWidth;
  798.  
  799.         int textWidth = text.Length;
  800.  
  801.         int leftMargin = (consoleWidth - textWidth) / 2;
  802.  
  803.         string centeredText = new string(' ', leftMargin) + text;
  804.  
  805.         Console.Write(centeredText);
  806.     }
  807.  
  808. /*
  809. ************************************************************
  810.                      END OF THE PROJECT
  811. ************************************************************
  812. */
  813.  
  814. ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
  815.  
  816. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement