简单五子棋,没有电脑AI

  刚学了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 }

棋手类:
  1 using System;
  2 using System.Drawing;
  3 
  4 namespace 五子棋.Control
  5 {
  6     class QiShou
  7     {
  8         #region 字段
  9         /// <summary>
 10         /// 棋子图像
 11         /// </summary> 
 12         /// /// <summary>
 13         /// 走棋棋盘
 14         /// </summary>
 15         byte[,] zouqiqipan;
 16         #endregion
 17         #region 属性
 18         public string PlayerName { get; set; }
 19         public Image ImagePlayer { get; set; }
 20         /// <summary>
 21         /// 棋子图像缩放比例
 22         /// </summary>
 23         public float ImageScale { get; set; }
 24 
 25         /// <summary>
 26         /// 走棋棋盘
 27         /// </summary>
 28         public byte[,] ZouQiQiPan
 29         {
 30             get
 31             {
 32                 return zouqiqipan;
 33             }
 34             set
 35             {
 36                 zouqiqipan = value;
 37             }
 38         }
 39         /// <summary>
 40         /// 是否可以走棋
 41         /// </summary>
 42         public bool IsZouqi { get; set; } 
 43         #endregion
 44         /// <summary>
 45         /// 构造函数
 46         /// </summary>
 47         /// <param name="image">棋子图像</param>
 48         /// <param name="imagescale">棋子缩放比例</param>
 49         /// /// <param name="zouqiqipan">走棋棋盘大小</param>
 50         public QiShou(Image image, float imagescale, byte[,] zouqiqipan)
 51         {
 52             this.zouqiqipan = zouqiqipan;
 53             ImagePlayer = image;
 54             ImageScale = imagescale;
 55             Init();
 56         }
 57         /// <summary>
 58         /// 初始化棋手
 59         /// </summary>
 60         private void Init()
 61         {
 62             for (int i = 0; i < zouqiqipan.GetLength(0); i++)
 63             {
 64                 for (int j = 0; j < zouqiqipan.GetLength(1); j++)
 65                 {
 66                     zouqiqipan[i, j] = 0;
 67                 }
 68             }
 69         }
 70 
 71         /// <summary>
 72         /// 下棋落字
 73         /// </summary>
 74         /// <param name="x">棋盘X网格</param>
 75         /// <param name="y">棋盘Y网格</param>
 76         public void LuoZi(int x, int y)
 77         {
 78             ZouQiQiPan[x, y] = 1;
 79         }
 80         #region 绘制棋子
 81         /// <summary>
 82         /// 绘制所有棋子
 83         /// </summary>
 84         /// <param name="start"></param>
 85         /// <param name="grid"></param>
 86         public void Render(Point start, int grid,Action<Image, int,int,float> actionDrawImage)
 87         {
 88             for (int i = 0; i < ZouQiQiPan.GetLength(0); i++)
 89             {
 90                 for (int j = 0; j < ZouQiQiPan.GetLength(1); j++)
 91                 {
 92                     if (zouqiqipan[i, j] == 1)
 93                     {
 94                         Render(i * grid + start.X, i * grid + start.Y,actionDrawImage);
 95 
 96                     }
 97                 }
 98             }
 99         }
100         public void Render(int x,int y, Action<Image, int, int, float> actionDrawImage)
101         {
102             actionDrawImage?.Invoke(ImagePlayer, x, y, ImageScale);
103         }
104         ///// <summary>
105         ///// 绘制棋子
106         ///// </summary>
107         ///// <param name="x">棋盘X网格坐标</param>
108         ///// <param name="y">棋盘Y网格坐标</param>
109         ///// <param name="g">画家对象</param>
110         //public void Render(int x, int y)
111         //{
112         //    //actionDrawimage(x, y, ImagePlayer, ImageScale);
113 
114 
115         //    //绘制棋子,绘制的坐标应该换算到中心
116         //    g.DrawImage(ImagePlayer, x - ImagePlayer.Width * ImageScale / 2, y - ImagePlayer.Height * ImageScale / 2,
117         //        ImagePlayer.Width * ImageScale, ImagePlayer.Height * ImageScale);
118         //}
119         #endregion
120         
121 
122     }
123     
124 }
View Code

