⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 form.cs

📁 tic tac toe is simple game .I think every people had play it
💻 CS
字号:
using System.Windows.Forms;
using System.Drawing;
using System.Threading;
using System;


class TicTacToe : Form
{
    #region Fields

    public static readonly int Computer = -1;
    public static readonly int Human    =  1;
    
    Board            GameBoard;
    SquareControl[,] aSquares;
    private int      CurrentPlayer;        //Computer or human?
    private int      FirstPlayer;          //Who gets first move?
    private int      ComputerFigure;       //Does computer use X or O?

    //worker thread for AI 
    Thread CalculateComputerMoveThread;
    
    //Size of the board in one dimension 
    int iBoardSize;
    
    //Used for sizing SquareControls
    int iSquareSize;

    //Used for mutually exclusive option storage
    MenuItemInt miiFirstPlayer;
    MenuItemInt miiComputerFigure;
    
    //MenuItems to deactivate during game play
    MenuItemInt[] amiiMenuItemsToDeactivate;


    #endregion

    public static void Main()
    {
        //TicTacToe form = new TicTacToe(3);
        Application.Run(new TicTacToe(3));
    }
    
    public TicTacToe(int Size)
    {
        iBoardSize = Size;
        
        //
        // Create Menus
        //

        //Main menu 
        this.Menu = new MainMenu();
        
        
        //File menu
        MenuItem File          = new MenuItem("&File");
        MenuItem NewGame       = new MenuItem("&NewGame", new EventHandler(OnFileNewGameClick),
                                        Shortcut.CtrlN);
        this.Menu.MenuItems.Add(File);
        this.Menu.MenuItems[0].MenuItems.Add(NewGame);
        
        
        //Options menu
        MenuItem Options            = new MenuItem("&Options");
        MenuItemInt   ComputerFirst = new MenuItemInt(TicTacToe.Computer,"Computer plays first", 
                                                      new EventHandler(OnOptionsFirstPlayerClick));
        MenuItemInt   HumanFirst    = new MenuItemInt(TicTacToe.Human, "Human plays first", 
                                                      new EventHandler(OnOptionsFirstPlayerClick));
        MenuItem      Spacer        = new MenuItem("-");
        MenuItemInt   ComputerX     = new MenuItemInt(Board.X, "Computer plays X", 
                                                      new EventHandler(OnOptionsComputerFigureClick));
        MenuItemInt   ComputerO     = new MenuItemInt(Board.O, "Computer plays O", 
                                                      new EventHandler(OnOptionsComputerFigureClick));
       
        ComputerFirst.RadioCheck = true;
        HumanFirst.RadioCheck    = true;
        ComputerX.RadioCheck     = true;
        ComputerO.RadioCheck     = true;
        
        this.Menu.MenuItems.Add(Options);
        this.Menu.MenuItems[1].MenuItems.Add(ComputerFirst);
        this.Menu.MenuItems[1].MenuItems.Add(HumanFirst);
        this.Menu.MenuItems[1].MenuItems.Add(Spacer);
        this.Menu.MenuItems[1].MenuItems.Add(ComputerX);
        this.Menu.MenuItems[1].MenuItems.Add(ComputerO);

        amiiMenuItemsToDeactivate = new MenuItemInt[] { ComputerX, ComputerO, ComputerFirst, HumanFirst };


        //
        // Set default options
        //
        FirstPlayer        = TicTacToe.Human;
        HumanFirst.Checked = true;
        ComputerFigure     = Board.X;
        ComputerX.Checked  = true;
        CurrentPlayer      = FirstPlayer;

        miiFirstPlayer    = HumanFirst;
        miiComputerFigure = ComputerX;
        
        
        //
        //Create the board
        //
        aSquares    = new SquareControl[iBoardSize, iBoardSize];
        GameBoard   = new Board(iBoardSize);
        int i, j;
        for(i = 0; i < iBoardSize; i++)
        {
            for (j = 0; j < iBoardSize; j++)
            {
                aSquares[i, j] = new SquareControl(i, j);
                aSquares[i, j].Click += new EventHandler(SquareControl_Click);
                aSquares[i, j].Parent = this;
            }
        }
        
        //
        //Sizing and positioning business
        //
        ClientSize = new Size(500, 500);
        SizeAndPositionControls();

        //avoid exceptions due to controls with zero size
        this.MinimumSize = new Size(200, 225);
    }
   
    //==================================================================================
    //   Gameplay code
    //==================================================================================

