• 简单五子棋,没有电脑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
  • 相关阅读:
    【转】人类的心理行为模式----《影响力》笔记
    c++类型形参的实参的受限转换
    如何确定网页和查询的相关性
    英语美文摘要
    特殊的字符数组
    c++中的虚函数
    [C#] 常用工具类——应用程序属性信息访问类
    c#常用工具类:文件和二进制转换
    [C#] 常用工具类——文件操作类
    Lamda和Linq语法对比详细
  • 原文地址:https://www.cnblogs.com/missile/p/5671945.html
Copyright © 2020-2023  润新知