C#版智能五子棋游戏(3)
作者:作者不详  发布日期:2011/06/12 18:47:05
C#版智能五子棋游戏(3)


其他的一些结构、枚举

using System;

namespace QiuQiu.ChessEngine
{
   /// <summary>
   /// 棋子信息
   /// </summary>
   public struct ChessInfo
   {
      public ChessPosition ChessPosition;
      public ChessType TheChessType;
      
      public ChessInfo(ChessPosition chessPosition, ChessType chessType)
      {
         ChessPosition = chessPosition;
         TheChessType = chessType;
      }
   }
   
   /// <summary>
   /// 棋子位置
   /// </summary>
   public struct ChessPosition
   {
      public int RowIndex;
      public int ColIndex;
      
      public ChessPosition(int rowIndex,int colIndex)
      {
         RowIndex = rowIndex;
         ColIndex = colIndex;
      }
      
      public static bool operator==(ChessPosition chessPosition1,ChessPosition chessPosition2)
      {
         return chessPosition1.ColIndex == chessPosition2.ColIndex && chessPosition1.RowIndex == chessPosition2.RowIndex;
      }
      
      public static bool operator!=(ChessPosition chessPosition1,ChessPosition chessPosition2)
      {
         return chessPosition1.ColIndex != chessPosition2.ColIndex || chessPosition1.RowIndex != chessPosition2.RowIndex;
      }
      
      public override int GetHashCode()
      {
         return base.GetHashCode ();
      }
      
      public override bool Equals(object obj)
      {
         ChessPosition pos = (ChessPosition)obj;
         return RowIndex == pos.RowIndex && ColIndex == pos.ColIndex;
      }
   }
}



using System;

namespace QiuQiu.ChessEngine
{
   /// <summary>
   /// 棋类
   /// </summary>
   public enum ChessType
   {
      None = 0,
      Black = 1,
      White = 2
   }
   
}

using System;
using System.Collections.Generic;
using System.Text;

namespace QiuQiu.ChessEngine
{
   public enum EventType
   {
      Illegality,//犯规
      DataFull,//数据满
      BlackWin,//黑棋胜
      WhiteWin,//白棋胜
      Exceptions
   }
}



PlayerInfoAttribute 特性,用于运行时加载玩家类读取相关信息

using System;
using System.Collections.Generic;
using System.Text;

namespace QiuQiu.ChessEngine
{
   public class PlayerInfoAttribute : Attribute
   {
      public string PlayerName { get; set; }
      public string Author { get; set; }
      public string ModifyTime { get; set; }
   }
}


还有一个,计时器类
using System;

namespace QiuQiu.ChessEngine
{
   /// <summary>
   /// 计时类
   /// </summary>
   public sealed class ChessTimer : IDisposable
   {
      private TimeSpan _blackPlayer;
      private TimeSpan _whitePlayer;
      private DateTime _lastTickTime;
      private ChessType _nowPlayer;
      private System.Timers.Timer _timer;
      
      public event ChessTimerElapsed Elapsed;
      
      public TimeSpan BlackPlayer
      {
         get { return _blackPlayer; }
         set { _blackPlayer = value; }
      }
      
      public TimeSpan WhitePlayer
      {
         get { return _whitePlayer; }
         set { _whitePlayer = value; }
      }
      
      public ChessTimer()
      {
         _timer = new System.Timers.Timer(1000);
         _timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
         Reset();
      }
      
      void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
      {
         switch (_nowPlayer)
         {
            case ChessType.Black:
            _blackPlayer += DateTime.Now - _lastTickTime;
            _lastTickTime = DateTime.Now;
            break;
            case ChessType.White:
            _whitePlayer += DateTime.Now - _lastTickTime;
            _lastTickTime = DateTime.Now;
            break;
         }
         
         if (Elapsed != null)
         Elapsed(this,new ChessTimerEventArgs(_blackPlayer,_whitePlayer));
      }
      
      //public TimeSpan BlackPlayer
      //{
      // get { return fBlackPlayer; }
      // set { fBlackPlayer = value; }
      //}
      
      //public TimeSpan WhitePlayer
      //{
      // get { return fWhitePlayer; }
      // set { fWhitePlayer = value; }
      //}
      
      public void Reset()
      {
         _blackPlayer = _whitePlayer = new TimeSpan(0);
         _lastTickTime = DateTime.Now;
      }
      
      public void Start(ChessType startPlayer)
      {
         Reset();
         _nowPlayer = startPlayer;
         _timer.Start();
      }
      
      public void Stop()
      {
         _timer.Stop();
      }
      
      public void Tick(ChessType chessType)
      {
         _nowPlayer = chessType;
         switch (_nowPlayer)
         {
            case ChessType.Black:
            _blackPlayer += DateTime.Now - _lastTickTime;
            _lastTickTime = DateTime.Now;
            break;
            case ChessType.White:
            _whitePlayer += DateTime.Now - _lastTickTime;
            _lastTickTime = DateTime.Now;
            break;
         }
      }
      
      public void Dispose()
      {
         if (_timer != null)
         {
            _timer.Dispose();
            _timer = null;
         }
      }
   }
   
   public class ChessTimerEventArgs : EventArgs
   {
      public TimeSpan BlackPlayer;
      public TimeSpan WhitePlayer;
      
      public ChessTimerEventArgs(TimeSpan blackPlayer,TimeSpan whitePlayer)
      {
         BlackPlayer = blackPlayer;
         WhitePlayer = whitePlayer;
      }
   }
   
   public delegate void ChessTimerElapsed(object sender, ChessTimerEventArgs e);
}



下面是ChessForm程序集,主是要主界面,棋盘控件,用户玩家的实现,动态加载玩家

先是Chessboard控件,主要是绘制棋盘,用户鼠标事件

using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Windows.Forms;
using QiuQiu.ChessEngine;

namespace QiuQiu.ChessEngine
{
   /// <summary>
   /// 棋盘
   /// </summary>
   public class Chessboard : System.Windows.Forms.UserControl
   {
      /// <summary>
      /// 必需的设计器变量。
      /// </summary>
      private System.ComponentModel.Container components = null;
      
      private int _rowCount;//表线行数
      private int _colCount;//表线列数
      private int _leftBlank;//左边空白像素
      private int _rightBlank;//右边空白像素
      private int _topBlank;//上边空白像素
      private int _buttomBlank;//下边空白像素
      private int _tableLineSpace;//线间间距像素
      private int _chessRadius;//棋子半径
      private Color _tableLineColor;//线颜色
      private Color _focusColor;//焦点颜色
      private IChessData _chessData;//棋子数据
      private bool _canManChess;//是否是用户下棋
      
      private ChessPosition fCurrentPosition;
      
      public event PutChessEventHandle PutChess;
      
      public Chessboard()
      {
         // 该调用是 Windows.Forms 窗体设计器所必需的。
         InitializeComponent();
         
         // TODO: 在 InitializeComponent 调用后添加任何初始化
         _rowCount = 15;//棋盘行数
         _colCount = 15;//棋盘列数
         _leftBlank = 20;//左边留空
         _rightBlank = 20;//右边留空
         _topBlank = 20;//上边留空
         _buttomBlank = 20;//下边留空
         _tableLineSpace = 30;//格间距
         _chessRadius = 10;//棋子半径
         _tableLineColor = Color.Black;//棋盘线颜色
         _focusColor = Color.Red;//焦点颜色
         
         _chessData = new ChessData(_rowCount,_colCount);
         
         int width = _leftBlank + _rightBlank + _tableLineSpace * (_colCount - 1);
         int hight = _topBlank + _buttomBlank + _tableLineSpace * (_rowCount - 1);
         base.Size = new Size(width,hight);
      }
      