    private void StartGame()
    {
        this.Reset();

        //disable options MenuItems
        foreach (MenuItemInt mii in amiiMenuItemsToDeactivate)
            mii.Enabled = false;

        //Make first computer move if necessary.
        //Otherwise, just return and wait for user input.
        if (CurrentPlayer == Computer)
        {
            CalculateComputerMove();
        }
        return;
    }

    //Apply a move to the GameBoard and the appropriate SquareControl
    private void MakeMove(Move move)
    {
        //make move on the Board
        GameBoard.MakeMove(CurrentPlayer, move);

        //update SquareControls
        if (CurrentPlayer == TicTacToe.Computer)
            aSquares[move.iCol, move.iRow].iContents = ComputerFigure;
        else
            aSquares[move.iCol, move.iRow].iContents = -ComputerFigure;
        aSquares[move.iCol, move.iRow].Invalidate();

        //Check for endgame, switch players
        GameBoard.CheckBoard();
        CurrentPlayer = -CurrentPlayer;

        //If game is over, update the form text
        if (GameBoard.BoardState != GameState.InProgress)
        {
            UpdateStatus();
        }
    }

    //update form text and re-enable options MenuItems
    private void UpdateStatus()
    {
        foreach (MenuItemInt mii in amiiMenuItemsToDeactivate)
            mii.Enabled = true;
        
        if (this.GameBoard.BoardState == GameState.HumanWins)
            this.Text = "You win!";
        else if (this.GameBoard.BoardState == GameState.ComputerWins)
            this.Text = "Computer wins!";
        else if (this.GameBoard.BoardState == GameState.Draw)
            this.Text = "Draw";
        return;
    }

    //get ready for another round
    private void Reset()
    {

        CurrentPlayer = FirstPlayer;
        int i, j;
        for (i = 0; i < iBoardSize; i++)
        {
            for (j = 0; j < iBoardSize; j++)
            {
                this.aSquares[i, j].iContents = Board.Empty;
                this.aSquares[i, j].Invalidate();
                this.GameBoard.aiBoard[i, j] = Board.Empty;

            }
        }


        this.GameBoard.BoardState = GameState.InProgress;
        this.GameBoard.iEmptySquares = iBoardSize * iBoardSize;
        this.Text = "";
    }
    
   
   
    //==================================================================================
    //  Code related to making computer moves
    //==================================================================================
    
    //used for callback from the worker thread
    delegate void MakeComputerMoveDelegate(Move move);
  
    //Spawn a new thread and kickoff lookahead
    private void CalculateComputerMove()
    {
        CalculateComputerMoveThread = new Thread(new ThreadStart(MakeComputerMove));
        CalculateComputerMoveThread.IsBackground = true;
        CalculateComputerMoveThread.Priority = ThreadPriority.Lowest;
        CalculateComputerMoveThread.Name = "AI worker thread";
        CalculateComputerMoveThread.Start();
    }
    
    
    //Entry point for worker thread
    private void MakeComputerMove()
    {
       //TODO: initialize alpha and beta

        int alpha = -2;
        int beta = 2;
        Move move = GetBestMove(this.GameBoard, this.CurrentPlayer, alpha, beta);

        Object[] args = { move };
        MakeComputerMoveDelegate MakeMoveDelegate = new MakeComputerMoveDelegate(this.MakeMove);
        this.BeginInvoke(MakeMoveDelegate, args);
    }

    
    //Game AI code.  Standard minimax search with alpha-beta pruning. Calculated in worker thread.
    private Move GetBestMove(Board board, int CurrentPlayer, int alpha, int beta)
    {
        Move BestMove = null;
        int iPossibleMoves = board.iEmptySquares;

        //Start at a random square, so that if two or more moves
        //are of equal rank, one of them will be chosen at random.
        Random rand = new Random();
        int i = rand.Next(board.iBoardSize);
        int j = rand.Next(board.iBoardSize);

        while (iPossibleMoves > 0)
        {
            //Loop through board.aiBoard to find next available move
            do
            {
                if (i < iBoardSize - 1)
                {
                    i++;
                }
                else if (j < iBoardSize - 1)
                {
                    i = 0; j++;
                }
                else
                {
                    i = 0; j = 0;
                }
            } while (board.aiBoard[i, j] != Board.Empty) ;

            Move NewMove = new Move(i, j);
            iPossibleMoves--;

            //Make Move
            Board NewBoard = new Board(board);
            NewBoard.MakeMove(CurrentPlayer, NewMove);
            NewBoard.CheckBoard();

            if (NewBoard.BoardState == GameState.InProgress)
            {
                Move tempMove = GetBestMove(NewBoard, -CurrentPlayer, alpha, beta);
                NewMove.iRank = tempMove.iRank;
            }
            else
            {
                //Assign a rank
                if(NewBoard.BoardState == GameState.Draw)
                    NewMove.iRank = 0;
                else 
                {
                    if (NewBoard.BoardState == GameState.ComputerWins)
                        NewMove.iRank = -1;
                     else
                    {
                         if (NewBoard.BoardState == GameState.HumanWins)
                            NewMove.iRank = 1;
                    }
                }
            }
            
            //Is NewMove the best move encountered at this level so far?
            if  (BestMove == null ||
                (CurrentPlayer == TicTacToe.Computer && NewMove.iRank < BestMove.iRank) ||
                (CurrentPlayer == TicTacToe.Human && NewMove.iRank > BestMove.iRank))
            {
                BestMove = NewMove;
            }

            
            //Update alpha and beta, if necessary.
            if (CurrentPlayer == TicTacToe.Computer && BestMove.iRank < beta)
                beta = BestMove.iRank;
            if (CurrentPlayer == TicTacToe.Human && BestMove.iRank > alpha)
                alpha = BestMove.iRank;

            
            //Check for pruning condition.
            if (alpha > beta)
            {
                //prune this branch
                iPossibleMoves = 0;
            }
       }
       return BestMove;
    }