棋盘类:

  1 using System;
  2 using System.Drawing;
  3 
  4 namespace 五子棋.Control
  5 {
  6     class QiPan
  7     {
  8 
  9         /// <summary>
 10         /// 棋盘绘制起点坐标
 11         /// </summary>
 12         public readonly Point start;
 13         /// <summary>
 14         /// X缩放
 15         /// </summary>
 16         public int ScaleX { get; set; }
 17         /// <summary>
 18         /// Y缩放
 19         /// </summary>
 20         public int ScaleY { get; set; }
 21         /// <summary>
 22         /// 棋盘宽度
 23         /// </summary>
 24         public int Width { get; set; }
 25         /// <summary>
 26         /// 棋盘高度
 27         /// </summary>
 28         public int Heigth { get; set; }
 29         /// <summary>
 30         /// 网格大小
 31         /// </summary>
 32         public int Grid { get; set; }
 33         /// <summary>
 34         /// 棋盘棋子
 35         /// </summary>
 36         private byte[,] qipanQiZi;
 37         public byte this[int x, int y]
 38         {
 39             get
 40             {
 41                 if (x < qipanQiZi.GetLength(0) && y < qipanQiZi.GetLength(1))
 42                 {
 43                     return qipanQiZi[x, y];
 44                 }
 45                 else
 46                 {
 47                     return 0;
 48                 }
 49             }
 50             set
 51             {
 52                 if (x < qipanQiZi.GetLength(0) && y < qipanQiZi.GetLength(1))
 53                 {
 54                     qipanQiZi[x, y] = value;
 55                 }
 56             }
 57         }
 58 
 59         /// <summary>
 60         /// 构造函数
 61         /// </summary>
 62         /// <param name="width">棋盘宽度</param>
 63         /// <param name="height">棋盘高度</param>
 64         /// <param name="grid">棋盘网格大小</param>
 65         public QiPan(Point start, int width, int height, int grid)
 66         {
 67             this.start = start;
 68             Width = width;
 69             Heigth = height;
 70             Grid = grid;
 71             Init();
 72 
 73         }
 74 
 75         private void Init()
 76         {
 77             qipanQiZi = new byte[Width / Grid + 1, Heigth / Grid + 1];
 78             for (int i = 0; i < qipanQiZi.GetLength(0); i++)
 79             {
 80                 for (int j = 0; j < qipanQiZi.GetLength(1); j++)
 81                 {
 82                     qipanQiZi[i, j] = 0;
 83                 }
 84             }
 85         }
 86 
 87         /// <summary>
 88         /// 构造函数
 89         /// 默认棋盘大小为400*400,方格大小为40
 90         /// </summary>
 91         public QiPan() : this(new Point(50, 50), 400, 400, 40)
 92         {
 93         }
 94         #region Graphics绘制棋盘
 95 
 96 
 97         /// <summary>
 98         /// 绘制棋盘
 99         /// </summary>
100         /// <param name="g"></param>
101         //public void Render(Graphics g)
102         //{
103         //    for (int i = 0; i <= Width / Grid; i++)
104         //    {
105         //        g.DrawLine(Pens.Black, start.X + (Grid * i), start.Y, start.X + (Grid * i), start.Y + Heigth);
106 
107         //    }
108         //    for (int i = 0; i <= Heigth / Grid; i++)
109         //    {
110         //        g.DrawLine(Pens.Black, start.X, start.Y + (Grid * i), start.X + Width, start.Y + (Grid * i));
111         //    }
112         //}
113         #endregion
114         public void Render(Action< Point, Point> actionDrawLine)
115         {
116             int row = Heigth / Grid + 1;
117             int cel = Width / Grid + 1;
118             for (int i = 0; i < row; i++)
119             {
120                 actionDrawLine?.Invoke( new Point(start.X, start.Y + Grid * i), new Point(start.X + Width, start.Y + Grid * i));
121             }
122             for (int i = 0; i < cel; i++)
123             {
124                 actionDrawLine?.Invoke( new Point(start.X + Grid * i, start.Y), new Point(start.X + Grid * i, start.Y + Heigth));
125             }
126         }
127     }
128 }
View Code
原文地址:https://www.cnblogs.com/missile/p/5671945.html