      public bool CanManChess
      {
         get { return _canManChess; }
         set { _canManChess = value; }
      }
      
      protected override void OnMouseUp(MouseEventArgs e)
      {
         //鼠标左键弹起事件
         if (_canManChess)
         {
            //如果用户下棋,则进行处理
            ChessPosition chessPosotion = GetChessInfo(e.X, e.Y);
            //鼠标弹出事件触发下子事件
            if (PutChess != null)
            {
               if (!_chessData.HasChess(chessPosotion))
               PutChess(null, new PutChessEventArgs(chessPosotion.RowIndex, chessPosotion.ColIndex));
            }
            Refresh();
         }
         base.OnMouseUp (e);
      }
      
      protected override void OnMouseMove(MouseEventArgs e)
      {
         base.OnMouseMove (e);
         //鼠标移动事件处理焦点
         ChessPosition nowPosotion = GetChessInfo(e.X,e.Y);
         if(nowPosotion.RowIndex >= _rowCount || nowPosotion.ColIndex >= _colCount)
         return;
         if(nowPosotion != fCurrentPosition && !_chessData.HasChess(nowPosotion))
         {
            //当当前鼠标所在位置与原焦点位置不同且当前位置无棋子时更换显示位置
            Graphics graphics = this.CreateGraphics();
            if(!_chessData.HasChess(fCurrentPosition))
            {
               //原焦点不存在棋子则擦去原焦点
               DrawFocus(fCurrentPosition,graphics,new SolidBrush(BackColor));
            }
            DrawFocus(nowPosotion,graphics,new SolidBrush(_focusColor));//绘制新焦点
            fCurrentPosition = nowPosotion;
         }
      }
      
      protected override void OnPaint(PaintEventArgs e)
      {
         //重绘事件
         DrawChessTable(e.Graphics);
         DrawChess(_chessData,e.Graphics);
         base.OnPaint (e);
      }
      
      /// <summary>
      /// 坐标转换成棋子位置
      /// </summary>
      /// <param name="X"></param>
      /// <param name="Y"></param>
      /// <param name="chessType"></param>
      /// <returns></returns>
      private ChessPosition GetChessInfo(int x,int y)
      {
         int rowIndex = (y - _topBlank + (_tableLineSpace >> 1)) / _tableLineSpace;
         int colIndex = (x - _leftBlank + (_tableLineSpace >> 1)) / _tableLineSpace;
         return new ChessPosition(colIndex,rowIndex);
      }
      
      /// <summary>
      /// 绘制棋盘
      /// </summary>
      /// <param name="graphics">绘图对象</param>
      private void DrawChessTable(Graphics graphics)
      {
         Pen pen = new Pen(_tableLineColor,1);
         
         int rowStart = _leftBlank;
         int rowEnd = _leftBlank + _tableLineSpace * (_colCount - 1);
         int colStart = _topBlank;
         int colEnd = _topBlank + _tableLineSpace * (_rowCount - 1);
         for(int rowIndex = 0;rowIndex < _rowCount;rowIndex ++)
         {
            int top = _topBlank + _tableLineSpace * rowIndex;
            graphics.DrawLine(pen,rowStart,top,rowEnd,top);
         }
         for(int colIndex = 0;colIndex < _colCount;colIndex ++)
         {
            int left = _topBlank + _tableLineSpace * colIndex;
            graphics.DrawLine(pen,left,colStart,left,colEnd);
         }
         pen.Dispose();
      }
      /// <summary>
      /// 绘制棋子
      /// </summary>
      /// <param name="chessData">棋子数据</param>
      /// <param name="graphics">绘图对象</param>
      private void DrawChess(IChessData chessData,Graphics graphics)
      {
         if(chessData == null)
         return;
         Brush[] brush = new SolidBrush[3];
         brush[1] = new SolidBrush(Color.Black);
         brush[2] = new SolidBrush(Color.White);
         Pen blackPen = new Pen(Color.Black,1);
         Pen redPen = new Pen(Color.Red,(float)1.5);
         for(int rowIndex = 0;rowIndex < _rowCount;rowIndex ++)
         {
            for(int colIndex = 0;colIndex < _colCount;colIndex ++)
            {
               ChessType chessType = chessData.GetChess(new ChessPosition(rowIndex,colIndex));
               if(chessType != ChessType.None)
               DrawAChess(rowIndex,colIndex,graphics,brush[(int)chessType],blackPen);
            }
         }
         //对上一个子描红框
         if(chessData.LastChess.TheChessType != ChessType.None)
         DrawAChess(chessData.LastChess.ChessPosition.RowIndex,chessData.LastChess.ChessPosition.ColIndex,graphics,brush[(int)chessData.LastChess.TheChessType],redPen);
         brush[1].Dispose();
         brush[2].Dispose();
         blackPen.Dispose();
         redPen.Dispose();
      }
      
      /// <summary>
      /// 绘制一颗棋子
      /// </summary>
      /// <param name="rowIndex">行索引</param>
      /// <param name="colIndex">列索引</param>
      /// <param name="graphics">绘图对象</param>
      /// <param name="brush">棋子笔刷</param>
      /// <param name="blackPen">黑线笔</param>
      private void DrawAChess(int rowIndex,int colIndex,Graphics graphics,Brush brush,Pen blackPen)
      {
         int x = _leftBlank + _tableLineSpace * rowIndex;
         int y = _topBlank + _tableLineSpace * colIndex;
         graphics.FillEllipse(brush,x - _chessRadius,y - _chessRadius,_chessRadius << 1,_chessRadius << 1);
         graphics.DrawEllipse(blackPen,x - _chessRadius,y - _chessRadius,_chessRadius << 1,_chessRadius << 1);
      }
      
      /// <summary>
      /// 绘制焦点
      /// </summary>
      /// <param name="position">焦点位置</param>
      /// <param name="graphics">绘图对象</param>
      /// <param name="brush">绘制笔刷</param>
      private void DrawFocus(ChessPosition position,Graphics graphics,Brush brush)
      {
         int x = _leftBlank + _tableLineSpace * position.RowIndex;
         int y = _topBlank + _tableLineSpace * position.ColIndex;
         Pen pen = new Pen(brush,2);
         graphics.DrawLine(pen,x - 8,y - 8,x - 2,y - 8);
         graphics.DrawLine(pen,x + 3,y - 8,x + 9,y - 8);
         graphics.DrawLine(pen,x - 8,y + 9,x - 2,y + 9);
         graphics.DrawLine(pen,x + 3,y + 9,x + 9,y + 9);
         graphics.DrawLine(pen,x - 8,y - 8,x - 8,y - 2);
         graphics.DrawLine(pen,x - 8,y + 3,x - 8,y + 9);
         graphics.DrawLine(pen,x + 9,y - 8,x + 9,y - 2);
         graphics.DrawLine(pen,x + 9,y + 3,x + 9,y + 9);
      }
      
      public void SetChessData(IChessData chessData)
      {
         _chessData = chessData;
      }
      
      /// <summary>
      /// 清理所有正在使用的资源。
      /// </summary>
      protected override void Dispose( bool disposing )
      {
         if( disposing )
         {
            if(components != null)
            {
               components.Dispose();
            }
         }
         base.Dispose( disposing );
      }
      
      #region 组件设计器生成的代码
      /// <summary>
      /// 设计器支持所需的方法 - 不要使用代码编辑器
      /// 修改此方法的内容。
      /// </summary>
      private void InitializeComponent()
      {
         components = new System.ComponentModel.Container();
      }
      #endregion
      
      public override ISite Site
      {
         get
         {
            return base.Site;
         }
      }
      
   }
}



用户玩家类,实现 IPlayer接口,依赖于Chessboard类
using System;
using System.Collections.Generic;
using System.Text;
using QiuQiu.ChessEngine;