    //==================================================================================
    //  SquareControl Event handlers
    //==================================================================================

    private void SquareControl_Click(object Sender, EventArgs ea)
    {
        SquareControl Square = (SquareControl)Sender;
        if (Square.iContents == Board.Empty && this.GameBoard.BoardState == GameState.InProgress
            && CurrentPlayer == TicTacToe.Human)
        {

            //Make the move
            Move move = new Move(Square.iCol, Square.iRow);
            MakeMove(move);

            if (this.GameBoard.BoardState == GameState.InProgress)
                CalculateComputerMove();
        }
        return;
    }

    
    //==================================================================================
    //  Menu event handlers
    //==================================================================================
   
    private void OnFileNewGameClick(object sender, EventArgs ea)
    {
        StartGame();
    }

    private void OnOptionsComputerFigureClick(object sender, EventArgs ea)
    {
        miiComputerFigure.Checked = false;
        miiComputerFigure = (MenuItemInt)sender;
        miiComputerFigure.Checked = true;

        ComputerFigure = miiComputerFigure.iValue;
    }
    
    private void OnOptionsFirstPlayerClick(object sender, EventArgs ea)
    {
        miiFirstPlayer.Checked = false;
        miiFirstPlayer = (MenuItemInt)sender;
        miiFirstPlayer.Checked = true;

        FirstPlayer = miiFirstPlayer.iValue;
    }

   
    //==================================================================================
    //  Methods related to displaying of the form
    //==================================================================================
    
    protected override void OnResize(EventArgs ea)
    {
        //Ensure that the client area is always square
        int iSize = Math.Min(ClientSize.Height, ClientSize.Width);
        ClientSize = new Size(iSize, iSize);
        
        //resize and reposition child controls
        SizeAndPositionControls();
        this.Invalidate();
    }
    private void SizeAndPositionControls()
    {
        iSquareSize = (this.ClientSize.Width / iBoardSize) - (3 * (iBoardSize - 1) / iBoardSize);

        int i, j;
        for (i = 0; i < iBoardSize; i++)
        {
            for (j = 0; j < iBoardSize; j++)
            {
                aSquares[i, j].Size = new Size(iSquareSize, iSquareSize);
                aSquares[i, j].Location = new Point(iSquareSize * i + 3 * i,
                                                    iSquareSize * j + 3 * j);
            }
        }
    }
    protected override void OnPaint(PaintEventArgs pea)
    {
        base.OnPaint(pea);
        Graphics g = pea.Graphics;
        Pen pen = new Pen(new SolidBrush(Color.Black), 10f);

        int i;
        for (i = 1; i < iBoardSize - 2; i++)
        {
            g.DrawLine(pen, new Point(i * iSquareSize + (i-1) * 3, 0),
                            new Point(i * iSquareSize + (i-1) * 3, this.ClientSize.Height));
        }
    }
}

//Custom MenuItem class used for mutually excluse options
class MenuItemInt : MenuItem
{
    public int iValue;
    public MenuItemInt(int integer, string str, EventHandler eh)
        : base(str, eh)
    {
        iValue = integer;
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -