|
|
using System;
using System.Collections;
using System.Drawing;
namespace tictactoe_basic
{
/// <summary>
/// Summary description for TTTModel.
/// </summary>
public class TTTModel
{
private Players mPlayers = new Players();
private StatusDetector mStatus = new StatusDetector_Hardcoded();
private TTTBoard mBoard = new TTTBoard();
public TTTModel()
{
mBoard.NewGame();
}
public delegate void UpdatedModel();
public event UpdatedModel Updated;
public StatusDetector.ResultEnum Result
{
get { return mStatus.GetStatus(mBoard); }
}
public bool MyTurn
{
get { return mPlayers.MyTurn; }
}
public void SetPlayerType(Player p)
{
mPlayers.SetPlayerType(p);
}
public void MakeMove(GridCoordinate gc)
{
if (Result != StatusDetector.ResultEnum.NotDone) return;
if (mBoard.CellOccupied(gc)) return;
mPlayers.Move(mBoard, gc);
mPlayers.NextPlayer();
NotifyOfUpdate();
if (Result != StatusDetector.ResultEnum.NotDone) return;
if (!mPlayers.CurrentPlayerIsHuman())
{
mPlayers.Move(mBoard, mPlayers.CurrentPlayersMove(mBoard));
mPlayers.NextPlayer();
NotifyOfUpdate();
}
}
public bool CellIsX(GridCoordinate gc)
{
return mBoard.CellIsX(gc);
}
public bool CellIsO(GridCoordinate gc)
{
return mBoard.CellIsO(gc);
}
public void NewGame()
{
mPlayers.NewGame();
mStatus.NewGame();
mBoard.NewGame();
NotifyOfUpdate();
}
public GridCoordinate GetWinnerSlashStart
{
get {return mStatus.GetWinnerSlashStart; }
}
public GridCoordinate GetWinnerSlashEnd
{
get {return mStatus.GetWinnerSlashEnd; }
}
private void NotifyOfUpdate()
{
if (Updated != null)
Updated();
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
class Players
{
private Player mMyPlayer;
private Player mYourPlayer;
private Player mPlayer;
private bool mMyTurn = false;
public Players()
{
mMyPlayer = new HumanPlayer();
mYourPlayer = new HumanPlayer();
SetPlayer();
}
public bool MyTurn
{
get { return mMyTurn; }
}
public void NewGame()
{
mMyTurn = false;
SetPlayer();
}
public void Move(TTTBoard board, GridCoordinate gc)
{
if (mMyTurn)
board.SetCellToO(gc);
else
board.SetCellToX(gc);
}
public void NextPlayer()
{
mMyTurn = !mMyTurn;
SetPlayer();
}
public bool CurrentPlayerIsHuman()
{
return mPlayer.IsHuman();
}
public GridCoordinate CurrentPlayersMove(TTTBoard board)
{
return mPlayer.Calculate(board);
}
public void SetPlayerType(Player p)
{
mMyPlayer = p;
}
private void SetPlayer()
{
if (MyTurn)
mPlayer = mMyPlayer;
else
mPlayer = mYourPlayer;
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// a Player takes a turn.
/// </summary>
abstract public class Player
{
public virtual bool IsHuman()
{
return false;
}
public abstract GridCoordinate Calculate(TTTBoard board);
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// HumanPlayer uses the mouse to select a move
/// Therefore Calculate() returns bogus coordinate
/// </summary>
class HumanPlayer : Player
{
public override bool IsHuman()
{
return true;
}
public override GridCoordinate Calculate(TTTBoard board)
{
return new GridCoordinate(-1, -1);
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// This player finds the first unoccupied square.
/// </summary>
class MachinePlayer_FirstFit : Player
{
public override GridCoordinate Calculate(TTTBoard board)
{
return board.GetNextFreeCell();
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// This player tries some hard-coded strategies:
/// 1) finding two squares ready for a third
/// 2) blocking the other guy
/// not necessarily in that order;
/// if not found return a random free square
/// Assume: we are 'O' the human is 'X'
/// </summary>
class MachinePlayer_HardCoded : Player
{
public override GridCoordinate Calculate(TTTBoard board)
{
GridCoordinate gc = CheckForPossibleMove(board);
if (gc != null) return gc;
return new MachinePlayer_Random().Calculate(board);
}
private GridCoordinate CheckForPossibleMove(TTTBoard board)
{
GridCoordinate gc;
foreach (GridTriplet triplet in new TTTBoardGeometry())
{
gc = CheckAxis(board, triplet);
if (gc != null) return gc;
}
return null;
}
private GridCoordinate CheckAxis(TTTBoard board, GridTriplet triplet)
{
GridCoordinate gc;
foreach(GridTriplet t in triplet)
{
gc = CheckTriplet(board, t);
if (gc != null) return gc;
}
return null;
}
private GridCoordinate CheckTriplet(TTTBoard board, GridTriplet triplet)
{
if (!board.CellOccupied(triplet.Cell0) &&
board.CellOccupied(triplet.Cell1) &&
board.CellsMatch(triplet.Cell1, triplet.Cell2))
return triplet.Cell0;
return null;
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// This player tries some hard-coded strategies:
/// 1) finding two squares ready for a third
/// 2) blocking the other guy
/// 3) a random free square
/// in that order!
/// (Only traps/pins/forks are not recognized.)
/// Assume: we are 'O' the human is 'X'
/// </summary>
class MachinePlayer_HardCoded2 : Player
{
private delegate GridCoordinate CheckTripletFunc(TTTBoard board, GridTriplet triplet);
private delegate GridCoordinate CheckAxisFunc(CheckTripletFunc trip, TTTBoard board, int i);
public override GridCoordinate Calculate(TTTBoard board)
{
GridCoordinate gc;
gc = CheckForMove(new CheckTripletFunc(CheckTripletForWin), board);
if (gc != null) return gc;
gc = CheckForMove(new CheckTripletFunc(CheckTripletForBlock), board);
if (gc != null) return gc;
return new MachinePlayer_Random().Calculate(board);
}
private GridCoordinate CheckForMove(CheckTripletFunc trip, TTTBoard board)
{
GridCoordinate gc;
foreach (GridTriplet triplet in new TTTBoardGeometry())
{
gc = CheckAxis(trip, board, triplet);
if (gc != null) return gc;
}
return null;
}
private GridCoordinate CheckAxis(CheckTripletFunc trip, TTTBoard board, GridTriplet triplet)
{
GridCoordinate gc;
foreach(GridTriplet t in triplet)
{
gc = trip(board, t);
if (gc != null) return gc;
}
return null;
}
private GridCoordinate CheckTripletForWin(TTTBoard board, GridTriplet triplet)
{
if (!board.CellOccupied(triplet.Cell0) &&
board.CellsMatch(triplet.Cell1, triplet.Cell2) && board.CellIsO(triplet.Cell1))
return triplet.Cell0;
return null;
}
private GridCoordinate CheckTripletForBlock(TTTBoard board, GridTriplet triplet)
{
if (!board.CellOccupied(triplet.Cell0) &&
board.CellsMatch(triplet.Cell1, triplet.Cell2) && board.CellIsX(triplet.Cell1))
return triplet.Cell0;
return null;
}
}
}
|
|
|
using System;
using System.Collections;
namespace tictactoe_basic
{
/// <summary>
/// This player selects a random cell
/// from the unoccupied cells
/// </summary>
class MachinePlayer_Random : Player
{
ArrayList mFreeCells = new ArrayList();
public override GridCoordinate Calculate(TTTBoard board)
{
mFreeCells = board.GetFreeCells();
if (mFreeCells.Count == 0) return null;
return RandomCell();
}
private GridCoordinate RandomCell()
{
return (GridCoordinate) mFreeCells[RandomIndex()];
}
private int RandomIndex()
{
return new Random().Next(mFreeCells.Count);
}
}
}
|
|
|
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace tictactoe_basic
{
/// <summary>
/// Summary description for MainWindow.
/// </summary>
public class MainWindow : System.Windows.Forms.Form
{
private TTTModel mModel = new TTTModel();
private TTTBoardGrid mGrid;
private System.Windows.Forms.Button mResultMistake;
private System.Windows.Forms.GroupBox groupBox1;
private System.Windows.Forms.RadioButton mNotDone;
private System.Windows.Forms.RadioButton mIWin;
private System.Windows.Forms.RadioButton mYouWin;
private System.Windows.Forms.RadioButton mATie;
private System.Windows.Forms.Button mNewGame;
private System.Windows.Forms.Label mMyTurn;
private System.Windows.Forms.Label mYourTurn;
private System.Windows.Forms.ListBox mMessages;
private System.Windows.Forms.MainMenu mainMenu1;
private System.Windows.Forms.MenuItem menuItem1;
private System.Windows.Forms.MenuItem mMenuPlayerHuman;
private System.Windows.Forms.MenuItem menuItem7;
private System.Windows.Forms.MenuItem mMenuPlayerFirstFit;
private System.Windows.Forms.MenuItem mMenuPlayerRandom;
private System.Windows.Forms.MenuItem mMenuPlayerHardCoded;
private System.Windows.Forms.MenuItem mMenuPlayerHardCoded2;
private MenuItem mCurrentPlayer;
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.Container components = null;
public MainWindow()
{
this.mGrid = new TTTBoardGrid(mModel);
InitializeComponent();
mModel.Updated += new TTTModel.UpdatedModel(OnModelUpdated);
this.Controls.Add(mGrid);
mModel.NewGame();
mCurrentPlayer = mMenuPlayerHuman;
mMenuPlayerHuman.Checked = true;
}
/// <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.mNotDone = new System.Windows.Forms.RadioButton();
this.mIWin = new System.Windows.Forms.RadioButton();
this.mResultMistake = new System.Windows.Forms.Button();
this.groupBox1 = new System.Windows.Forms.GroupBox();
this.mATie = new System.Windows.Forms.RadioButton();
this.mYouWin = new System.Windows.Forms.RadioButton();
this.mNewGame = new System.Windows.Forms.Button();
this.mMyTurn = new System.Windows.Forms.Label();
this.mYourTurn = new System.Windows.Forms.Label();
this.mMessages = new System.Windows.Forms.ListBox();
this.mainMenu1 = new System.Windows.Forms.MainMenu();
this.menuItem1 = new System.Windows.Forms.MenuItem();
this.mMenuPlayerHuman = new System.Windows.Forms.MenuItem();
this.mMenuPlayerFirstFit = new System.Windows.Forms.MenuItem();
this.mMenuPlayerRandom = new System.Windows.Forms.MenuItem();
this.mMenuPlayerHardCoded = new System.Windows.Forms.MenuItem();
this.mMenuPlayerHardCoded2 = new System.Windows.Forms.MenuItem();
this.menuItem7 = new System.Windows.Forms.MenuItem();
this.groupBox1.SuspendLayout();
this.SuspendLayout();
//
// mNotDone
//
this.mNotDone.Enabled = false;
this.mNotDone.Location = new System.Drawing.Point(8, 13);
this.mNotDone.Name = "mNotDone";
this.mNotDone.Size = new System.Drawing.Size(72, 24);
this.mNotDone.TabIndex = 1;
this.mNotDone.Text = "Not Done";
//
// mIWin
//
this.mIWin.Enabled = false;
this.mIWin.Location = new System.Drawing.Point(88, 13);
this.mIWin.Name = "mIWin";
this.mIWin.Size = new System.Drawing.Size(56, 24);
this.mIWin.TabIndex = 2;
this.mIWin.Text = "I Win!";
//
// mResultMistake
//
this.mResultMistake.Location = new System.Drawing.Point(272, 13);
this.mResultMistake.Name = "mResultMistake";
this.mResultMistake.Size = new System.Drawing.Size(88, 23);
this.mResultMistake.TabIndex = 5;
this.mResultMistake.Text = "That\'s Wrong!";
this.mResultMistake.Visible = false;
//
// groupBox1
//
this.groupBox1.Controls.AddRange(new System.Windows.Forms.Control[] {
this.mATie,
this.mYouWin,
this.mNotDone,
this.mIWin,
this.mResultMistake});
this.groupBox1.Location = new System.Drawing.Point(144, 352);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(368, 48);
this.groupBox1.TabIndex = 6;
this.groupBox1.TabStop = false;
this.groupBox1.Text = "The Result";
//
// mATie
//
this.mATie.Enabled = false;
this.mATie.Location = new System.Drawing.Point(216, 12);
this.mATie.Name = "mATie";
this.mATie.Size = new System.Drawing.Size(56, 24);
this.mATie.TabIndex = 5;
this.mATie.Text = "A Tie!";
//
// mYouWin
//
this.mYouWin.Enabled = false;
this.mYouWin.Location = new System.Drawing.Point(144, 12);
this.mYouWin.Name = "mYouWin";
this.mYouWin.Size = new System.Drawing.Size(72, 24);
this.mYouWin.TabIndex = 4;
this.mYouWin.Text = "You Win!";
//
// mNewGame
//
this.mNewGame.Location = new System.Drawing.Point(24, 32);
this.mNewGame.Name = "mNewGame";
this.mNewGame.TabIndex = 7;
this.mNewGame.Text = "New Game";
this.mNewGame.Click += new System.EventHandler(this.mNewGame_Click);
//
// mMyTurn
//
this.mMyTurn.Location = new System.Drawing.Point(24, 88);
this.mMyTurn.Name = "mMyTurn";
this.mMyTurn.Size = new System.Drawing.Size(64, 16);
this.mMyTurn.TabIndex = 8;
this.mMyTurn.Text = "My Turn!";
//
// mYourTurn
//
this.mYourTurn.Location = new System.Drawing.Point(24, 104);
this.mYourTurn.Name = "mYourTurn";
this.mYourTurn.Size = new System.Drawing.Size(64, 16);
this.mYourTurn.TabIndex = 9;
this.mYourTurn.Text = "Your Turn!";
//
// mMessages
//
this.mMessages.Location = new System.Drawing.Point(0, 144);
this.mMessages.Name = "mMessages";
this.mMessages.Size = new System.Drawing.Size(136, 251);
this.mMessages.TabIndex = 10;
//
// mainMenu1
//
this.mainMenu1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.menuItem1});
//
// menuItem1
//
this.menuItem1.Index = 0;
this.menuItem1.MenuItems.AddRange(new System.Windows.Forms.MenuItem[] {
this.mMenuPlayerHuman,
this.mMenuPlayerFirstFit,
this.mMenuPlayerRandom,
this.mMenuPlayerHardCoded,
this.mMenuPlayerHardCoded2,
this.menuItem7});
this.menuItem1.Text = "Player Type";
//
// mMenuPlayerHuman
//
this.mMenuPlayerHuman.Index = 0;
this.mMenuPlayerHuman.Text = "Human";
this.mMenuPlayerHuman.Click += new System.EventHandler(this.mMenuPlayerHuman_Click);
//
// mMenuPlayerFirstFit
//
this.mMenuPlayerFirstFit.Index = 1;
this.mMenuPlayerFirstFit.Text = "First Fit";
this.mMenuPlayerFirstFit.Click += new System.EventHandler(this.mMenuPlayerFirstFit_Click);
//
// mMenuPlayerRandom
//
this.mMenuPlayerRandom.Index = 2;
this.mMenuPlayerRandom.Text = "Random";
this.mMenuPlayerRandom.Click += new System.EventHandler(this.mMenuPlayerRandom_Click);
//
// mMenuPlayerHardCoded
//
this.mMenuPlayerHardCoded.Index = 3;
this.mMenuPlayerHardCoded.Text = "Hard Coded #1";
this.mMenuPlayerHardCoded.Click += new System.EventHandler(this.mMenuPlayerHardCoded_Click);
//
// mMenuPlayerHardCoded2
//
this.mMenuPlayerHardCoded2.Index = 4;
this.mMenuPlayerHardCoded2.Text = "Hard Coded #2";
this.mMenuPlayerHardCoded2.Click += new System.EventHandler(this.mMenuPlayerHardCoded2_Click);
//
// menuItem7
//
this.menuItem7.Enabled = false;
this.menuItem7.Index = 5;
this.menuItem7.Text = "Neural Net";
//
// MainWindow
//
this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
this.ClientSize = new System.Drawing.Size(520, 405);
this.Controls.AddRange(new System.Windows.Forms.Control[] {
this.mMessages,
this.mYourTurn,
this.mMyTurn,
this.mNewGame,
this.groupBox1});
this.MaximizeBox = false;
this.Menu = this.mainMenu1;
this.MinimizeBox = false;
this.Name = "MainWindow";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
this.Text = "Tic-Tac-Toe Basic";
this.groupBox1.ResumeLayout(false);
this.ResumeLayout(false);
}
#endregion
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.Run(new MainWindow());
}
public void OnModelUpdated()
{
UpdateResult();
UpdateTurn();
mGrid.Invalidate();
}
private void mNewGame_Click(object sender, System.EventArgs e)
{
mModel.NewGame();
}
private void UpdateTurn()
{
if (mModel.MyTurn)
{
this.mMyTurn.BackColor = Color.Azure;
this.mYourTurn.BackColor = Color.LightGray;
}
else
{
this.mMyTurn.BackColor = Color.LightGray;
this.mYourTurn.BackColor = Color.Azure;
}
}
private void UpdateResult()
{
this.mNotDone.BackColor = Color.LightGray;
this.mATie.BackColor = Color.LightGray;
this.mIWin.BackColor = Color.LightGray;
this.mYouWin.BackColor = Color.LightGray;
RadioButton btn = null;
switch(mModel.Result)
{
case StatusDetector.ResultEnum.NotDone: btn = this.mNotDone; break;
case StatusDetector.ResultEnum.Tie: btn = this.mATie; break;
case StatusDetector.ResultEnum.IWin: btn = this.mIWin; break;
case StatusDetector.ResultEnum.YouWin: btn = this.mYouWin; break;
}
btn.Checked = true;
btn.BackColor = Color.Azure;
}
private void mMenuPlayerFirstFit_Click(object sender, System.EventArgs e)
{
mModel.SetPlayerType(new MachinePlayer_FirstFit());
SelectPlayerItem(mMenuPlayerFirstFit);
}
private void mMenuPlayerHardCoded_Click(object sender, System.EventArgs e)
{
mModel.SetPlayerType(new MachinePlayer_HardCoded());
SelectPlayerItem(mMenuPlayerHardCoded);
}
private void mMenuPlayerHardCoded2_Click(object sender, System.EventArgs e)
{
mModel.SetPlayerType(new MachinePlayer_HardCoded2());
SelectPlayerItem(mMenuPlayerHardCoded2);
}
private void mMenuPlayerHuman_Click(object sender, System.EventArgs e)
{
mModel.SetPlayerType(new HumanPlayer());
SelectPlayerItem(mMenuPlayerHuman);
}
private void mMenuPlayerRandom_Click(object sender, System.EventArgs e)
{
mModel.SetPlayerType(new MachinePlayer_Random());
SelectPlayerItem(mMenuPlayerRandom);
}
private void SelectPlayerItem(MenuItem newitem)
{
mCurrentPlayer.Checked = false;
newitem.Checked = true;
mCurrentPlayer = newitem;
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// base class for all Status Detectors
/// </summary>
public abstract class StatusDetector
{
public enum ResultEnum {NotDone, IWin, YouWin, Tie};
protected GridCoordinate mResultWinnerStart = new GridCoordinate(-1, -1);
protected GridCoordinate mResultWinnerEnd = new GridCoordinate(-1, -1);
public void NewGame()
{
mResultWinnerStart = new GridCoordinate(-1, -1);
mResultWinnerEnd = new GridCoordinate(-1, -1);
}
public GridCoordinate GetWinnerSlashStart
{
get {return mResultWinnerStart; }
}
public GridCoordinate GetWinnerSlashEnd
{
get {return mResultWinnerEnd; }
}
public abstract ResultEnum GetStatus(TTTBoard board);
protected void SetWinner(GridCoordinate start, GridCoordinate end)
{
mResultWinnerStart = start;
mResultWinnerEnd = end;
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// Just try all the possible combinations...
/// </summary>
public class StatusDetector_Hardcoded : StatusDetector
{
public override ResultEnum GetStatus(TTTBoard board)
{
ResultEnum res;
for (int row = 0; row < 3; ++row)
{
res = RowStatus(board, row);
if (res != ResultEnum.NotDone) return res;
}
for (int col = 0; col < 3; ++col)
{
res = ColStatus(board, col);
if (res != ResultEnum.NotDone) return res;
}
res = Diag1Status(board);
if (res != ResultEnum.NotDone) return res;
res = Diag2Status(board);
if (res != ResultEnum.NotDone) return res;
for (int row = 0; row < 3; ++row)
for (int col = 0; col< 3; ++col)
if (!board.CellOccupied(new GridCoordinate(row, col)))
return ResultEnum.NotDone;
return ResultEnum.Tie;
}
private ResultEnum RowStatus(TTTBoard board, int row)
{
GridTriplet triplet = new GridTriplet(new GridCoordinate(row, 0), new GridCoordinate(row, 1), new GridCoordinate(row, 2));
return LineStatus(board, triplet);
}
private ResultEnum ColStatus(TTTBoard board, int col)
{
GridTriplet triplet = new GridTriplet(new GridCoordinate(0, col), new GridCoordinate(1, col), new GridCoordinate(2, col));
return LineStatus(board, triplet );
}
private ResultEnum Diag1Status(TTTBoard board)
{
GridTriplet triplet = new GridTriplet(new GridCoordinate(0, 0), new GridCoordinate(1, 1), new GridCoordinate(2, 2));
return LineStatus(board, triplet);
}
private ResultEnum Diag2Status(TTTBoard board)
{
GridTriplet triplet = new GridTriplet(new GridCoordinate(2, 0), new GridCoordinate(1, 1), new GridCoordinate(0, 2));
return LineStatus(board, triplet);
}
private ResultEnum LineStatus(TTTBoard board, GridTriplet triplet)
{
if (!LineFilled(board, triplet)) return ResultEnum.NotDone;
SetWinner(triplet.Cell0, triplet.Cell2);
return StatusOf(board, triplet.Cell0);
}
private bool LineFilled(TTTBoard board, GridTriplet triplet)
{
return board.CellsMatch(triplet.Cell0, triplet.Cell1) &&
board.CellsMatch(triplet.Cell0, triplet.Cell2) &&
board.CellOccupied(triplet.Cell0);
}
private ResultEnum StatusOf(TTTBoard board, GridCoordinate gc)
{
if (board.CellIsX(gc))
return ResultEnum.YouWin;
return ResultEnum.IWin;
}
}
}
|
|
|
using System;
using System.Collections;
namespace tictactoe_basic
{
/// <summary>
/// Summary description for TTTBoard.
/// </summary>
public class TTTBoard
{
private Cell[,] mBoard = new Cell[3, 3];
public enum Cell{X, O, None};
public TTTBoard()
{
NewGame();
}
public void SetCellToX(GridCoordinate gc)
{
mBoard[gc.Row, gc.Col] = Cell.X;
}
public void SetCellToO(GridCoordinate gc)
{
mBoard[gc.Row, gc.Col] = Cell.O;
}
public bool CellIsX(GridCoordinate gc)
{
return mBoard[gc.Row, gc.Col] == Cell.X;
}
public bool CellIsO(GridCoordinate gc)
{
return mBoard[gc.Row, gc.Col] == Cell.O;
}
public bool CellOccupied(GridCoordinate gc)
{
return CellIsX(gc) || CellIsO(gc);
}
public GridCoordinate GetNextFreeCell()
{
for (int row = 0; row < 3; ++row)
for(int col = 0; col < 3; ++col)
if (mBoard[row, col] == Cell.None)
return new GridCoordinate(row, col);
return null;
}
public ArrayList GetFreeCells()
{
ArrayList list = new ArrayList();
for (int row = 0; row < 3; ++row)
for(int col = 0; col < 3; ++col)
if (mBoard[row, col] == Cell.None)
list.Add(new GridCoordinate(row, col));
return list;
}
public void NewGame()
{
for(int row = 0; row < 3; ++row)
for(int col = 0; col < 3; ++col)
mBoard[row,col] = Cell.None;
}
public bool CellsMatch(GridCoordinate gc1, GridCoordinate gc2)
{
return mBoard[gc1.Row, gc1.Col] == mBoard[gc2.Row, gc2.Col];
}
}
}
|
|
|
using System;
using System.Collections;
using System.Drawing;
namespace tictactoe_basic
{
class TTTBoardGeometry : IEnumerable
{
private const int cHotGap = 10;
private const int cLineWidth = 3;
private const int cGap = 5;
private Rectangle[,] mRects = new Rectangle[3,3];
private int mColWidth = -1;
private int mRowHeight = -1;
private int mWidth = -1;
private int mHeight = -1;
public IEnumerator GetEnumerator()
{
return new GridEnumerator();
}
public void Init(int h, int w)
{
mHeight = h - 2 * cGap;
mWidth = w - 2 * cGap;
mColWidth = (mWidth - 2 * cLineWidth) / 3;
mRowHeight = (mHeight - 2 * cLineWidth) / 3;
int colwidth = mColWidth - (2 * cHotGap);
int rowheight = mRowHeight - (2 * cHotGap);
mRects[0,0].X = cGap + cHotGap;
mRects[0,0].Y = cGap + cHotGap;
mRects[0,0].Width = colwidth;
mRects[0,0].Height = rowheight;
mRects[0,1].X = mRects[0,0].X + mRects[0,0].Width + cHotGap + cLineWidth + cHotGap;
mRects[0,1].Y = cGap + cHotGap;
mRects[0,1].Width = colwidth;
mRects[0,1].Height = rowheight;
mRects[0,2].X = mRects[0,1].X + mRects[0,1].Width + cHotGap + cLineWidth + cHotGap;
mRects[0,2].Y = cGap + cHotGap;
mRects[0,2].Width = colwidth;
mRects[0,2].Height = rowheight;
mRects[1,0].X = cGap + cHotGap;
mRects[1,0].Y = mRects[0,0].Y + mRects[0,0].Height + cHotGap + cLineWidth + cHotGap;
mRects[1,0].Width = colwidth;
mRects[1,0].Height = rowheight;
mRects[1,1].X = mRects[1,0].X + mRects[1,0].Width + cHotGap + cLineWidth + cHotGap;
mRects[1,1].Y = mRects[0,1].Y + mRects[0,1].Height + cHotGap + cLineWidth + cHotGap;
mRects[1,1].Width = colwidth;
mRects[1,1].Height = rowheight;
mRects[1,2].X = mRects[1,1].X + mRects[1,1].Width + cHotGap + cLineWidth + cHotGap;
mRects[1,2].Y = mRects[0,2].Y + mRects[0,2].Height + cHotGap + cLineWidth + cHotGap;
mRects[1,2].Width = colwidth;
mRects[1,2].Height = rowheight;
mRects[2,0].X = cGap + cHotGap;
mRects[2,0].Y = mRects[1,0].Y + mRects[1,0].Height + cHotGap + cLineWidth + cHotGap;
mRects[2,0].Width = colwidth;
mRects[2,0].Height = rowheight;
mRects[2,1].X = mRects[2,0].X + mRects[2,0].Width + cHotGap + cLineWidth + cHotGap;
mRects[2,1].Y = mRects[1,1].Y + mRects[1,1].Height + cHotGap + cLineWidth + cHotGap;
mRects[2,1].Width = colwidth;
mRects[2,1].Height = rowheight;
mRects[2,2].X = mRects[2,1].X + mRects[2,1].Width + cHotGap + cLineWidth + cHotGap;
mRects[2,2].Y = mRects[1,2].Y + mRects[1,2].Height + cHotGap + cLineWidth + cHotGap;
mRects[2,2].Width = colwidth;
mRects[2,2].Height = rowheight;
}
public int IndexAtPoint(int x, int y)
{
for(int row = 0; row < 3; ++row)
for(int col = 0; col < 3; ++col)
if (mRects[row,col].Contains(x, y))
return row*3 + col;
return -1;
}
public Rectangle this [GridCoordinate gc]
{
get { return mRects[gc.Row, gc.Col]; }
}
public Point TopLeft(GridCoordinate gc)
{
return new Point(mRects[gc.Row, gc.Col].X, mRects[gc.Row, gc.Col].Y);
}
public Point TopRight(GridCoordinate gc)
{
return new Point(mRects[gc.Row, gc.Col].X + mRects[gc.Row, gc.Col].Width, mRects[gc.Row, gc.Col].Y);
}
public Point BottomLeft(GridCoordinate gc)
{
return new Point(mRects[gc.Row, gc.Col].X, mRects[gc.Row, gc.Col].Y + mRects[gc.Row, gc.Col].Height);
}
public Point BottomRight(GridCoordinate gc)
{
return new Point(mRects[gc.Row, gc.Col].X + mRects[gc.Row, gc.Col].Width, mRects[gc.Row, gc.Col].Y + mRects[gc.Row, gc.Col].Height);
}
public Point GridVerticalLine1Top
{
get { return new Point(cGap + mColWidth, cGap); }
}
public Point GridVerticalLine1Bottom
{
get { return new Point(cGap + mColWidth, mHeight); }
}
public Point GridVerticalLine2Top
{
get { return new Point(cGap + mColWidth + cLineWidth + mColWidth, cGap); }
}
public Point GridVerticalLine2Bottom
{
get { return new Point(cGap + mColWidth + cLineWidth + mColWidth, mHeight); }
}
public Point GridHorizontalLine1Left
{
get { return new Point(cGap, cGap + mRowHeight); }
}
public Point GridHorizontalLine1Right
{
get { return new Point(mWidth, cGap + mRowHeight); }
}
public Point GridHorizontalLine2Left
{
get { return new Point(cGap, cGap + mRowHeight + cLineWidth + mRowHeight); }
}
public Point GridHorizontalLine2Right
{
get { return new Point(mWidth, cGap + mRowHeight + cLineWidth + mRowHeight); }
}
private static Pen cGridPen = new Pen(Color.Blue, cLineWidth);
public Pen GridPen
{
get { return cGridPen; }
}
private static Pen cXPen = new Pen(Color.Red, cLineWidth);
public Pen XPen
{
get { return cXPen; }
}
private static Pen cOPen = new Pen(Color.Green, cLineWidth);
public Pen OPen
{
get { return cOPen; }
}
private static SolidBrush cBackColor = new SolidBrush(Color.White);
public SolidBrush BackColor
{
get { return cBackColor; }
}
}
}
|
|
|
using System;
using System.Drawing;
using System.Windows.Forms;
namespace tictactoe_basic
{
class TTTBoardGrid : Panel
{
private TTTBoardGeometry mGeometry = new TTTBoardGeometry();
private TTTModel mModel;
public TTTBoardGrid(TTTModel model)
{
mModel = model;
this.BackColor = Color.White;
this.MouseDown += new MouseEventHandler(Grid_MouseDown);
this.Paint += new PaintEventHandler(PaintHandler);
this.Location = new System.Drawing.Point(144, 8);
this.Name = "mGrid";
this.Size = new System.Drawing.Size(368, 336);
mGeometry.Init(this.Height, this.Width);
}
private void Grid_MouseDown(object sender, MouseEventArgs e)
{
int i = mGeometry.IndexAtPoint(e.X, e.Y);
if (i < 0) return;
mModel.MakeMove(new GridCoordinate(i / 3, i % 3));
}
private void PaintHandler(object sender, PaintEventArgs e)
{
Draw(e.Graphics);
}
public void Draw(Graphics g)
{
DrawBackground(g);
DrawGrid(g);
DrawCells(g);
}
private void DrawBackground(Graphics g)
{
g.FillRectangle(mGeometry.BackColor, 0, 0, this.Width, this.Height);
}
private void DrawGrid(Graphics g)
{
g.DrawLine(mGeometry.GridPen, mGeometry.GridVerticalLine1Top, mGeometry.GridVerticalLine1Bottom);
g.DrawLine(mGeometry.GridPen, mGeometry.GridVerticalLine2Top, mGeometry.GridVerticalLine2Bottom);
g.DrawLine(mGeometry.GridPen, mGeometry.GridHorizontalLine1Left, mGeometry.GridHorizontalLine1Right);
g.DrawLine(mGeometry.GridPen, mGeometry.GridHorizontalLine2Left, mGeometry.GridHorizontalLine2Right);
}
private void DrawCells(Graphics g)
{
for(int row = 0; row < 3; ++row)
for(int col = 0; col < 3; ++col)
{
GridCoordinate gc = new GridCoordinate(row, col);
DrawHighlightedBackground(g, gc);
if (mModel.CellIsX(gc))
DrawXAt(g, gc);
else if (mModel.CellIsO(gc))
DrawOAt(g, gc);
}
}
private void DrawXAt(Graphics g, GridCoordinate gc)
{
g.DrawLine(mGeometry.XPen, mGeometry.TopLeft(gc), mGeometry.BottomRight(gc));
g.DrawLine(mGeometry.XPen, mGeometry.TopRight(gc), mGeometry.BottomLeft(gc));
}
private void DrawOAt(Graphics g, GridCoordinate gc)
{
g.DrawEllipse(mGeometry.OPen, mGeometry[gc]);
}
private void DrawHighlightedBackground(Graphics g, GridCoordinate gc)
{
GridCoordinate start = mModel.GetWinnerSlashStart;
GridCoordinate end = mModel.GetWinnerSlashEnd;
if ((start.Col == gc.Col && start.Row == gc.Row) ||
((start.Col + end.Col) / 2 == gc.Col && (start.Row + end.Row) / 2 == gc.Row) ||
(end.Col == gc.Col && end.Row == gc.Row))
g.FillRectangle(new SolidBrush(Color.LightGray), mGeometry[gc]);
}
}
}
|
|
|
using System;
namespace tictactoe_basic
{
/// <summary>
/// Summary description for Coordinate.
/// </summary>
public class GridCoordinate
{
private int mRow;
private int mCol;
public GridCoordinate(int row, int col)
{
mRow = row;
mCol = col;
}
public int Row
{
get { return mRow; }
}
public int Col
{
get { return mCol; }
}
}
}
|
|
|
using System;
using System.Collections;
namespace tictactoe_basic
{
/// <summary>
/// Knows how to return all the possible rows, cols and diagonals
/// </summary>
public class GridEnumerator : IEnumerator
{
private int mCurrent = -1;
public GridEnumerator()
{
Reset();
}
public object Current
{
get
{
switch (mCurrent)
{
//rows
case 0 : return new GridTriplet(new GridCoordinate(0, 0), new GridCoordinate(0, 1), new GridCoordinate(0, 2));
case 1 : return new GridTriplet(new GridCoordinate(1, 0), new GridCoordinate(1, 1), new GridCoordinate(1, 2));
case 2 : return new GridTriplet(new GridCoordinate(2, 0), new GridCoordinate(2, 1), new GridCoordinate(2, 2));
//cols
case 3 : return new GridTriplet(new GridCoordinate(0, 0), new GridCoordinate(1, 0), new GridCoordinate(2, 0));
case 4 : return new GridTriplet(new GridCoordinate(0, 1), new GridCoordinate(1, 1), new GridCoordinate(2, 1));
case 5 : return new GridTriplet(new GridCoordinate(0, 2), new GridCoordinate(1, 2), new GridCoordinate(2, 2));
//diags
case 6 : return new GridTriplet(new GridCoordinate(0, 0), new GridCoordinate(1, 1), new GridCoordinate(2, 2));
case 7 : return new GridTriplet(new GridCoordinate(0, 2), new GridCoordinate(1, 1), new GridCoordinate(2, 0));
default:
throw new InvalidOperationException("bug in GridEnumerator");
}
}
}
public bool MoveNext()
{
if (mCurrent >= 7) return false;
mCurrent++;
return true;
}
public void Reset()
{
mCurrent = -1;
}
}
}
|
|
|
using System;
using System.Collections;
namespace tictactoe_basic
{
/// <summary>
/// A FlyWeight to contain a row, col, or diagonal of cells
/// </summary>
public class GridTriplet
{
GridCoordinate mCell0;
GridCoordinate mCell1;
GridCoordinate mCell2;
public GridTriplet(GridCoordinate cell0, GridCoordinate cell1, GridCoordinate cell2)
{
mCell0 = cell0;
mCell1 = cell1;
mCell2 = cell2;
}
public GridCoordinate Cell0 { get { return mCell0; } }
public GridCoordinate Cell1 { get { return mCell1; } }
public GridCoordinate Cell2 { get { return mCell2; } }
public TripletEnumerator GetEnumerator()
{
return new TripletEnumerator(this);
}
}
}
|
|
|
using System;
using System.Collections;
namespace tictactoe_basic
{
/// <summary>
/// Knows how to permute the cells in a GridTriplet
/// as required by the MachinePlayers
/// </summary>
public class TripletEnumerator : IEnumerator
{
private int mCurrent = -1;
private GridTriplet mOriginal;
public TripletEnumerator(GridTriplet triplet)
{
mOriginal = triplet;
Reset();
}
public object Current
{
get
{
switch (mCurrent)
{
case 0 : return new GridTriplet(mOriginal.Cell0, mOriginal.Cell1, mOriginal.Cell2);
case 1 : return new GridTriplet(mOriginal.Cell1, mOriginal.Cell0, mOriginal.Cell2);
case 2 : return new GridTriplet(mOriginal.Cell2, mOriginal.Cell1, mOriginal.Cell0);
default:
throw new InvalidOperationException("bug in TripletEnumerator");
}
}
}
public bool MoveNext()
{
if (mCurrent >= 2) return false;
mCurrent++;
return true;
}
public void Reset()
{
mCurrent = -1;
}
}
}
|