简单五子棋,没有电脑AI

  • 2019 年 10 月 10 日
  • 筆記

  刚学了C#委托,做了个五子棋练习,把前台绘制和后台逻辑分开,前台绘制方法用委托传给后台逻辑。

界面好简单。。。

先看类图

控制类控制整个游戏的逻辑,包括调用棋盘类的属性初始化棋盘、初始化两个棋手、轮流落子。棋盘里有一个二维数组保存整个棋盘的落子情况,棋手里也有一个二维数组保存自己的落子情况。方向类是为了方便判断输赢的。

下面是代码:注释很详细就不说明了:

主要控制类:

  1 using System;    2 using System.Collections.Generic;    3 using System.Drawing;    4 using 五子棋.Properties;    5    6 namespace 五子棋.Control    7 {    8     class Controler    9     {   10         #region 字段   11         ///// <summary>   12         ///// 画家对象   13         ///// </summary>   14         //Graphics g;   15         /// <summary>   16         /// 棋盘对象   17         /// </summary>   18         QiPan qipan;   19         /// <summary>   20         /// 棋手列表   21         /// </summary>   22         List<QiShou> qishou;   23         /// <summary>   24         /// 游戏是否结束   25         /// </summary>   26         bool Gameover = false;   27         /// <summary>   28         /// 绘制直线委托   29         /// </summary>   30         Action<Point, Point> actionDrawLine;   31         /// <summary>   32         /// 绘制棋子图像委托   33         /// </summary>   34         Action<Image, int, int, float> actionDrawimage;   35         /// <summary>   36         /// 取得胜利事件,返回胜利选手的名称   37         /// </summary>   38         Action<string> actionWin;   39         #endregion   40   41         #region 构造函数   42   43         /// <summary>   44         /// 构造函数   45         /// </summary>   46         /// <param name="actionDrawLine">绘制直线委托</param>   47         /// <param name="actionDrawimage">绘制棋子图像委托</param>   48         public Controler(Action< Point, Point> actionDrawLine, Action<Image, int, int, float> actionDrawimage,Action<string> actionWin)   49         {   50             //开始游戏   51             this.actionDrawLine = actionDrawLine;   52             this.actionDrawimage = actionDrawimage;   53             this.actionWin = actionWin;   54             StartGame();   55         }   56         #endregion   57   58         #region 方法   59   60         /// <summary>   61         /// 棋手轮流下棋   62         /// </summary>   63         /// <param name="x">棋子X坐标</param>   64         /// <param name="y">棋子Y坐标</param>   65         public void LuoZi(int x, int y)   66         {   67             if (Gameover)   68             {   69                 return;   70             }   71             //把不在棋盘交点上的坐标换算到最接近的棋盘交点上   72   73             //x = (int)Math.Round((double)(x - qipan.start.X) / qipan.Grid)   74             //    * qipan.Grid + qipan.start.X;   75             //y = (int)Math.Round((double)(y - qipan.start.Y) / qipan.Grid)   76             //    * qipan.Grid + qipan.start.Y;   77             //换算到棋盘第几条线   78             int qipanX = (int)Math.Round((double)(x - qipan.start.X) / qipan.Grid);   79             int qipanY = (int)Math.Round((double)(y - qipan.start.Y) / qipan.Grid);   80             if (qipan[qipanX, qipanY] == 0)   81             {   82                 for (int i = 0; i < qishou.Count; i++)   83                 {   84                     if (qishou[i].IsZouqi)   85                     {   86                         qipan[qipanX, qipanY] = 1;   87                         qishou[i].LuoZi(qipanX, qipanY);   88                         //换算到棋盘控件坐标并绘制棋子   89                         qishou[i].Render(qipanX * qipan.Grid + qipan.start.X,   90                             qipanY * qipan.Grid + qipan.start.Y, actionDrawimage);   91   92                         //判断当前玩家是否获胜,获胜则游戏结束   93                         Gameover = IsWin(qishou[i], new Point(qipanX, qipanY));   94                         if (Gameover)   95                         {   96                             //if (actionWin!=null)   97                             //{   98                             //    actionWin.Invoke(qishou[i].PlayerName);   99                             //}  100                             actionWin?.Invoke(qishou[i].PlayerName);  101                         }  102  103                         //走棋后设置棋手不可走棋  104                         //qishou[i].LuoZi(x, y, g);  105                     }  106                     qishou[i].IsZouqi = !qishou[i].IsZouqi;  107                 }  108             }  109         }  110         /// <summary>  111         /// 刷新界面  112         /// </summary>  113         public void Render()  114         {  115             qipan.Render(actionDrawLine);  116             for (int i = 0; i < qishou.Count; i++)  117             {  118                 qishou[i].Render(qipan.start, qipan.Grid, actionDrawimage);  119             }  120         }  121         /// <summary>  122         /// 判断是否获胜  123         /// </summary>  124         /// <param name="qishou">棋手</param>  125         /// <param name="p">当前棋子坐标</param>  126         /// <returns></returns>  127         public bool IsWin(QiShou qishou, Point p)  128         {  129  130             //如果点在连续直线上就累加,当sum=5时,表示连续5个棋子在一条直线上  131             int sum = 1;  132             for (int i = 0; i < 8; i++)  133             {  134                 Console.WriteLine(i);  135                 //下一个要检查的点  136                 Point nextP = p;  137                 Direction dr = (Direction)i;  138                 if (i % 2 == 0)  139                 {  140                     sum = 1;  141                 }  142                 for (int j = 0; j < 5; j++)  143                 {  144                     //根据当前方向判断设置下一个点  145                     #region switch  146                     switch (dr)  147                     {  148                         case Direction.Top:  149                             nextP.X = nextP.X;  150                             nextP.Y = nextP.Y - 1;  151                             break;  152                         case Direction.RightTop:  153                             nextP.X = nextP.X + 1;  154                             nextP.Y = nextP.Y - 1;  155                             break;  156                         case Direction.Rigth:  157                             nextP.X = nextP.X + 1;  158                             nextP.Y = nextP.Y;  159                             break;  160                         case Direction.RigthBotton:  161                             nextP.X = nextP.X + 1;  162                             nextP.Y = nextP.Y + 1;  163                             break;  164                         case Direction.Botton:  165                             nextP.X = nextP.X;  166                             nextP.Y = nextP.Y + 1;  167                             break;  168                         case Direction.LeftBotton:  169                             nextP.X = nextP.X - 1;  170                             nextP.Y = nextP.Y + 1;  171                             break;  172                         case Direction.Left:  173                             nextP.X = nextP.X - 1;  174                             nextP.Y = nextP.Y;  175                             break;  176                         case Direction.LeftTop:  177                             nextP.X = nextP.X - 1;  178                             nextP.Y = nextP.Y - 1;  179                             break;  180                         default:  181                             break;  182                     }  183                     #endregion  184  185                     if (nextP.X >= 0 && nextP.X < qishou.ZouQiQiPan.GetLength(0)  186                         && nextP.Y >= 0 && nextP.Y < qishou.ZouQiQiPan.GetLength(1))  187                     {  188                         if (qishou.ZouQiQiPan[nextP.X, nextP.Y] == 0)  189                         {  190                             break;  191                         }  192                         else  193                         {  194                             sum += qishou.ZouQiQiPan[nextP.X, nextP.Y];  195                         }  196                     }  197                     else  198                     {  199                         break;  200                     }  201                 }  202                 if (sum == 5)  203                 {  204                     return true;  205                 }  206  207             }  208  209             return false;  210         }  211         /// <summary>  212         /// 开始游戏  213         /// </summary>  214         public void StartGame()  215         {  216             Gameover = false;  217             //初始化棋盘  218             qipan = new QiPan();  219             //初始化两种棋手:白棋和黑棋  220             qishou = new List<QiShou>()  221             {  222                 new QiShou(Resources.白棋,0.08f,new byte[qipan.Heigth/qipan.Grid+1,qipan.Width/qipan.Grid+1]) {IsZouqi=true,PlayerName="Bai" },  223  224                 new QiShou(Resources.黑棋,0.08f,new byte[qipan.Heigth/qipan.Grid+1,qipan.Width/qipan.Grid+1]) { IsZouqi=false,PlayerName="Hei" }  225             };  226             Render();  227         }  228         #endregion  229  230     }  231 }    棋手类: