Revers I
Revers I
DEPT: IT
By:
Supervisor:
Amjad Al-gomai
Eng.Daifallah Al-bokary
Ahmad Al-hadi
Ehab Ismail
Youns Rasheed
Ahmad Al-hasani
Abstract
This game build to wins and lose by using artifical intelligence application by also using max-min
algorithm. The goal of the game is to clear the playing field by forming groups of tow like-colored
marbles white and black . The game ends when the player have points more than another player The
more balls destroyed in one shot, the more points scored. Who owns more pieces the other rises to the
top and controls the game.
Introduction
Implementation
We used max-min algorithm search .The mechanism of the algorithm of Maxman is to search each
level at the lowest value and ascend to the father the right of the son until we reach the root.
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;
// 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;
// AI parameters.
private int lookAheadDepth;
private int forfeitWeight;
private int frontierWeight;
private int mobilityWeight;
private int stabilityWeight;
// Defines the maximum move rank value (used for ranking an end
game).
private static int maxRank = System.Int32.MaxValue - 64;
public ReversiForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
// TODO: Add any constructor code after
InitializeComponent call
//
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);
}
// 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();
// Add it.
this.boardPanel.Controls.Add(this.rowLabels[i]);
}
/// <summary>
/// Clean up any resources being used.
/// </summary>
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
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_ButtonClic
k);
//
// 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.Im
ageStream")));
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;
}
//
// 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;
// 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;
//
// 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;
//
// 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);
this.moveListView.EnsureVisible(this.moveListView.Items.Count - 1);
//
// 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;
//
// 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;
}
//
// Stops animation of a move and resets the squares.
//
private void StopMoveAnimation()
{
// Stop the animation timer.
this.animationTimer.Stop();
//
// 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;
//
===================================================================
// 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();
//
===================================================================
// 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;
//
// 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;
this.forfeitWeight * forfeit +
this.frontierWeight * (testBoard.BlackFrontierCount -
testBoard.WhiteFrontierCount) +
this.stabilityWeight * (testBoard.WhiteSafeCount -
testBoard.BlackSafeCount) +
score;
}
//
// 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];
this.moveListView.EnsureVisible(this.moveListView.Items.Count - 1);
else
this.moveListView.Refresh();
//
// 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;
//
// 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));
//
===================================================================
// 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();
//
// 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"));
//
// 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 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());
//====================================================================
// 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();
//
// 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;
//
// 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;
//
// 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);
// 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;
//====================================================================
// 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;
dlg.Dispose();
}
//
// 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);
this.HighlightValidMoves();
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;
//
// 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;
this.squareControls[i, j].Refresh();
}
}
}
//
// Handles a mouse leave on a board square.
//
private void SquareControl_MouseLeave(object sender,
System.EventArgs e)
{
SquareControl squareControl = (SquareControl) sender;
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();
}
}
//
// 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;
Simulation