namespace QiuQiu.ChessForm
{
   /// <summary>
   /// 用户玩家类,依赖于棋盘界面
   /// </summary>
   [PlayerInfo(PlayerName = "ManPlayer", Author = "QiuQiu", ModifyTime = "2008-4-23")]
   internal class ManPlayer : IPlayer
   {
      private ChessType _chessType;
      private Chessboard _chessboard;
      private PutChessEventHandle _putChessEventHandle;
      
      /// <summary>
      /// 落子事件,当需要落子时触发该事件
      /// </summary>
      public event PutChessEventHandle PutChess;
      
      /// <summary>
      /// 玩家所执的棋类型
      /// </summary>
      public ChessType ChessType { get { return _chessType; } }
      
      public ManPlayer(Chessboard chessboard)
      {
         _chessboard = chessboard;
         _putChessEventHandle = new PutChessEventHandle(_chessboard_PutChess);
      }
      
      void _chessboard_PutChess(IPlayer sender, PutChessEventArgs args)
      {
         _chessboard.CanManChess = false;
         _chessboard.PutChess -= _putChessEventHandle;
         if (PutChess != null)
         {
            PutChess(this, args);
         }
         
      }
      
      /// <summary>
      /// 初始化玩家
      /// </summary>
      /// <param name="chessData">棋盘数据</param>
      /// <param name="chessType">所执棋类型</param>
      public void Init(ChessType chessType)
      {
         _chessType = chessType;
      }
      
      /// <summary>
      /// 通知进行落子
      /// </summary>
      public void DoChess(IChessData chessData)
      {
         _chessboard.CanManChess = true;
         _chessboard.PutChess += _putChessEventHandle;
      }
      
   }
}



ChessPlayers 类,反射运行时加载玩家类

using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using System.IO;
using QiuQiu.ChessEngine;

namespace QiuQiu.ChessForm
{
   public class ChessPlayers
   {
      private Dictionary<string, Type> _players;
      private static string manPlayerName = "用户玩家";
      
      public void LoadPlayer()
      {
         _players = new Dictionary<string, Type>();
         _players.Add(manPlayerName, typeof(ManPlayer));
         string localPath = Environment.CurrentDirectory;
         string[] dlls = Directory.GetFiles(localPath, "*.dll", SearchOption.TopDirectoryOnly);
         foreach(string dll in dlls)
         {
            Assembly asm = Assembly.LoadFrom(dll);
            Type[] types = asm.GetTypes();
            foreach(Type type in types)
            {
               if (type.IsClass && !type.IsAbstract)
               {
                  Type interfaceType = type.GetInterface(typeof(IPlayer).Name);
                  if (interfaceType != null)
                  {
                     Attribute attr = Attribute.GetCustomAttribute(type, typeof(PlayerInfoAttribute));
                     PlayerInfoAttribute playerInfo = attr as PlayerInfoAttribute;
                     if (playerInfo != null)
                     {
                        _players.Add(playerInfo.PlayerName, type);
                     }
                  }
               }
            }
         }
      }
      
      public string[] GetPlayerNames()
      {
         if (_players == null)
         {
            return new string[] { };
         }
         string[] result = new string[_players.Count];
         _players.Keys.CopyTo(result, 0);
         return result;
      }
      
      public IPlayer GetPlayer(string playerName,MainForm form)
      {
         if (playerName.Equals(manPlayerName))
         {
            return new ManPlayer(form.chessboard1);
         }
         if (_players == null)
         {
            return null;
         }
         if(!_players.ContainsKey(playerName))
         {
            return null;
         }
         Type playerType = _players[playerName];
         if (playerType == null)
         {
            return null;
         }
         try
         {
            IPlayer player = Activator.CreateInstance(playerType) as IPlayer;
            return player;
         }
         catch
         {
            return null;
         }
      }
   }
}



 



本文来源:
上一篇 下一篇