Advertisement
SuperLemrick

Tic Tac Toe

Jun 9th, 2015
315
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 20.64 KB | None | 0 0
  1. ////////////////////////////////////////////////////////////////
  2. // Copyright 2013, CompuScholar, Inc.
  3. //
  4. // This source code is for use by the students and teachers who
  5. // have purchased the corresponding TeenCoder or KidCoder product.
  6. // It may not be transmitted to other parties for any reason
  7. // without the written consent of CompuScholar, Inc.
  8. // This source is provided as-is for educational purposes only.
  9. // CompuScholar, Inc. makes no warranty and assumes
  10. // no liability regarding the functionality of this program.
  11. //
  12. ////////////////////////////////////////////////////////////////
  13.  
  14. using System;
  15. using System.Collections.Generic;
  16. using System.Linq;
  17. using Microsoft.Xna.Framework;
  18. using Microsoft.Xna.Framework.Audio;
  19. using Microsoft.Xna.Framework.Content;
  20. using Microsoft.Xna.Framework.GamerServices;
  21. using Microsoft.Xna.Framework.Graphics;
  22. using Microsoft.Xna.Framework.Input;
  23. using Microsoft.Xna.Framework.Media;
  24. using Microsoft.Xna.Framework.Net;
  25. using Microsoft.Xna.Framework.Storage;
  26.  
  27. using SpriteLibrary;
  28.  
  29. namespace TicTacToe
  30. {
  31.     // The Marker class represents a normal Sprite
  32.     // plus an indication of which player placed
  33.     // the X or O symbol
  34.     public class Marker : Sprite
  35.     {
  36.         public int Player;
  37.     };
  38.  
  39.     /// <summary>
  40.     /// This is the main type for your game
  41.     /// </summary>
  42.     public class TicTacToe : Microsoft.Xna.Framework.Game
  43.     {
  44.         GraphicsDeviceManager graphics;
  45.         SpriteBatch spriteBatch;
  46.  
  47.         // these textures represent all of the images used in the game
  48.         Texture2D oTexture;
  49.         Texture2D xTexture;
  50.         Texture2D boardTexture;
  51.         Texture2D splashTexture;
  52.  
  53.         // these sprites are used to display the overlay and splash images
  54.         Sprite overlay;
  55.         Sprite splash;
  56.  
  57.         // the gameboard is a 2D (3x3) grid of Marker objects
  58.         public Marker[,] gameboard;
  59.  
  60.         // these properties keep track of the player scores and current turn
  61.         public int player1Score;
  62.         public int player2Score;
  63.         public int currentPlayer;
  64.  
  65.         // this font is used to display all text in the game
  66.         SpriteFont gameFont;
  67.  
  68.         // constants to help define the grid size and display dimensions
  69.         private const int GRID_SIZE = 3;
  70.         private const int CELL_SIZE = 50;
  71.         private const int LINE_WIDTH = 25;
  72.  
  73.         // this enumeration represnts all game screens
  74.         enum GameScreen
  75.         {
  76.             Splash,
  77.             Menu,
  78.             Playing,
  79.             GameOver
  80.         };
  81.  
  82.         // here we keep track of the current screen
  83.         GameScreen currentScreen;
  84.  
  85.         // user input handling variables
  86.         KeyboardState oldKeyboardState;
  87.         MouseState oldMouseState;
  88.  
  89.         // display the winning game message
  90.         String gameOverMessage;
  91.  
  92.         // This method is provided complete as part of the activity starter.
  93.         public TicTacToe()
  94.         {
  95.             graphics = new GraphicsDeviceManager(this);
  96.             Content.RootDirectory = "Content";
  97.         }
  98.  
  99.         /// <summary>
  100.         /// Allows the game to perform any initialization it needs to before starting to run.
  101.         /// This is where it can query for any required services and load any non-graphic
  102.         /// related content.  Calling base.Initialize will enumerate through any components
  103.         /// and initialize them as well.
  104.         /// </summary>
  105.         // This method is provided complete as part of the activity starter.
  106.         protected override void Initialize()
  107.         {
  108.             // call base initialize first to run LoadContent and get all textures loaded
  109.             // prior to initializing sprites
  110.             base.Initialize();
  111.  
  112.             // start with the splash screen
  113.             currentScreen = GameScreen.Splash;
  114.  
  115.             // set the screen size smaller than normal; don't need a huge window!
  116.             this.graphics.PreferredBackBufferWidth = 400;
  117.             this.graphics.PreferredBackBufferHeight = 400;
  118.             this.graphics.ApplyChanges();
  119.  
  120.             // create a sprite for the splash screen image
  121.             splash = new Sprite();
  122.             splash.SetTexture(splashTexture);
  123.  
  124.             // center the splash on the screen
  125.             splash.UpperLeft = new Vector2(this.GraphicsDevice.Viewport.Width / 2 - splash.GetWidth() / 2,
  126.                                            this.GraphicsDevice.Viewport.Height / 2 - splash.GetHeight() / 2);
  127.  
  128.             // create a sprite for the game board overlay
  129.             overlay = new Sprite();
  130.             overlay.SetTexture(boardTexture);
  131.  
  132.             // center the board on the screen
  133.             overlay.UpperLeft = new Vector2(this.GraphicsDevice.Viewport.Width / 2 - overlay.GetWidth() / 2,
  134.                                             this.GraphicsDevice.Viewport.Height / 2 - overlay.GetHeight() / 2);
  135.  
  136.  
  137.         }
  138.  
  139.         /// <summary>
  140.         /// LoadContent will be called once per game and is the place to load
  141.         /// all of your content.
  142.         /// </summary>
  143.         // This method is provided complete as part of the activity starter.
  144.         protected override void LoadContent()
  145.         {
  146.             // Create a new SpriteBatch, which can be used to draw textures.
  147.             spriteBatch = new SpriteBatch(GraphicsDevice);
  148.  
  149.             // load the game font to be used for all text
  150.             gameFont = this.Content.Load<SpriteFont>("GameFont");
  151.  
  152.             // load all textures to be used in the game
  153.             oTexture = this.Content.Load<Texture2D>("Images\\oSymbol");
  154.             xTexture = this.Content.Load<Texture2D>("Images\\xSymbol");
  155.             boardTexture = this.Content.Load<Texture2D>("Images\\tic_tac_toe_board2");
  156.             splashTexture = this.Content.Load<Texture2D>("Images\\tic_tac_toe_splash");
  157.  
  158.         }
  159.  
  160.         // This method is provided complete as part of the activity starter.
  161.         private void startGame()
  162.         {
  163.             // when a new game is started...
  164.  
  165.             // create new 2D array of markers for the game board
  166.             // (all elements are initially NULL)
  167.             gameboard = new Marker[GRID_SIZE, GRID_SIZE];
  168.  
  169.             // we are now on the playing screen with the X player to start
  170.             currentScreen = GameScreen.Playing;
  171.             currentPlayer = 1;
  172.  
  173.             // let's see the mouse cursor for this screen
  174.             this.IsMouseVisible = true;
  175.         }
  176.  
  177.         // This method is provided complete as part of the activity starter.
  178.         private void stopGame(String message)
  179.         {
  180.             // to stop the game, save the game-over message
  181.             gameOverMessage = message;
  182.             // move to the game over screen
  183.             currentScreen = GameScreen.GameOver;
  184.             // hide the mouse
  185.             this.IsMouseVisible = false;
  186.         }
  187.  
  188.         /// <summary>
  189.         /// UnloadContent will be called once per game and is the place to unload
  190.         /// all content.
  191.         /// </summary>
  192.         // This method is provided complete as part of the activity starter.
  193.         protected override void UnloadContent()
  194.         {
  195.             // TODO: Unload any non ContentManager content here
  196.         }
  197.  
  198.         /// <summary>
  199.         /// Allows the game to run logic such as updating the world,
  200.         /// checking for collisions, gathering input, and playing audio.
  201.         /// </summary>
  202.         /// <param name="gameTime">Provides a snapshot of timing values.</param>
  203.         // This method is provided complete as part of the activity starter.
  204.         protected override void Update(GameTime gameTime)
  205.         {
  206.             // Allows the game to exit
  207.             if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
  208.                 this.Exit();
  209.  
  210.             // user input variable initialization
  211.             KeyboardState currentKeyboard = Keyboard.GetState();
  212.             if (oldKeyboardState == null)
  213.                 oldKeyboardState = currentKeyboard;
  214.  
  215.             // pick the right update method to call based on the current screen
  216.             if (currentScreen == GameScreen.Splash)
  217.             {
  218.                 updateSplash(gameTime, currentKeyboard);
  219.             }
  220.             else if (currentScreen == GameScreen.Menu)
  221.             {
  222.                 updateMenu(gameTime, currentKeyboard);
  223.             }
  224.             else if (currentScreen == GameScreen.Playing)
  225.             {
  226.                 updatePlaying(gameTime, currentKeyboard);
  227.             }
  228.             else if (currentScreen == GameScreen.GameOver)
  229.             {
  230.                 updateGameover(gameTime, currentKeyboard);
  231.             }
  232.  
  233.             // save old keyboard state
  234.             oldKeyboardState = currentKeyboard;
  235.  
  236.             base.Update(gameTime);
  237.         }
  238.  
  239.         // This method is provided complete as part of the activity starter.
  240.         private void updateSplash(GameTime gameTime, KeyboardState currentKeyboard)
  241.         {
  242.             // keep the splash displayed for a few seconds
  243.             if (gameTime.TotalGameTime > TimeSpan.FromSeconds(5))
  244.             {
  245.                 // move to menu screen
  246.                 currentScreen = GameScreen.Menu;
  247.             }
  248.         }
  249.  
  250.         // This method is provided complete as part of the activity starter.
  251.         private bool wasKeyPressed(Keys target, KeyboardState currentKeyboard)
  252.         {
  253.             // return true if the target key has just been pressed
  254.             if (currentKeyboard.IsKeyUp(target) && oldKeyboardState.IsKeyDown(target))
  255.                 return true;
  256.             else
  257.                 return false;
  258.         }
  259.  
  260.         // This method is provided complete as part of the activity starter.
  261.         private void updateMenu(GameTime gameTime, KeyboardState currentKeyboard)
  262.         {
  263.             // from the menu, a space bar press will start a new round of games
  264.             if (wasKeyPressed(Keys.Space, currentKeyboard))
  265.             {
  266.                 player1Score = 0;
  267.                 player2Score = 0;
  268.                 startGame();
  269.             }
  270.             else if (wasKeyPressed(Keys.Escape, currentKeyboard))
  271.             {
  272.                 // the escape key will exit the program
  273.                 Exit();
  274.             }
  275.  
  276.         }
  277.  
  278.         // This method is provided complete as part of the activity starter.
  279.         private bool wasLeftMouseButtonPressed(MouseState currentMouse)
  280.         {
  281.             // return true if the left mouse button is now pressed
  282.             if ((currentMouse.LeftButton == ButtonState.Released) && (oldMouseState.LeftButton == ButtonState.Pressed))
  283.                 return true;
  284.             else
  285.                 return false;
  286.         }
  287.  
  288.         // This method is provided complete as part of the activity starter.
  289.         private void updatePlaying(GameTime gameTime, KeyboardState currentKeyboard)
  290.         {
  291.             // when playing the game, need to track the mouse state
  292.             MouseState currentMouse = Mouse.GetState();
  293.             if (oldMouseState == null)
  294.                 oldMouseState = currentMouse;
  295.  
  296.             // when the user left-clicks the mouse
  297.             if (wasLeftMouseButtonPressed(currentMouse))
  298.             {
  299.                 // get mouse click position relative to UpperLeft point on board
  300.                 Vector2 clickPosition = new Vector2(currentMouse.X, currentMouse.Y) - overlay.UpperLeft;
  301.  
  302.                 // assume the mouse click was not on a valid column and row
  303.                 int col = -1;
  304.                 int row = -1;
  305.  
  306.                 // now check each row and column (0-2) at the same time
  307.                 for (int i = 0; i < GRID_SIZE; i++)
  308.                 {
  309.                     // calculate the min and max coordinate for this cell
  310.                     // (both horizontal and vertical since it's a square!)
  311.                     int bound1 = i * (CELL_SIZE + LINE_WIDTH);
  312.                     int bound2 = bound1 + CELL_SIZE;
  313.  
  314.                     // see if the X-position was within this cell boundary
  315.                     if ((clickPosition.X >= bound1) && (clickPosition.X < bound2))
  316.                     {
  317.                         col = i;    // yes user clicked on a valid column
  318.                     }
  319.                     // see if the Y-position was within this cell boundary
  320.                     if ((clickPosition.Y >= bound1) && (clickPosition.Y < bound2))
  321.                     {
  322.                         row = i;    // yes user clicked on a valid row
  323.                     }
  324.                 }
  325.  
  326.                 // if user clicked on a valid row and column
  327.                 if ((col != -1) && (row != -1))
  328.                 {
  329.                     // if the target cell is currently null (no marker)
  330.                     if (gameboard[col, row] == null)
  331.                     {
  332.                         // create a new marker, store the current player number
  333.                         Marker marker = new Marker();
  334.                         marker.Player = currentPlayer;
  335.  
  336.                         // set the marker texter to X or O based on current player
  337.                         if (currentPlayer == 1)
  338.                             marker.SetTexture(xTexture);
  339.                         else
  340.                             marker.SetTexture(oTexture);
  341.  
  342.                         // position the marker on the selected square
  343.                         marker.UpperLeft = new Vector2(col * (CELL_SIZE + LINE_WIDTH),
  344.                                                        row * (CELL_SIZE + LINE_WIDTH)) + overlay.UpperLeft;
  345.  
  346.                         // store the marker in the 2D array
  347.                         gameboard[col, row] = marker;
  348.  
  349.                         // change players now that a valid move has been made
  350.                         if (currentPlayer == 1)
  351.                             currentPlayer = 2;
  352.                         else
  353.                             currentPlayer = 1;
  354.                     }
  355.                 }
  356.  
  357.                 // see if there is now a winner
  358.                 int winner = checkForWinner();
  359.  
  360.                 // if player 1 has won
  361.                 if (winner == 1)
  362.                 {
  363.                     player1Score++;
  364.                     stopGame("Player 1 Wins!");
  365.                 }
  366.                 else if (winner == 2)   // if player 2 has won
  367.                 {
  368.                     player2Score++;
  369.                     stopGame("Player 2 Wins!");
  370.                 }
  371.                 else if (winner == 3)   // if no player won
  372.                 {
  373.                     stopGame("Tie game!");
  374.                 }
  375.  
  376.             }
  377.  
  378.             // save old mouse state for next time
  379.             oldMouseState = currentMouse;
  380.  
  381.         }
  382.  
  383.         // This method is provided complete as part of the activity starter.
  384.         private int checkLine(Marker m1, Marker m2, Marker m3)
  385.         {
  386.             if ((m1 == null) || (m2 == null) || (m3 == null))
  387.                 return 0;   // no winner if any marker is null
  388.  
  389.             if ((m1.Player == 1) && (m2.Player == 1) && (m3.Player == 1))
  390.                 return 1;   // player 1 has won!
  391.  
  392.             if ((m1.Player == 2) && (m2.Player == 2) && (m3.Player == 2))
  393.                 return 2;   // player 2 has won!
  394.  
  395.             return 0; // no player has won yet
  396.         }
  397.  
  398.         // This method is provided complete as part of the activity starter.
  399.         private int checkForWinner()
  400.         {
  401.             int winner;
  402.  
  403.             // check horizontal lines
  404.             winner = checkLine(gameboard[0, 0], gameboard[1, 0], gameboard[2, 0]);
  405.             if (winner != 0) return winner; // someone has won!
  406.             winner = checkLine(gameboard[0, 1], gameboard[1, 1], gameboard[2, 1]);
  407.             if (winner != 0) return winner; // someone has won!
  408.             winner = checkLine(gameboard[0, 2], gameboard[1, 2], gameboard[2, 2]);
  409.             if (winner != 0) return winner; // someone has won!
  410.  
  411.  
  412.             // check vertical lines
  413.             winner = checkLine(gameboard[0, 0], gameboard[0, 1], gameboard[0, 2]);
  414.             if (winner != 0) return winner; // someone has won!
  415.             winner = checkLine(gameboard[1, 0], gameboard[1, 1], gameboard[1, 2]);
  416.             if (winner != 0) return winner; // someone has won!
  417.             winner = checkLine(gameboard[2, 0], gameboard[2, 1], gameboard[2, 2]);
  418.             if (winner != 0) return winner; // someone has won!
  419.  
  420.             // check diagonal lines
  421.             winner = checkLine(gameboard[0, 0], gameboard[1, 1], gameboard[2, 2]);
  422.             if (winner != 0) return winner; // someone has won!
  423.             winner = checkLine(gameboard[2, 0], gameboard[1, 1], gameboard[0, 2]);
  424.             if (winner != 0) return winner; // someone has won!
  425.  
  426.             // check for tie game (all squares filled)
  427.             for (int row = 0; row < GRID_SIZE; row++)
  428.             {
  429.                 for (int col = 0; col < GRID_SIZE; col++)
  430.                 {
  431.                     if (gameboard[col, row] == null)
  432.                         return 0;   // not a tie game yet
  433.                 }
  434.             }
  435.  
  436.             return 3;   // tie game!
  437.         }
  438.  
  439.         // This method is provided complete as part of the activity starter.
  440.         private void updateGameover(GameTime gameTime, KeyboardState currentKeyboard)
  441.         {
  442.             // if space bar was pressed
  443.             if (wasKeyPressed(Keys.Space, currentKeyboard))
  444.             {
  445.                 // start a new game
  446.                 startGame();
  447.             }
  448.             // if escape was pressed
  449.             else if (wasKeyPressed(Keys.Escape, currentKeyboard))
  450.             {
  451.                 // return to main menu
  452.                 currentScreen = GameScreen.Menu;
  453.             }
  454.         }
  455.  
  456.  
  457.         /// <summary>
  458.         /// This is called when the game should draw itself.
  459.         /// </summary>
  460.         /// <param name="gameTime">Provides a snapshot of timing values.</param>
  461.         // The student will complete this method as part of the chapter activity.
  462.         protected override void Draw(GameTime gameTime)
  463.         {
  464.             GraphicsDevice.Clear(Color.Azure);
  465.  
  466.             spriteBatch.Begin();
  467.  
  468.             switch (currentScreen)
  469.             {
  470.                 case GameScreen.Splash:
  471.                     drawSplash(gameTime);
  472.                     break;
  473.                 case GameScreen.Menu:
  474.                     drawMenu(gameTime);
  475.                     break;
  476.                 case GameScreen.Playing:
  477.                     drawPlaying(gameTime);
  478.                     break;
  479.                 case GameScreen.GameOver:
  480.                     drawPlaying(gameTime);
  481.                     drawGameOver(gameTime);
  482.                     break;
  483.             }
  484.  
  485.             spriteBatch.End();
  486.  
  487.             base.Draw(gameTime);
  488.         }
  489.  
  490.         // The student will complete this method as part of the chapter activity.
  491.         private void drawSplash(GameTime gameTime)
  492.         {
  493.             splash.Draw(spriteBatch);
  494.         }
  495.  
  496.         // The student will complete this method as part of the chapter activity.
  497.         private void drawMenu(GameTime gameTime)
  498.         {
  499.             spriteBatch.DrawString(gameFont, "Press Space to begin new round", new Vector2(30, 10), Color.Black);
  500.             spriteBatch.DrawString(gameFont, "Press ESC to exit game", new Vector2(30, 30), Color.Black);
  501.  
  502.             overlay.Draw(spriteBatch);
  503.         }
  504.  
  505.         // The student will complete this method as part of the chapter activity.
  506.         private void drawPlaying(GameTime gameTime)
  507.         {
  508.             for (int col = 0; col < GRID_SIZE; col++)
  509.             {
  510.                 for (int row = 0; row < GRID_SIZE; row++)
  511.                 {
  512.                     if (gameboard[col, row] != null)
  513.                     {
  514.                         gameboard[col, row].Draw(spriteBatch);
  515.                     }
  516.                 }
  517.             }
  518.  
  519.             overlay.Draw(spriteBatch);
  520.  
  521.             spriteBatch.DrawString(gameFont, "Player 1 Score: " + player1Score.ToString(), new Vector2(overlay.UpperLeft.X, overlay.UpperLeft.Y + overlay.GetHeight() + 20), Color.Black);
  522.             spriteBatch.DrawString(gameFont, "Player 2 Score: " + player2Score.ToString(), new Vector2(overlay.UpperLeft.X, overlay.UpperLeft.Y + overlay.GetHeight() + 50), Color.Black);
  523.         }
  524.  
  525.         // The student will complete this method as part of the chapter activity.
  526.         private void drawGameOver(GameTime gameTime)
  527.         {
  528.             spriteBatch.DrawString(gameFont, gameOverMessage, new Vector2(30, 10), Color.Red);
  529.             spriteBatch.DrawString(gameFont, "Press Space to play again", new Vector2(30, 40), Color.Black);
  530.             spriteBatch.DrawString(gameFont, "Press ESC to return to the main menu", new Vector2(30, 60), Color.Black);
  531.         }
  532.     }
  533. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement