实例介绍
【实例截图】
【核心代码】
using System; using System.Drawing; using System.Collections; using System.ComponentModel; using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; // download by http://www.codefans.net namespace Reversi { /// <summary> /// Summary description for Reversi. /// </summary> public class ReversiForm : System.Windows.Forms.Form { // Main menu. private System.Windows.Forms.MainMenu mainMenu; private System.Windows.Forms.MenuItem gameMenuItem; private System.Windows.Forms.MenuItem newGameMenuItem; private System.Windows.Forms.MenuItem resignGameMenuItem; private System.Windows.Forms.MenuItem gameSeparator1MenuItem; private System.Windows.Forms.MenuItem optionsMenuItem; private System.Windows.Forms.MenuItem statisticsMenuItem; private System.Windows.Forms.MenuItem gameSeparator2MenuItem; private System.Windows.Forms.MenuItem exitMenuItem; private System.Windows.Forms.MenuItem moveMenuItem; private System.Windows.Forms.MenuItem undoMoveMenuItem; private System.Windows.Forms.MenuItem undoAllMovesMenuItem; private System.Windows.Forms.MenuItem redoMoveMenuItem; private System.Windows.Forms.MenuItem redoAllMovesMenuItem; private System.Windows.Forms.MenuItem moveSeparatorMenuItem; private System.Windows.Forms.MenuItem resumePlayMenuItem; private System.Windows.Forms.MenuItem helpMenuItem; private System.Windows.Forms.MenuItem helpTopicsMenuItem; private System.Windows.Forms.MenuItem helpSeparatorMenuItem; private System.Windows.Forms.MenuItem aboutMenuItem; // Tool bar. private System.Windows.Forms.ToolBar playToolBar; private System.Windows.Forms.ImageList playImageList; private System.Windows.Forms.ToolBarButton newGameToolBarButton; private System.Windows.Forms.ToolBarButton resignGameToolBarButton; private System.Windows.Forms.ToolBarButton separatorToolBarButton; private System.Windows.Forms.ToolBarButton undoAllMovesToolBarButton; private System.Windows.Forms.ToolBarButton undoMoveToolBarButton; private System.Windows.Forms.ToolBarButton resumePlayToolBarButton; private System.Windows.Forms.ToolBarButton redoMoveToolBarButton; private System.Windows.Forms.ToolBarButton redoAllMovesToolBarButton; // Board display. private System.Windows.Forms.Panel boardPanel; private System.Windows.Forms.Label cornerLabel; private System.Windows.Forms.Panel squaresPanel; // Information display. private System.Windows.Forms.Panel infoPanel; private System.Windows.Forms.Label whiteTextLabel; private System.Windows.Forms.Label whiteCountLabel; private System.Windows.Forms.Label blackTextLabel; private System.Windows.Forms.Label blackCountLabel; private System.Windows.Forms.Label currentColorTextLabel; private System.Windows.Forms.Panel currentColorPanel; private System.Windows.Forms.ListView moveListView; private System.Windows.Forms.ColumnHeader moveNullColumn; private System.Windows.Forms.ColumnHeader moveNumberColumn; private System.Windows.Forms.ColumnHeader movePlayerColumn; private System.Windows.Forms.ColumnHeader movePositionColumn; // Status display. private System.Windows.Forms.Panel statusPanel; private System.Windows.Forms.Label statusLabel; private System.Windows.Forms.ProgressBar statusProgressBar; /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.Container components = null; // This enumeration should match the button order on the tool bar. public enum ToolBarButton { NewGame, ResignGame, Separator, UndoAllMoves, UndoMove, ResumePlay, RedoMove, RedoAllMoves } // Defines the difficulty settings. public enum Difficulty { Beginner, Intermediate, Advanced, Expert } // Defines the game states. private enum GameState { GameOver, // The game is over (also used for the initial state). InMoveAnimation, // A move has been made and the animation is active. InPlayerMove, // Waiting for the user to make a move. InComputerMove, // Waiting for the computer to make a move. MoveCompleted // A move has been completed (including the animation, if active). } // The game board. private Board board; private Label[] colLabels, rowLabels; private SquareControl[,] squareControls; // Game options. private Options options = new Options(); // Game statistics. private Statistics statistics = new Statistics(); // Game parameters. private GameState gameState; private int currentColor; private int moveNumber; // This timer is used to animate moves during game play. private System.Windows.Forms.Timer animationTimer = new System.Windows.Forms.Timer(); private static readonly int animationTimerInterval = 50; // AI parameters. private int lookAheadDepth; private int forfeitWeight; private int frontierWeight; private int mobilityWeight; private int stabilityWeight; // Defines a thread for running the computer move look ahead. private Thread calculateComputerMoveThread; // Defines a structure for holding a look ahead move and rank. private struct ComputerMove { public int row; public int col; public int rank; public ComputerMove(int row, int col) { this.row = row; this.col = col; this.rank = 0; } } // Defines the maximum move rank value (used for ranking an end game). private static int maxRank = System.Int32.MaxValue - 64; // For converting column numbers to letters and vice versa. private static String alpha = "ABCDEFGH"; // For getting moves via the keyboard. private int keyedColNumber; private int keyedRowNumber; // Defines a structure for holding move history data. private struct MoveRecord { public Board board; public int currentColor; public ListViewItem moveListItem; public MoveRecord(Board board, int currentColor, ListViewItem moveListItem) { this.board = new Board(board); this.currentColor = currentColor; this.moveListItem = moveListItem; } } // Defines an array for storing the move history. private ArrayList moveHistory; // Used to track which player made the last move. private int lastMoveColor; // Used to suspend computer play while moves are undone/redone. private bool isComputerPlaySuspended; // Used to save statistics when undoing moves in a completed game. private Statistics oldStatistics; // For tracking the window location and size. private Rectangle windowSettings; // For loading and saving program settings. private ProgramSettings settings; private static readonly string programSettingsFileName = "Reversi.xml"; // The help file name. private static readonly string helpFileName = "Reversi.chm"; public ReversiForm() { // // Required for Windows Form Designer support // InitializeComponent(); // // TODO: Add any constructor code after InitializeComponent call // // Create the game board. this.board = new Board(); // Create the controls for each square, add them to the squares // panel and set up event handling. this.squareControls = new SquareControl[8, 8]; int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { // Create it. this.squareControls[i, j] = new SquareControl(i, j); // Position it. this.squareControls[i, j].Left = j * this.squareControls[i, j].Width; this.squareControls[i, j].Top = i * this.squareControls[i, j].Height; // Add it. this.squaresPanel.Controls.Add(this.squareControls[i, j]); // Set up event handling for it. this.squareControls[i, j].MouseMove = new MouseEventHandler(this.SquareControl_MouseMove); this.squareControls[i, j].MouseLeave = new EventHandler(this.SquareControl_MouseLeave); this.squareControls[i, j].Click = new EventHandler(this.SquareControl_Click); } // Create the column and row labels. this.colLabels = new Label[8]; for (i = 0; i < 8; i ) { // Create a column label. this.colLabels[i] = new Label(); // Set its display properties. this.colLabels[i].Text = ReversiForm.alpha.Substring(i, 1); this.colLabels[i].BackColor = this.cornerLabel.BackColor; this.colLabels[i].ForeColor = this.cornerLabel.ForeColor; this.colLabels[i].TextAlign = ContentAlignment.MiddleCenter; // Set its size and position. this.colLabels[i].Width = this.squareControls[0, 0].Width; this.colLabels[i].Height = this.cornerLabel.Height; this.colLabels[i].Left = this.cornerLabel.Width i * this.colLabels[0].Width; this.colLabels[i].Top = 0; // Add it. this.boardPanel.Controls.Add(this.colLabels[i]); } this.rowLabels = new Label[8]; for (i = 0; i < 8; i ) { // Create a row label. this.rowLabels[i] = new Label(); // Set its display properties. this.rowLabels[i].Text = (i 1).ToString(); this.rowLabels[i].BackColor = this.cornerLabel.BackColor; this.rowLabels[i].ForeColor = this.cornerLabel.ForeColor; this.rowLabels[i].TextAlign = ContentAlignment.MiddleCenter; // Set its size and position. this.rowLabels[i].Width = this.cornerLabel.Height; this.rowLabels[i].Height = this.squareControls[0, 0].Height; this.rowLabels[i].Left = 0; this.rowLabels[i].Top = this.cornerLabel.Height i * this.rowLabels[0].Width; // Add it. this.boardPanel.Controls.Add(this.rowLabels[i]); } // Initialize the game state. this.gameState = ReversiForm.GameState.GameOver; // Initialize the animation timer. this.animationTimer.Interval = ReversiForm.animationTimerInterval; this.animationTimer.Tick = new EventHandler(this.AnimateMove); // Initialize the window settings. this.windowSettings = new Rectangle( this.DesktopLocation.X, this.DesktopLocation.Y, this.ClientSize.Width, this.ClientSize.Height); // Load any saved program settings. this.settings = new ProgramSettings(ReversiForm.programSettingsFileName); this.LoadProgramSettings(); } /// <summary> /// Clean up any resources being used. /// </summary> protected override void Dispose( bool disposing ) { if( disposing ) { if (components != null) { components.Dispose(); } } base.Dispose( disposing ); } #region Windows Form Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.components = new System.ComponentModel.Container(); System.Resources.ResourceManager resources = new System.Resources.ResourceManager(typeof(ReversiForm)); this.infoPanel = new System.Windows.Forms.Panel(); this.currentColorPanel = new System.Windows.Forms.Panel(); this.whiteCountLabel = new System.Windows.Forms.Label(); this.whiteTextLabel = new System.Windows.Forms.Label(); this.currentColorTextLabel = new System.Windows.Forms.Label(); this.blackCountLabel = new System.Windows.Forms.Label(); this.blackTextLabel = new System.Windows.Forms.Label(); this.moveListView = new System.Windows.Forms.ListView(); this.moveNullColumn = new System.Windows.Forms.ColumnHeader(); this.moveNumberColumn = new System.Windows.Forms.ColumnHeader(); this.movePlayerColumn = new System.Windows.Forms.ColumnHeader(); this.movePositionColumn = new System.Windows.Forms.ColumnHeader(); this.squaresPanel = new System.Windows.Forms.Panel(); this.mainMenu = new System.Windows.Forms.MainMenu(); this.gameMenuItem = new System.Windows.Forms.MenuItem(); this.newGameMenuItem = new System.Windows.Forms.MenuItem(); this.resignGameMenuItem = new System.Windows.Forms.MenuItem(); this.gameSeparator1MenuItem = new System.Windows.Forms.MenuItem(); this.optionsMenuItem = new System.Windows.Forms.MenuItem(); this.statisticsMenuItem = new System.Windows.Forms.MenuItem(); this.gameSeparator2MenuItem = new System.Windows.Forms.MenuItem(); this.exitMenuItem = new System.Windows.Forms.MenuItem(); this.moveMenuItem = new System.Windows.Forms.MenuItem(); this.undoMoveMenuItem = new System.Windows.Forms.MenuItem(); this.redoMoveMenuItem = new System.Windows.Forms.MenuItem(); this.undoAllMovesMenuItem = new System.Windows.Forms.MenuItem(); this.redoAllMovesMenuItem = new System.Windows.Forms.MenuItem(); this.moveSeparatorMenuItem = new System.Windows.Forms.MenuItem(); this.resumePlayMenuItem = new System.Windows.Forms.MenuItem(); this.helpMenuItem = new System.Windows.Forms.MenuItem(); this.helpTopicsMenuItem = new System.Windows.Forms.MenuItem(); this.helpSeparatorMenuItem = new System.Windows.Forms.MenuItem(); this.aboutMenuItem = new System.Windows.Forms.MenuItem(); this.boardPanel = new System.Windows.Forms.Panel(); this.cornerLabel = new System.Windows.Forms.Label(); this.statusProgressBar = new System.Windows.Forms.ProgressBar(); this.statusLabel = new System.Windows.Forms.Label(); this.statusPanel = new System.Windows.Forms.Panel(); this.playToolBar = new System.Windows.Forms.ToolBar(); this.newGameToolBarButton = new System.Windows.Forms.ToolBarButton(); this.resignGameToolBarButton = new System.Windows.Forms.ToolBarButton(); this.separatorToolBarButton = new System.Windows.Forms.ToolBarButton(); this.undoAllMovesToolBarButton = new System.Windows.Forms.ToolBarButton(); this.undoMoveToolBarButton = new System.Windows.Forms.ToolBarButton(); this.resumePlayToolBarButton = new System.Windows.Forms.ToolBarButton(); this.redoMoveToolBarButton = new System.Windows.Forms.ToolBarButton(); this.redoAllMovesToolBarButton = new System.Windows.Forms.ToolBarButton(); this.playImageList = new System.Windows.Forms.ImageList(this.components); this.infoPanel.SuspendLayout(); this.boardPanel.SuspendLayout(); this.statusPanel.SuspendLayout(); this.SuspendLayout(); // // infoPanel // this.infoPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Right))); this.infoPanel.Controls.Add(this.currentColorPanel); this.infoPanel.Controls.Add(this.whiteCountLabel); this.infoPanel.Controls.Add(this.whiteTextLabel); this.infoPanel.Controls.Add(this.currentColorTextLabel); this.infoPanel.Controls.Add(this.blackCountLabel); this.infoPanel.Controls.Add(this.blackTextLabel); this.infoPanel.Controls.Add(this.moveListView); this.infoPanel.Location = new System.Drawing.Point(296, 32); this.infoPanel.Name = "infoPanel"; this.infoPanel.Size = new System.Drawing.Size(168, 276); this.infoPanel.TabIndex = 3; // // currentColorPanel // this.currentColorPanel.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.currentColorPanel.Location = new System.Drawing.Point(88, 56); this.currentColorPanel.Name = "currentColorPanel"; this.currentColorPanel.Size = new System.Drawing.Size(16, 16); this.currentColorPanel.TabIndex = 5; this.currentColorPanel.Visible = false; // // whiteCountLabel // this.whiteCountLabel.Location = new System.Drawing.Point(80, 32); this.whiteCountLabel.Name = "whiteCountLabel"; this.whiteCountLabel.Size = new System.Drawing.Size(24, 13); this.whiteCountLabel.TabIndex = 3; this.whiteCountLabel.Text = "0"; this.whiteCountLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // whiteTextLabel // this.whiteTextLabel.AutoSize = true; this.whiteTextLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0))); this.whiteTextLabel.Location = new System.Drawing.Point(40, 32); this.whiteTextLabel.Name = "whiteTextLabel"; this.whiteTextLabel.Size = new System.Drawing.Size(39, 16); this.whiteTextLabel.TabIndex = 2; this.whiteTextLabel.Text = "White: "; // // currentColorTextLabel // this.currentColorTextLabel.AutoSize = true; this.currentColorTextLabel.Location = new System.Drawing.Point(32, 56); this.currentColorTextLabel.Name = "currentColorTextLabel"; this.currentColorTextLabel.Size = new System.Drawing.Size(48, 16); this.currentColorTextLabel.TabIndex = 4; this.currentColorTextLabel.Text = "Current: "; this.currentColorTextLabel.Visible = false; // // blackCountLabel // this.blackCountLabel.Location = new System.Drawing.Point(80, 8); this.blackCountLabel.Name = "blackCountLabel"; this.blackCountLabel.Size = new System.Drawing.Size(24, 13); this.blackCountLabel.TabIndex = 1; this.blackCountLabel.Text = "0"; this.blackCountLabel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // blackTextLabel // this.blackTextLabel.AutoSize = true; this.blackTextLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((System.Byte)(0))); this.blackTextLabel.Location = new System.Drawing.Point(40, 8); this.blackTextLabel.Name = "blackTextLabel"; this.blackTextLabel.Size = new System.Drawing.Size(38, 16); this.blackTextLabel.TabIndex = 0; this.blackTextLabel.Text = "Black: "; // // moveListView // this.moveListView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.moveListView.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.moveListView.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { this.moveNullColumn, this.moveNumberColumn, this.movePlayerColumn, this.movePositionColumn}); this.moveListView.FullRowSelect = true; this.moveListView.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; this.moveListView.Location = new System.Drawing.Point(2, 88); this.moveListView.Name = "moveListView"; this.moveListView.Size = new System.Drawing.Size(164, 188); this.moveListView.TabIndex = 6; this.moveListView.TabStop = false; this.moveListView.View = System.Windows.Forms.View.Details; // // moveNullColumn // this.moveNullColumn.Text = ""; this.moveNullColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.moveNullColumn.Width = 0; // // moveNumberColumn // this.moveNumberColumn.Text = "#"; this.moveNumberColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.moveNumberColumn.Width = 32; // // movePlayerColumn // this.movePlayerColumn.Text = "Player"; this.movePlayerColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right; this.movePlayerColumn.Width = 52; // // movePositionColumn // this.movePositionColumn.Text = "Position"; this.movePositionColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center; this.movePositionColumn.Width = 62; // // squaresPanel // this.squaresPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.squaresPanel.Location = new System.Drawing.Point(16, 16); this.squaresPanel.Name = "squaresPanel"; this.squaresPanel.Size = new System.Drawing.Size(256, 256); this.squaresPanel.TabIndex = 1; // // mainMenu // this.mainMenu.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.gameMenuItem, this.moveMenuItem, this.helpMenuItem}); // // gameMenuItem // this.gameMenuItem.Index = 0; this.gameMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.newGameMenuItem, this.resignGameMenuItem, this.gameSeparator1MenuItem, this.optionsMenuItem, this.statisticsMenuItem, this.gameSeparator2MenuItem, this.exitMenuItem}); this.gameMenuItem.ShowShortcut = false; this.gameMenuItem.Text = "&Game"; // // newGameMenuItem // this.newGameMenuItem.Index = 0; this.newGameMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlN; this.newGameMenuItem.Text = "&New Game"; this.newGameMenuItem.Click = new System.EventHandler(this.newGameMenuItem_Click); // // resignGameMenuItem // this.resignGameMenuItem.Enabled = false; this.resignGameMenuItem.Index = 1; this.resignGameMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlR; this.resignGameMenuItem.Text = "&Resign Game"; this.resignGameMenuItem.Click = new System.EventHandler(this.resignGameMenuItem_Click); // // gameSeparator1MenuItem // this.gameSeparator1MenuItem.Index = 2; this.gameSeparator1MenuItem.Text = "-"; // // optionsMenuItem // this.optionsMenuItem.Index = 3; this.optionsMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlO; this.optionsMenuItem.Text = "&Options..."; this.optionsMenuItem.Click = new System.EventHandler(this.optionsMenuItem_Click); // // statisticsMenuItem // this.statisticsMenuItem.Index = 4; this.statisticsMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlS; this.statisticsMenuItem.Text = "&Statistics..."; this.statisticsMenuItem.Click = new System.EventHandler(this.statisticsMenuItem_Click); // // gameSeparator2MenuItem // this.gameSeparator2MenuItem.Index = 5; this.gameSeparator2MenuItem.Text = "-"; // // exitMenuItem // this.exitMenuItem.Index = 6; this.exitMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlX; this.exitMenuItem.Text = "E&xit"; this.exitMenuItem.Click = new System.EventHandler(this.exitMenuItem_Click); // // moveMenuItem // this.moveMenuItem.Index = 1; this.moveMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.undoMoveMenuItem, this.redoMoveMenuItem, this.undoAllMovesMenuItem, this.redoAllMovesMenuItem, this.moveSeparatorMenuItem, this.resumePlayMenuItem}); this.moveMenuItem.ShowShortcut = false; this.moveMenuItem.Text = "&Move"; // // undoMoveMenuItem // this.undoMoveMenuItem.Enabled = false; this.undoMoveMenuItem.Index = 0; this.undoMoveMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlZ; this.undoMoveMenuItem.Text = "&Undo Move"; this.undoMoveMenuItem.Click = new System.EventHandler(this.undoMoveMenuItem_Click); // // redoMoveMenuItem // this.redoMoveMenuItem.Enabled = false; this.redoMoveMenuItem.Index = 1; this.redoMoveMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlY; this.redoMoveMenuItem.Text = "&Redo Move"; this.redoMoveMenuItem.Click = new System.EventHandler(this.redoMoveMenuItem_Click); // // undoAllMovesMenuItem // this.undoAllMovesMenuItem.Enabled = false; this.undoAllMovesMenuItem.Index = 2; this.undoAllMovesMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftZ; this.undoAllMovesMenuItem.Text = "U&ndo All Moves"; this.undoAllMovesMenuItem.Click = new System.EventHandler(this.undoAllMovesmenuItem_Click); // // redoAllMovesMenuItem // this.redoAllMovesMenuItem.Enabled = false; this.redoAllMovesMenuItem.Index = 3; this.redoAllMovesMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlShiftY; this.redoAllMovesMenuItem.Text = "Re&do All Moves"; this.redoAllMovesMenuItem.Click = new System.EventHandler(this.redoAllMovesMenuItem_Click); // // moveSeparatorMenuItem // this.moveSeparatorMenuItem.Index = 4; this.moveSeparatorMenuItem.Text = "-"; // // resumePlayMenuItem // this.resumePlayMenuItem.Enabled = false; this.resumePlayMenuItem.Index = 5; this.resumePlayMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlP; this.resumePlayMenuItem.Text = "Resume &Play"; this.resumePlayMenuItem.Click = new System.EventHandler(this.resumePlayMenuItem_Click); // // helpMenuItem // this.helpMenuItem.Index = 2; this.helpMenuItem.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] { this.helpTopicsMenuItem, this.helpSeparatorMenuItem, this.aboutMenuItem}); this.helpMenuItem.ShowShortcut = false; this.helpMenuItem.Text = "&Help"; // // helpTopicsMenuItem // this.helpTopicsMenuItem.Index = 0; this.helpTopicsMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlH; this.helpTopicsMenuItem.Text = "&Help Topics"; this.helpTopicsMenuItem.Click = new System.EventHandler(this.helpTopicsMenuItem_Click); // // helpSeparatorMenuItem // this.helpSeparatorMenuItem.Index = 1; this.helpSeparatorMenuItem.Text = "-"; // // aboutMenuItem // this.aboutMenuItem.Index = 2; this.aboutMenuItem.Shortcut = System.Windows.Forms.Shortcut.CtrlA; this.aboutMenuItem.Text = "&About"; this.aboutMenuItem.Click = new System.EventHandler(this.aboutMenuItem_Click); // // boardPanel // this.boardPanel.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.boardPanel.BackColor = System.Drawing.SystemColors.Control; this.boardPanel.Controls.Add(this.cornerLabel); this.boardPanel.Controls.Add(this.squaresPanel); this.boardPanel.Location = new System.Drawing.Point(8, 32); this.boardPanel.Name = "boardPanel"; this.boardPanel.Size = new System.Drawing.Size(272, 272); this.boardPanel.TabIndex = 2; // // cornerLabel // this.cornerLabel.BackColor = System.Drawing.SystemColors.ControlDark; this.cornerLabel.ForeColor = System.Drawing.SystemColors.ControlLightLight; this.cornerLabel.Location = new System.Drawing.Point(0, 0); this.cornerLabel.Name = "cornerLabel"; this.cornerLabel.Size = new System.Drawing.Size(16, 16); this.cornerLabel.TabIndex = 0; // // statusProgressBar // this.statusProgressBar.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.statusProgressBar.BackColor = System.Drawing.SystemColors.ControlLight; this.statusProgressBar.Location = new System.Drawing.Point(350, 2); this.statusProgressBar.Name = "statusProgressBar"; this.statusProgressBar.Size = new System.Drawing.Size(104, 16); this.statusProgressBar.Step = 1; this.statusProgressBar.TabIndex = 1; this.statusProgressBar.Visible = false; // // statusLabel // this.statusLabel.AutoSize = true; this.statusLabel.Location = new System.Drawing.Point(16, 2); this.statusLabel.Name = "statusLabel"; this.statusLabel.Size = new System.Drawing.Size(0, 16); this.statusLabel.TabIndex = 0; this.statusLabel.TextAlign = System.Drawing.ContentAlignment.MiddleLeft; // // statusPanel // this.statusPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.statusPanel.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.statusPanel.Controls.Add(this.statusProgressBar); this.statusPanel.Controls.Add(this.statusLabel); this.statusPanel.Location = new System.Drawing.Point(8, 312); this.statusPanel.Name = "statusPanel"; this.statusPanel.Size = new System.Drawing.Size(456, 24); this.statusPanel.TabIndex = 4; // // playToolBar // this.playToolBar.Buttons.AddRange(new System.Windows.Forms.ToolBarButton[] { this.newGameToolBarButton, this.resignGameToolBarButton, this.separatorToolBarButton, this.undoAllMovesToolBarButton, this.undoMoveToolBarButton, this.resumePlayToolBarButton, this.redoMoveToolBarButton, this.redoAllMovesToolBarButton}); this.playToolBar.Divider = false; this.playToolBar.DropDownArrows = true; this.playToolBar.ImageList = this.playImageList; this.playToolBar.Location = new System.Drawing.Point(0, 0); this.playToolBar.Name = "playToolBar"; this.playToolBar.ShowToolTips = true; this.playToolBar.Size = new System.Drawing.Size(472, 26); this.playToolBar.TabIndex = 1; this.playToolBar.ButtonClick = new System.Windows.Forms.ToolBarButtonClickEventHandler(this.playToolBar_ButtonClick); // // newGameToolBarButton // this.newGameToolBarButton.ImageIndex = 0; this.newGameToolBarButton.ToolTipText = "New Game"; // // resignGameToolBarButton // this.resignGameToolBarButton.Enabled = false; this.resignGameToolBarButton.ImageIndex = 1; this.resignGameToolBarButton.ToolTipText = "Resign Game"; // // separatorToolBarButton // this.separatorToolBarButton.Style = System.Windows.Forms.ToolBarButtonStyle.Separator; // // undoAllMovesToolBarButton // this.undoAllMovesToolBarButton.Enabled = false; this.undoAllMovesToolBarButton.ImageIndex = 2; this.undoAllMovesToolBarButton.ToolTipText = "Undo All Moves"; // // undoMoveToolBarButton // this.undoMoveToolBarButton.Enabled = false; this.undoMoveToolBarButton.ImageIndex = 3; this.undoMoveToolBarButton.ToolTipText = "Undo Move"; // // resumePlayToolBarButton // this.resumePlayToolBarButton.Enabled = false; this.resumePlayToolBarButton.ImageIndex = 4; this.resumePlayToolBarButton.ToolTipText = "Resume Play"; // // redoMoveToolBarButton // this.redoMoveToolBarButton.Enabled = false; this.redoMoveToolBarButton.ImageIndex = 5; this.redoMoveToolBarButton.ToolTipText = "Redo Move"; // // redoAllMovesToolBarButton // this.redoAllMovesToolBarButton.Enabled = false; this.redoAllMovesToolBarButton.ImageIndex = 6; this.redoAllMovesToolBarButton.ToolTipText = "Redo All Moves"; // // playImageList // this.playImageList.ImageSize = new System.Drawing.Size(16, 16); this.playImageList.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("playImageList.ImageStream"))); this.playImageList.TransparentColor = System.Drawing.Color.Transparent; // // ReversiForm // this.AutoScaleBaseSize = new System.Drawing.Size(5, 13); this.ClientSize = new System.Drawing.Size(472, 345); this.Controls.Add(this.playToolBar); this.Controls.Add(this.boardPanel); this.Controls.Add(this.infoPanel); this.Controls.Add(this.statusPanel); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); this.KeyPreview = true; this.Menu = this.mainMenu; this.Name = "ReversiForm"; this.Text = "Reversi"; this.Resize = new System.EventHandler(this.ReversiForm_Resize); this.Closing = new System.ComponentModel.CancelEventHandler(this.ReversiForm_Closing); this.KeyPress = new System.Windows.Forms.KeyPressEventHandler(this.ReversiForm_KeyPress); this.Move = new System.EventHandler(this.ReversiForm_Move); this.Closed = new System.EventHandler(this.ReversiForm_Closed); this.infoPanel.ResumeLayout(false); this.boardPanel.ResumeLayout(false); this.statusPanel.ResumeLayout(false); this.ResumeLayout(false); } #endregion /// <summary> /// The main entry point for the application. /// </summary> [STAThread] static void Main() { Application.Run(new ReversiForm()); } // =================================================================== // This code handles game play. // =================================================================== // // Starts a new game. // private void StartGame() { this.StartGame(false); } // // Starts a new game or, optionally, restarts an ended game. // private void StartGame(bool isRestart) { // Enable/disable the menu items and tool bar buttons as // appropriate. this.newGameMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.NewGame].Enabled = false; this.resignGameMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.ResignGame].Enabled = true; if (!isRestart) { this.undoMoveMenuItem.Enabled = this.undoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoAllMoves].Enabled = false; this.redoMoveMenuItem.Enabled = this.redoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoAllMoves].Enabled = false; this.resumePlayMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.ResumePlay].Enabled = false; } // Initialize the information display. this.currentColorTextLabel.Visible = true; this.currentColorPanel.Visible = true; // Initialize a new game. if (!isRestart) { // Initialize the move list. this.moveNumber = 1; this.moveListView.Items.Clear(); this.moveListView.Refresh(); // Initialize the move history. this.moveHistory = new ArrayList(60); // Initialize the last move color. this.lastMoveColor = Board.Empty; // Clear the suspend computer play flag. this.isComputerPlaySuspended = false; // Initialize the board. this.board.SetForNewGame(); this.UpdateBoardDisplay(); // Initialize the status display. this.statusLabel.Text = ""; this.statusPanel.Refresh(); // Set the first player. this.currentColor = this.options.FirstMove; } // Start the first turn. this.StartTurn(); } // // Ends the current game. // private void EndGame() { this.EndGame(false); } // // Ends the current game, optionally by player resignation. // private void EndGame(bool isResignation) { // Set the game state. this.gameState = ReversiForm.GameState.GameOver; // Stop the game timer. this.animationTimer.Stop(); // Enable/disable the menu items and tool bar buttons as // appropriate. this.newGameMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.NewGame].Enabled = true; this.resignGameMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.ResignGame].Enabled = false; this.undoMoveMenuItem.Enabled = this.undoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoAllMoves].Enabled = false; this.redoMoveMenuItem.Enabled = this.redoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoAllMoves].Enabled = false; this.resumePlayMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.ResumePlay].Enabled = false; // Clear the current player indicator display. this.currentColorTextLabel.Visible = false; this.currentColorPanel.BackColor = Color.Empty; this.currentColorPanel.Visible = false; // Hide the status progress bar. this.statusProgressBar.Visible = false; this.statusPanel.Refresh(); // For a computer vs. user game, determine who played what color. int computerColor = Board.Empty; int userColor = Board.Empty; if (this.IsComputerPlayer(Board.Black) && !this.IsComputerPlayer(Board.White)) { computerColor = Board.Black; userColor = Board.White; } if (this.IsComputerPlayer(Board.White) && !this.IsComputerPlayer(Board.Black)) { computerColor = Board.White; userColor = Board.Black; } // Save the current statistics, in case the game is restarted. this.oldStatistics = new Statistics(this.statistics); // Handle a resignation. if (isResignation) { // For computer vs. computer game, just update the status // message. if (this.IsComputerPlayer(Board.Black) && this.IsComputerPlayer(Board.White)) this.statusLabel.Text = "Game aborted."; else { // Determine which player is resigning. In a computer vs. // user game, the computer will never resign so it must be // the user. In a user vs. user game we'll assume it is // the current player. int resigningColor = this.currentColor; if (this.IsComputerPlayer(Board.Black) || this.IsComputerPlayer(Board.White)) resigningColor = userColor; // Update the status message and record the game as a 64-0 // loss for the resigning player. if (resigningColor == Board.Black) { this.statusLabel.Text = "Black resigns."; this.statistics.Update(0, 64, computerColor, userColor); } else { this.statusLabel.Text = "White resigns."; this.statistics.Update(64, 0, computerColor, userColor); } } } // Handle an end game. else { // Update the status message. if (this.board.BlackCount > this.board.WhiteCount) this.statusLabel.Text = "Black wins."; else if (this.board.WhiteCount > this.board.BlackCount) this.statusLabel.Text = "White wins."; else this.statusLabel.Text = "Draw."; // Record the result. this.statistics.Update(this.board.BlackCount, this.board.WhiteCount, computerColor, userColor); } // Update the status display. this.statusPanel.Refresh(); // Re-enable the undo move-related menu items and tool bar // buttons. this.undoMoveMenuItem.Enabled = this.undoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoMove].Enabled = this.undoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoAllMoves].Enabled = true; } // // Sets up for the current player to make a move or ends the game if // neither player can make a valid move. // private void StartTurn() { // If the current player cannot make a valid move, forfeit the turn. if (!this.board.HasAnyValidMove(this.currentColor)) { // Switch back to the other player. this.currentColor *= -1; // If the original player cannot make a valid move either, the game is over. if (!this.board.HasAnyValidMove(this.currentColor)) { this.EndGame(); return; } } // Set the player text for the status display. string playerText = String.Format("{0}'s", (this.currentColor == Board.Black ? "Black" : "White")); if ((this.options.ComputerPlaysBlack && !this.options.ComputerPlaysWhite) || (this.options.ComputerPlaysWhite && !this.options.ComputerPlaysBlack)) playerText = (this.IsComputerPlayer(this.currentColor) ? "My" : "Your"); // Update the turn display. if (this.currentColor == Board.Black) this.currentColorPanel.BackColor = Color.Black; else this.currentColorPanel.BackColor = Color.White; this.currentColorPanel.Refresh(); // If the current color is under computer control, set up for a // computer move. if (this.IsComputerPlayer(this.currentColor)) { // Set the game state. this.gameState = ReversiForm.GameState.InComputerMove; // Check if computer play is currently suspended. if (this.isComputerPlaySuspended) { // Enable the "Resume Play" menu item and tool bar button // so that the user can resume the game. this.resumePlayMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.ResumePlay].Enabled = true; // Set the status display. string shortCutText = this.resumePlayMenuItem.Shortcut.ToString(); System.Text.RegularExpressions.Regex re = new System.Text.RegularExpressions.Regex("(Alt|Ctrl|Shift)", System.Text.RegularExpressions.RegexOptions.IgnoreCase); shortCutText = re.Replace(shortCutText, "$1 "); this.statusLabel.Text = String.Format("{0} move... (Suspended, press {1} to resume play.)", playerText, shortCutText); this.statusProgressBar.Visible = false; } else { // Set the status display. this.statusLabel.Text = String.Format("{0} move, thinking... ", playerText); this.statusProgressBar.Minimum = 0; this.statusProgressBar.Maximum = this.board.GetValidMoveCount(this.currentColor); this.statusProgressBar.Value = 0; // Position the progress bar just to the right of the text and make it visible. this.statusProgressBar.Left = this.statusLabel.Left this.statusLabel.Width; this.statusProgressBar.Visible = true; // Start a separate thread to perform the computer's move. this.calculateComputerMoveThread = new Thread(new ThreadStart(this.CalculateComputerMove)); this.calculateComputerMoveThread.IsBackground = true; this.calculateComputerMoveThread.Priority = System.Threading.ThreadPriority.Lowest; this.calculateComputerMoveThread.Name = "Calculate Computer Move"; this.calculateComputerMoveThread.Start(); } } // Otherwise, set up for a user move. else { // Set the game state. this.gameState = ReversiForm.GameState.InPlayerMove; // Reset the keyed column and row numbers. this.keyedColNumber = -1; this.keyedRowNumber = -1; // Show valid moves, if that option is active. if (this.options.ShowValidMoves) { this.HighlightValidMoves(); this.squaresPanel.Refresh(); } // Update the status display. this.statusLabel.Text = String.Format("{0} move...", playerText); this.statusProgressBar.Visible = false; // Set focus on the form so it will receive key presses. this.Focus(); } // Update the status display. this.statusPanel.Refresh(); } // // Determines if a given color is being played by the computer. // private bool IsComputerPlayer(int color) { return ((this.options.ComputerPlaysBlack && color == Board.Black) || (this.options.ComputerPlaysWhite && color == Board.White)); } // // Makes a move for the current player. // private void MakeMove(int row, int col) { // Clean up the move history to ensure that it contains only the // moves made prior to this one. while (this.moveHistory.Count > this.moveNumber - 1) this.moveHistory.RemoveAt(this.moveHistory.Count - 1); // Add the move to the move list. string color = "Black"; if (this.currentColor == Board.White) color = "White"; string[] subItems = { String.Empty, this.moveNumber.ToString(), color, (alpha[col] (row 1).ToString()) }; ListViewItem listItem = new ListViewItem(subItems); this.moveListView.Items.Add(listItem); // If necessary, scroll the list to bring the last move into view. this.moveListView.EnsureVisible(this.moveListView.Items.Count - 1); // Add this move to the move history. this.moveHistory.Add(new MoveRecord(this.board, this.currentColor, listItem)); // Enable/disable the move-related menu items and tool bar buttons as // appropriate. this.undoMoveMenuItem.Enabled = this.undoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoAllMoves].Enabled = true; this.redoMoveMenuItem.Enabled = this.redoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoAllMoves].Enabled = false; // Bump the move number. this.moveNumber ; // Update the status display. this.statusLabel.Text = ""; this.statusProgressBar.Visible = false; this.statusPanel.Refresh(); // Clear any board square highlighting. this.UnHighlightSquares(); // Make a copy of the board (for doing move animation). Board oldBoard = new Board(this.board); // Make the move on the board. this.board.MakeMove(this.currentColor, row, col); // If the animate move option is active, set up animation for the // affected discs. if (this.options.AnimateMoves) { int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { // Mark the newly added disc. if (i == row && j == col) this.squareControls[i, j].IsNew = true; else { // Initialize animation for the discs that were // flipped. if (this.board.GetSquareContents(i, j) != oldBoard.GetSquareContents(i, j)) this.squareControls[i, j].AnimationCounter = SquareControl.AnimationStart; } } } // Update the display to reflect the board changes. this.UpdateBoardDisplay(); // Save the player color. this.lastMoveColor = this.currentColor; // If the animate moves option is active, start the animation. if (this.options.AnimateMoves) { this.gameState = ReversiForm.GameState.InMoveAnimation; this.animationTimer.Start(); } // Otherwise, end the move. else this.EndMove(); } // // Called when a move has been completed (including any animation) to // start the next turn. // private void EndMove() { // Set the game state. this.gameState = ReversiForm.GameState.MoveCompleted; // Switch players and start the next turn. this.currentColor *= -1; this.StartTurn(); } // // Updates the animation of a move. // private void AnimateMove(Object sender, EventArgs e) { // Lock the board to prevent race conditions. lock (this.board) { // If a move is being animated, advance the animation counters on // the square controls. if (this.gameState == ReversiForm.GameState.InMoveAnimation) { bool isComplete = true; int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) if (this.squareControls[i, j].AnimationCounter > SquareControl.AnimationStop) { this.squareControls[i, j].AnimationCounter--; isComplete = false; } // Refresh the display. this.squaresPanel.Refresh(); // If the animation is complete, end the move. if (isComplete) { this.StopMoveAnimation(); this.UpdateBoardDisplay(); this.EndMove(); } } } } // // Stops animation of a move and resets the squares. // private void StopMoveAnimation() { // Stop the animation timer. this.animationTimer.Stop(); // Reset the animation counters and new disc flag on all squares. SquareControl squareControl; int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { squareControl = (SquareControl) this.squaresPanel.Controls[i * 8 j]; squareControl.AnimationCounter = SquareControl.AnimationStop; squareControl.IsNew = false; } } // // Makes a player-controlled move for the current color. // private void MakePlayerMove(int row, int col) { // Allow the computer to resume play. this.isComputerPlaySuspended = false; // Make the move. this.MakeMove(row, col); } // =================================================================== // Code to handle computer moves. // =================================================================== // // Cancels the computer move thread, if it is active. // private void KillComputerMoveThread() { if (this.calculateComputerMoveThread == null || this.calculateComputerMoveThread.ThreadState == ThreadState.Stopped) return; try { this.calculateComputerMoveThread.Abort(); this.calculateComputerMoveThread.Join(); } catch (Exception ex) {} finally { this.calculateComputerMoveThread = null; } } // // Define delegates for callbacks from the worker thread. // public delegate void UpdateStatusProgressDelegate(); public delegate void MakeComputerMoveDelegate(int row, int col); // // Updates the status progress bar. // Note: Called from the worker thread. // private void UpdateStatusProgress() { // Increase the progress bar value by one. if (this.statusProgressBar.Value < this.statusProgressBar.Maximum) { this.statusProgressBar.Value ; this.statusProgressBar.Refresh(); } } // // Makes a computer-controlled move for the current color. // Note: Called from the worker thread. // private void MakeComputerMove(int row, int col) { // Lock the board to prevent a race condition while performing the // move. lock (this.board) { // Make the move. this.MakeMove(row, col); } } // // Calculates a computer move. // Note: Executed in the worker thread. // private void CalculateComputerMove() { // Load the AI parameters. this.SetAIParameters(); // Find the best available move. ComputerMove move = this.GetBestMove(this.board); // Perform a callback to make the move. Object[] args = { move.row, move.col }; MakeComputerMoveDelegate moveDelegate = new MakeComputerMoveDelegate(this.MakeComputerMove); this.BeginInvoke(moveDelegate, args); } // =================================================================== // Game AI code. // Note: These are executed in the worker thread. // =================================================================== // // This function starts the look ahead process to find the best move // for the current player color. // private ComputerMove GetBestMove(Board board) { // Initialize the alpha-beta cutoff values. int alpha = ReversiForm.maxRank 64; int beta = -alpha; // Kick off the look ahead. return this.GetBestMove(board, this.currentColor, 1, alpha, beta); } // // This function uses look ahead to evaluate all valid moves for a // given player color and returns the best move it can find. // private ComputerMove GetBestMove(Board board, int color, int depth, int alpha, int beta) { // Initialize the best move. ComputerMove bestMove = new ComputerMove(-1, -1); bestMove.rank = -color * ReversiForm.maxRank; // Find out how many valid moves we have so we can initialize the // mobility score. int validMoves = board.GetValidMoveCount(color); // Start at a random position on the board. This way, if two or // more moves are equally good, we'll take one of them at random. Random random = new Random(); int rowStart = random.Next(8); int colStart = random.Next(8); // Check all valid moves. int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { // Get the row and column. int row = (rowStart i) % 8; int col = (colStart j) % 8; if (board.IsValidMove(color, row, col)) { // Update the progress bar for each move when on the // first look ahead depth level. if (depth == 1) this.BeginInvoke(new UpdateStatusProgressDelegate(this.UpdateStatusProgress)); // Make the move. ComputerMove testMove = new ComputerMove(row, col); Board testBoard = new Board(board); testBoard.MakeMove(color, testMove.row, testMove.col); int score = testBoard.WhiteCount - testBoard.BlackCount; // Check the board. int nextColor = -color; int forfeit = 0; bool isEndGame = false; int opponentValidMoves = testBoard.GetValidMoveCount(nextColor); if (opponentValidMoves == 0) { // The opponent cannot move, count the forfeit. forfeit = color; // Switch back to the original color. nextColor = -nextColor; // If that player cannot make a move either, the // game is over. if (!testBoard.HasAnyValidMove(nextColor)) isEndGame = true; } // If we reached the end of the look ahead (end game or // max depth), evaluate the board and set the move // rank. if (isEndGame || depth == this.lookAheadDepth) { // For an end game, max the ranking and add on the // final score. if (isEndGame) { // Negative value for black win. if (score < 0) testMove.rank = -ReversiForm.maxRank score; // Positive value for white win. else if (score > 0) testMove.rank = ReversiForm.maxRank score; // Zero for a draw. else testMove.rank = 0; } // It's not an end game so calculate the move rank. else testMove.rank = this.forfeitWeight * forfeit this.frontierWeight * (testBoard.BlackFrontierCount - testBoard.WhiteFrontierCount) this.mobilityWeight * color * (validMoves - opponentValidMoves) this.stabilityWeight * (testBoard.WhiteSafeCount - testBoard.BlackSafeCount) score; } // Otherwise, perform a look ahead. else { ComputerMove nextMove = this.GetBestMove(testBoard, nextColor, depth 1, alpha, beta); // Pull up the rank. testMove.rank = nextMove.rank; // Forfeits are cumulative, so if the move did not // result in an end game, add any current forfeit // value to the rank. if (forfeit != 0 && Math.Abs(testMove.rank) < ReversiForm.maxRank) testMove.rank = forfeitWeight * forfeit; // Adjust the alpha and beta values, if necessary. if (color == Board.White && testMove.rank > beta) beta = testMove.rank; if (color == Board.Black && testMove.rank < alpha) alpha = testMove.rank; } // Perform a cutoff if the rank is outside tha alpha-beta range. if (color == Board.White && testMove.rank > alpha) { testMove.rank = alpha; return testMove; } if (color == Board.Black && testMove.rank < beta) { testMove.rank = beta; return testMove; } // If this is the first move tested, assume it is the // best for now. if (bestMove.row < 0) bestMove = testMove; // Otherwise, compare the test move to the current // best move and take the one that is better for this // color. else if (color * testMove.rank > color * bestMove.rank) bestMove = testMove; } } // Return the best move found. return bestMove; } // // Sets the AI parameters based on the current difficulty setting. // private void SetAIParameters() { // Set the AI parameter weights. switch (this.options.Difficulty) { case ReversiForm.Difficulty.Beginner: this.forfeitWeight = 2; this.frontierWeight = 1; this.mobilityWeight = 0; this.stabilityWeight = 3; break; case ReversiForm.Difficulty.Intermediate: this.forfeitWeight = 3; this.frontierWeight = 1; this.mobilityWeight = 0; this.stabilityWeight = 5; break; case ReversiForm.Difficulty.Advanced: this.forfeitWeight = 7; this.frontierWeight = 2; this.mobilityWeight = 1; this.stabilityWeight = 10; break; case ReversiForm.Difficulty.Expert: this.forfeitWeight = 35; this.frontierWeight = 10; this.mobilityWeight = 5; this.stabilityWeight = 50; break; default: this.forfeitWeight = 0; this.frontierWeight = 0; this.mobilityWeight = 0; this.stabilityWeight = 0; break; } // Set the look-ahead depth. this.lookAheadDepth = (int) this.options.Difficulty 3; // Near the end of the game, when there are relatively few moves // left, set the look-ahead depth to do an exhaustive search. if (this.moveNumber >= 55 - (int) this.options.Difficulty) this.lookAheadDepth = this.board.EmptyCount; } // =================================================================== // Code to handle undo/redo of moves. // =================================================================== // // Restores the game to the state it was in before the specified move // was made. // private void RestoreGameAt(int n) { // Get the move record. MoveRecord item = (MoveRecord) this.moveHistory[n]; // Stop any animation. this.StopMoveAnimation(); // Clear any board square highlighting. this.UnHighlightSquares(); // Restore the board and update the display. this.board = new Board(item.board); this.UpdateBoardDisplay(); // Restore the current player. this.currentColor = item.currentColor; // Restore the move list. this.moveListView.Items.Clear(); for (int i = 0; i < n; i ) { item = (MoveRecord) this.moveHistory[i]; this.moveListView.Items.Add(item.moveListItem); } if (this.moveListView.Items.Count > 0) this.moveListView.EnsureVisible(this.moveListView.Items.Count - 1); else this.moveListView.Refresh(); // Set the current move number. this.moveNumber = n 1; // Enable/disable the move-related menu items and tool bar buttons // as appropriate. this.undoMoveMenuItem.Enabled = this.undoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.UndoAllMoves].Enabled = (this.moveNumber > 1); this.redoMoveMenuItem.Enabled = this.redoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoAllMoves].Enabled = (this.moveNumber < this.moveHistory.Count); this.resumePlayMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.ResumePlay].Enabled = false; // Suspend computer play. this.isComputerPlaySuspended = true; } // // Undoes the previous move or all moves. // private void UndoMove(bool undoAll) { // Save the current game state so we'll know if we need to perform // a restart. GameState oldGameState = this.gameState; // Stop the computer move thread, if active. this.KillComputerMoveThread(); // Lock the board to prevent any changes by an active computer // move. lock (this.board) { // When undoing the last move, we need to save the current // board and player color in the move history so that it can // be restored if the move is redone. if (this.moveHistory.Count < this.moveNumber) { // Add the data to the move history. this.moveHistory.Add(new MoveRecord(this.board, -this.lastMoveColor, new ListViewItem())); } // Undo either the previous move or all moves. this.RestoreGameAt((undoAll ? 0 : this.moveNumber - 2)); } // If the game was over, restore the statistics and restart it. if (oldGameState == ReversiForm.GameState.GameOver) { this.statistics = new Statistics(this.oldStatistics); this.StartGame(true); } // Otherwise, start play at that move. else this.StartTurn(); } // // Redoes the next move or all moves. // private void RedoMove(bool redoAll) { // Redo either the next move or all moves. this.RestoreGameAt((redoAll ? this.moveHistory.Count - 1 : this.moveNumber)); // Start play at that move. this.StartTurn(); } // =================================================================== // Code to handle the board display. // =================================================================== // // Updates the display to reflect the current game board. // private void UpdateBoardDisplay() { // Set counts. this.blackCountLabel.Text = this.board.BlackCount.ToString(); this.blackCountLabel.Refresh(); this.whiteCountLabel.Text = this.board.WhiteCount.ToString(); this.whiteCountLabel.Refresh(); // Map the current game board to the square controls. SquareControl squareControl; int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { squareControl = (SquareControl) this.squaresPanel.Controls[i * 8 j]; squareControl.Contents = this.board.GetSquareContents(i, j); squareControl.PreviewContents = Board.Empty; } // Redraw the board. this.squaresPanel.Refresh(); } // // Highlights the board squares that represent valid moves for the // current player. // private void HighlightValidMoves() { // Check each square. SquareControl squareControl; int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { squareControl = (SquareControl) this.squaresPanel.Controls[i * 8 j]; if (this.board.IsValidMove(this.currentColor, i, j)) squareControl.IsValid = true; else squareControl.IsValid = false; } } // // Removes any highlighting from all the board squares. // private void UnHighlightSquares() { // Clear the flags on each square. SquareControl squareControl; int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { squareControl = (SquareControl) this.squaresPanel.Controls[i * 8 j]; squareControl.IsActive = false; squareControl.IsValid = false; squareControl.IsNew = false; } } // // Sets the board square colors based on the current game options. // private void SetSquareControlColors() { SquareControl.ActiveSquareBackColor = this.options.ActiveSquareColor; SquareControl.NormalBackColor = this.options.BoardColor; SquareControl.MoveIndicatorColor = this.options.MoveIndicatorColor; SquareControl.ValidMoveBackColor = this.options.ValidMoveColor; } //==================================================================== // These functions to handle the loading and saving of the program // settings. //==================================================================== // // Loads any saved program settings. // private void LoadProgramSettings() { // Load the saved window settings and resize the window. try { // Load the saved window settings. int left = System.Int32.Parse(this.settings.GetValue("Window", "Left")); int top = System.Int32.Parse(this.settings.GetValue("Window", "Top")); int width = System.Int32.Parse(this.settings.GetValue("Window", "Width")); int height = System.Int32.Parse(this.settings.GetValue("Window", "Height")); // Reposition and resize the window. this.StartPosition = System.Windows.Forms.FormStartPosition.Manual; this.DesktopLocation = new Point(left, top); this.ClientSize = new Size(width, height); // Load saved options. this.options.ShowValidMoves = (bool) System.Boolean.Parse(this.settings.GetValue("Options", "ShowValidMoves")); this.options.PreviewMoves = (bool) System.Boolean.Parse(this.settings.GetValue("Options", "PreviewMoves")); this.options.AnimateMoves = (bool) System.Boolean.Parse(this.settings.GetValue("Options", "AnimateMoves")); this.options.BoardColor = Color.FromArgb(System.Int32.Parse(this.settings.GetValue("Options", "BoardColor"))); this.options.ValidMoveColor = Color.FromArgb(System.Int32.Parse(this.settings.GetValue("Options", "ValidMoveColor"))); this.options.ActiveSquareColor = Color.FromArgb(System.Int32.Parse(this.settings.GetValue("Options", "ActiveSquareColor"))); this.options.MoveIndicatorColor = Color.FromArgb(System.Int32.Parse(this.settings.GetValue("Options", "MoveIndicatorColor"))); this.options.FirstMove = (int) System.Int32.Parse(this.settings.GetValue("Options", "FirstMove")); this.options.ComputerPlaysBlack = (bool) System.Boolean.Parse(this.settings.GetValue("Options", "ComputerPlaysBlack")); this.options.ComputerPlaysWhite = (bool) System.Boolean.Parse(this.settings.GetValue("Options", "ComputerPlaysWhite")); this.options.Difficulty = (ReversiForm.Difficulty) System.Enum.Parse(this.options.Difficulty.GetType(), this.settings.GetValue("Options", "Difficulty"), true); // Set the square control colors based on options loaded. this.SetSquareControlColors(); // Load saved statistics. this.statistics.BlackWins = System.Int32.Parse(settings.GetValue("Statistics", "BlackWins")); this.statistics.WhiteWins = System.Int32.Parse(settings.GetValue("Statistics", "WhiteWins")); this.statistics.OverallDraws = System.Int32.Parse(settings.GetValue("Statistics", "OverallDraws")); this.statistics.BlackTotalScore = System.Int32.Parse(settings.GetValue("Statistics", "BlackTotalScore")); this.statistics.WhiteTotalScore = System.Int32.Parse(settings.GetValue("Statistics", "WhiteTotalScore")); this.statistics.ComputerWins = System.Int32.Parse(settings.GetValue("Statistics", "ComputerWins")); this.statistics.UserWins = System.Int32.Parse(settings.GetValue("Statistics", "UserWins")); this.statistics.VsComputerDraws = System.Int32.Parse(settings.GetValue("Statistics", "VsComputerDraws")); this.statistics.ComputerTotalScore = System.Int32.Parse(settings.GetValue("Statistics", "ComputerTotalScore")); this.statistics.UserTotalScore = System.Int32.Parse(settings.GetValue("Statistics", "UserTotalScore")); } catch (Exception ex) {} } // // Saves the current program settings. // private void SaveProgramSettings() { // Save window settings. this.settings.SetValue("Window", "Left", this.windowSettings.Left.ToString()); this.settings.SetValue("Window", "Top", this.windowSettings.Top.ToString()); this.settings.SetValue("Window", "Width", this.windowSettings.Width.ToString()); this.settings.SetValue("Window", "Height", this.windowSettings.Height.ToString()); // Save game options. this.settings.SetValue("Options", "ShowValidMoves", this.options.ShowValidMoves.ToString()); this.settings.SetValue("Options", "PreviewMoves", this.options.PreviewMoves.ToString()); this.settings.SetValue("Options", "AnimateMoves", this.options.AnimateMoves.ToString()); this.settings.SetValue("Options", "BoardColor", SquareControl.NormalBackColor.ToArgb().ToString()); this.settings.SetValue("Options", "ValidMoveColor", SquareControl.ValidMoveBackColor.ToArgb().ToString()); this.settings.SetValue("Options", "ActiveSquareColor", SquareControl.ActiveSquareBackColor.ToArgb().ToString()); this.settings.SetValue("Options", "MoveIndicatorColor", SquareControl.MoveIndicatorColor.ToArgb().ToString()); this.settings.SetValue("Options", "FirstMove", this.options.FirstMove.ToString()); this.settings.SetValue("Options", "ComputerPlaysBlack", this.options.ComputerPlaysBlack.ToString()); this.settings.SetValue("Options", "ComputerPlaysWhite", this.options.ComputerPlaysWhite.ToString()); this.settings.SetValue("Options", "Difficulty", this.options.Difficulty.ToString()); // Save statistics. this.settings.SetValue("Statistics", "BlackWins", this.statistics.BlackWins.ToString()); this.settings.SetValue("Statistics", "WhiteWins", this.statistics.WhiteWins.ToString()); this.settings.SetValue("Statistics", "OverallDraws", this.statistics.OverallDraws.ToString()); this.settings.SetValue("Statistics", "BlackTotalScore", this.statistics.BlackTotalScore.ToString()); this.settings.SetValue("Statistics", "WhiteTotalScore", this.statistics.WhiteTotalScore.ToString()); this.settings.SetValue("Statistics", "ComputerWins", this.statistics.ComputerWins.ToString()); this.settings.SetValue("Statistics", "UserWins", this.statistics.UserWins.ToString()); this.settings.SetValue("Statistics", "VsComputerDraws", this.statistics.VsComputerDraws.ToString()); this.settings.SetValue("Statistics", "ComputerTotalScore", this.statistics.ComputerTotalScore.ToString()); this.settings.SetValue("Statistics", "UserTotalScore", this.statistics.UserTotalScore.ToString()); // Save the program settings. this.settings.Save(); } //==================================================================== // Event handlers for the form. //==================================================================== // // Handles a window close. // private void ReversiForm_Closed(object sender, System.EventArgs e) { // Stop the computer move thread, if active. this.KillComputerMoveThread(); // Save the current program settings. this.SaveProgramSettings(); } // // Handles a window close request. If a game is active, it will prompt // for confirmation first. // private void ReversiForm_Closing(object sender, System.ComponentModel.CancelEventArgs e) { bool doClose = true; // Prompt for confirmation if a game is in progress. if (this.gameState != ReversiForm.GameState.GameOver) { // Create and show the confirm dialog, saving the result. ConfirmDialog dlg = new ConfirmDialog("Exit the program?"); if (dlg.ShowDialog(this) != DialogResult.Yes) doClose = false; dlg.Dispose(); } // Cancel the close request if necessary. if (!doClose) e.Cancel = true; } // // Handles a key press. // private void ReversiForm_KeyPress(object sender, System.Windows.Forms.KeyPressEventArgs e) { // Check the game state to ensure it is the user's turn. if (this.gameState != ReversiForm.GameState.InPlayerMove) return; // Convert the key character to column/row number. string s = e.KeyChar.ToString().ToUpper(); int col = ReversiForm.alpha.IndexOf(s); int row; try { row = System.Int32.Parse(s) - 1; } catch { row = -1; } // Is the key a valid column letter? if (col >= 0 && col < 8) { // Yes; store it, clear the keyed row number and exit. this.keyedColNumber = col; this.keyedRowNumber = -1; return; } // If we don't have a valid column number yet, exit. if (this.keyedColNumber < 0 || this.keyedColNumber > 7) return; // We have a valid column number. Is the key a valid row number? if (row < 0 || row > 7) { // No, reset both and exit. this.keyedColNumber = -1; this.keyedRowNumber = -1; return; } else this.keyedRowNumber = row; // The keyed column and row numbers are valid. Is the position a // valid move? if (this.board.IsValidMove(this.currentColor, this.keyedRowNumber, this.keyedColNumber)) { // Yes, make it. this.MakePlayerMove(this.keyedRowNumber, this.keyedColNumber); } else { // No, reset both. this.keyedColNumber = -1; this.keyedRowNumber = -1; } } // // Handles a window move. // private void ReversiForm_Move(object sender, System.EventArgs e) { // If the window has not been minimized or maximized, save its location. if (this.WindowState == FormWindowState.Normal) { this.windowSettings.X = this.DesktopLocation.X; this.windowSettings.Y = this.DesktopLocation.Y; } } // // Handles a window resize. // private void ReversiForm_Resize(object sender, System.EventArgs e) { // Determine the size each square should be within the board. int l = (int) (Math.Min(this.squaresPanel.Width, this.squaresPanel.Height) / 8); l = Math.Max(l, 8); // Resize and reposition each square control. int i, j; for (i = 0; i < 8; i ) for (j = 0; j < 8; j ) { this.squareControls[i, j].Width = l; this.squareControls[i, j].Height = l; this.squareControls[i, j].Left = j * l; this.squareControls[i, j].Top = i * l; } // Fix the column and row headers. for (i = 0; i < 8; i ) { this.colLabels[i].Width = l; this.colLabels[i].Left = this.cornerLabel.Width i * l; this.rowLabels[i].Height = l; this.rowLabels[i].Top = this.cornerLabel.Height i * l; } // Fix the info panel height to align it's bottom with the bottom row of squares. this.infoPanel.Height = 8 * l this.colLabels[0].Height; // Position the progress bar just to the right of the satus text. this.statusProgressBar.Left = this.statusLabel.Left this.statusLabel.Width; // If the window has not been minimized or maximized, save it size. if (this.WindowState == FormWindowState.Normal) { this.windowSettings.Width = this.ClientSize.Width; this.windowSettings.Height = this.ClientSize.Height; } } //==================================================================== // Event handlers for the menu items. //==================================================================== // // Handles a "New Game" click. // private void newGameMenuItem_Click(object sender, System.EventArgs e) { // Start a new game. this.StartGame(); } // // Handles a "Resign Game" click. // private void resignGameMenuItem_Click(object sender, System.EventArgs e) { bool doEnd = true; // Prompt for confirmation if a game is in progress. if (this.gameState != ReversiForm.GameState.GameOver) { // Create and show the confirm dialog, saving the result. ConfirmDialog dlg = new ConfirmDialog("Resign this game?"); if (dlg.ShowDialog(this) != DialogResult.Yes) doEnd = false; dlg.Dispose(); } // End the game if the request was not cancelled. if (doEnd) { // Stop the computer move thread, if active. this.KillComputerMoveThread(); // Stop any active animation and reset the board display. this.StopMoveAnimation(); this.UnHighlightSquares(); this.UpdateBoardDisplay(); // End the game with the resignation flag set. this.EndGame(true); } } // // Handles an "Options..." click. // private void optionsMenuItem_Click(object sender, System.EventArgs e) { // Create the options dialog and set the option controls according // to the current game options. OptionsDialog dlg = new OptionsDialog(this.options); // Show the options dialog and if the "OK" button was pressed, // update the game options. if (dlg.ShowDialog(this) == DialogResult.OK) { // Update the game options that are safe to change using the // values from the dialog. this.options.ShowValidMoves = dlg.Options.ShowValidMoves; this.options.PreviewMoves = dlg.Options.PreviewMoves; this.options.AnimateMoves = dlg.Options.AnimateMoves; this.options.BoardColor = dlg.Options.BoardColor; this.options.ValidMoveColor = dlg.Options.ValidMoveColor; this.options.ActiveSquareColor = dlg.Options.ActiveSquareColor; this.options.MoveIndicatorColor = dlg.Options.MoveIndicatorColor; this.options.Difficulty = dlg.Options.Difficulty; // Set the square control colors based on the current color options. this.SetSquareControlColors(); // If a game is currently in progress, special handling is // needed for changes to the player options. if (this.gameState != ReversiForm.GameState.GameOver) { // Lock the board to prevent race conditions. lock (this.board) { // If a move is currently being animated, complete it // now. if (this.gameState == ReversiForm.GameState.InMoveAnimation) { // Stop animation and end the move. this.StopMoveAnimation(); this.UpdateBoardDisplay(); this.EndMove(); } // Clear any board square highlighting. this.UnHighlightSquares(); // If the changes to the player options affect the // current player, restart the current turn. if ((dlg.Options.FirstMove != this.options.FirstMove && this.lastMoveColor == Board.Empty) || dlg.Options.ComputerPlaysBlack != this.options.ComputerPlaysBlack || dlg.Options.ComputerPlaysWhite != this.options.ComputerPlaysWhite) { // Kill any currently active computer move. this.KillComputerMoveThread(); // Set the player options. this.options.FirstMove = dlg.Options.FirstMove; this.options.ComputerPlaysBlack = dlg.Options.ComputerPlaysBlack; this.options.ComputerPlaysWhite = dlg.Options.ComputerPlaysWhite; // If no moves have been made yet, set the current color // based on the first move option. if (this.lastMoveColor == Board.Empty) this.currentColor = this.options.FirstMove; // Update the board display. this.squaresPanel.Refresh(); // Restart the current turn. this.StartTurn(); } // Otherwise, set the player options and update the // board display. else { // Set the player options. this.options.FirstMove = dlg.Options.FirstMove; this.options.ComputerPlaysBlack = dlg.Options.ComputerPlaysBlack; this.options.ComputerPlaysWhite = dlg.Options.ComputerPlaysWhite; // Highlight valid moves, if appropriate. if (this.options.ShowValidMoves && !this.IsComputerPlayer(this.currentColor)) this.HighlightValidMoves(); // Update the board display. this.squaresPanel.Refresh(); } } } // A game is not in progress so just set the player options. else { this.options.FirstMove = dlg.Options.FirstMove; this.options.ComputerPlaysBlack = dlg.Options.ComputerPlaysBlack; this.options.ComputerPlaysWhite = dlg.Options.ComputerPlaysWhite; // Update the board display, in case the colors have been // changed. this.squaresPanel.Refresh(); } } dlg.Dispose(); } // // Handles a "Statistics..." click. // private void statisticsMenuItem_Click(object sender, System.EventArgs e) { // Create and show the statistics dialog. StatisticsDialog dlg = new StatisticsDialog(this.statistics); dlg.ShowDialog(this); dlg.Dispose(); } // // Handles an "Exit" click. // private void exitMenuItem_Click(object sender, System.EventArgs e) { // Close the form. this.Close(); } // // Handles an "Undo Move" click. // private void undoMoveMenuItem_Click(object sender, System.EventArgs e) { // Undo the previous move. this.UndoMove(false); } // // Handles a "Redo Move" click. // private void redoMoveMenuItem_Click(object sender, System.EventArgs e) { // Redo the next move. this.RedoMove(false); } // // Handles an "Undo All Moves" click. // private void undoAllMovesmenuItem_Click(object sender, System.EventArgs e) { // Undo all moves. this.UndoMove(true); } // // Handles a "Redo All Moves" click. // private void redoAllMovesMenuItem_Click(object sender, System.EventArgs e) { // Redo all moves. this.RedoMove(true); } // // Handles a "Resume Play" click. // private void resumePlayMenuItem_Click(object sender, System.EventArgs e) { // Disable the "Redo Move," "Redo All Moves" and "Resume Play" // menu items and tool bar buttons. this.redoMoveMenuItem.Enabled = this.redoAllMovesMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoMove].Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.RedoAllMoves].Enabled = false; this.resumePlayMenuItem.Enabled = this.playToolBar.Buttons[(int) ReversiForm.ToolBarButton.ResumePlay].Enabled = false; // Set the game state. this.gameState = ReversiForm.GameState.MoveCompleted; // Clear the suspend computer play flag and restart the turn. this.isComputerPlaySuspended = false; this.StartTurn(); } // // Handles a "Help Topics" click. // private void helpTopicsMenuItem_Click(object sender, System.EventArgs e) { // If the help file exists, show it. Otherwise, display an error // message. System.IO.FileInfo fileInfo = new System.IO.FileInfo(ReversiForm.helpFileName); if (fileInfo.Exists) Help.ShowHelp(this, ReversiForm.helpFileName); else MessageBox.Show(this, String.Format("Help file '{0}' not found.", ReversiForm.helpFileName), "File Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error); } // // Handles an "About" click. // private void aboutMenuItem_Click(object sender, System.EventArgs e) { // Create and show the about dialog. AboutDialog dlg = new AboutDialog(); dlg.ShowDialog(this); dlg.Dispose(); } //==================================================================== // Event handlers for the tool bar. //==================================================================== // // Handles a button click on the tool bar. // private void playToolBar_ButtonClick(object sender, System.Windows.Forms.ToolBarButtonClickEventArgs e) { // Determine which button was clicked and simulate a click on the // corresponding menu item. switch(this.playToolBar.Buttons.IndexOf(e.Button)) { case (int) ReversiForm.ToolBarButton.NewGame: this.newGameMenuItem.PerformClick(); break; case (int) ReversiForm.ToolBarButton.ResignGame: this.resignGameMenuItem.PerformClick(); break; case (int) ReversiForm.ToolBarButton.UndoAllMoves: this.undoAllMovesMenuItem.PerformClick(); break; case (int) ReversiForm.ToolBarButton.UndoMove: this.undoMoveMenuItem.PerformClick(); break; case (int) ReversiForm.ToolBarButton.ResumePlay: this.resumePlayMenuItem.PerformClick(); break; case (int) ReversiForm.ToolBarButton.RedoMove: this.redoMoveMenuItem.PerformClick(); break; case (int) ReversiForm.ToolBarButton.RedoAllMoves: this.redoAllMovesMenuItem.PerformClick(); break; default: break; } } // =================================================================== // Event handlers for the square controls. // =================================================================== // // Handles a mouse move on a board square. // private void SquareControl_MouseMove(object sender, MouseEventArgs e) { // Check the game state to ensure that it is the user's turn. if (this.gameState != ReversiForm.GameState.InPlayerMove) return; SquareControl squareControl = (SquareControl) sender; // If the square is a valid move for the current player, // indicate it. if (this.board.IsValidMove(this.currentColor, squareControl.Row, squareControl.Col)) { // if (!squareControl.IsActive && squareControl.PreviewContents == Board.Empty) { // If the show valid moves option is active, mark the // square. if (this.options.ShowValidMoves) { squareControl.IsActive = true; // If the preview moves option is not active, update // the square display now. if (!this.options.PreviewMoves) squareControl.Refresh(); } // If the preview moves option is active, mark the // appropriate squares. if (this.options.PreviewMoves) { // Create a temporary board to make the move on. Board board = new Board(this.board); board.MakeMove(this.currentColor, squareControl.Row, squareControl.Col); // Set up the move preview. for (int i = 0; i < 8; i ) for (int j = 0; j < 8; j ) if (board.GetSquareContents(i, j) != this.board.GetSquareContents(i, j)) { // Set and update the square display. this.squareControls[i, j].PreviewContents = board.GetSquareContents(i, j); this.squareControls[i, j].Refresh(); } } } // Change the cursor. squareControl.Cursor = System.Windows.Forms.Cursors.Hand; } } // // Handles a mouse leave on a board square. // private void SquareControl_MouseLeave(object sender, System.EventArgs e) { SquareControl squareControl = (SquareControl) sender; // If the square is currently active, deactivate it. if (squareControl.IsActive) { squareControl.IsActive = false; squareControl.Refresh(); } // If the move is being previewed, clear all affected squares. if (squareControl.PreviewContents != Board.Empty) { // Clear the move preview. for (int i = 0; i < 8; i ) for (int j = 0; j < 8; j ) if (this.squareControls[i, j].PreviewContents != Board.Empty) { this.squareControls[i, j].PreviewContents = Board.Empty; this.squareControls[i, j].Refresh(); } } // Restore the cursor. squareControl.Cursor = System.Windows.Forms.Cursors.Default; } // // Handles a click on a board square. // private void SquareControl_Click(object sender, System.EventArgs e) { // Check the game state to ensure it's the user's turn. if (this.gameState != ReversiForm.GameState.InPlayerMove) return; SquareControl squareControl = (SquareControl) sender; // If the move is valid, make it. if (this.board.IsValidMove(this.currentColor, squareControl.Row, squareControl.Col)) { // Restore the cursor. squareControl.Cursor = System.Windows.Forms.Cursors.Default; // Make the move. this.MakePlayerMove(squareControl.Row, squareControl.Col); } } } }
标签: 翻转
小贴士
感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。
- 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
- 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
- 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
- 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。
关于好例子网
本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明
网友评论
我要评论