C#游戏编程:《控制台小游戏系列》之《四、游戏渲染模块》

来源:互联网 发布:软件开发 风险控制 编辑:程序博客网 时间:2024/04/29 15:20

一、绘图模块结构

  

  渲染模块,也即是绘图模块,由以上相关类和结构组成。以下对每个组件进行描述分析:


  ■绘图类(CDRraw)

  这个类负责渲染画面,提供了一系列的操作用于画面的绘制:

  • 在指定位置绘制字符串
  • 在指定区域绘制字符串
  • 在指定位置绘制矩形
  • 在指定位置填充矩形
  • 指定绘制符号
  • 指定擦除画面背景色
控制台画面的绘制是基于字符的输出,所以字符就是构成画面的元素,这里绘制画面所用到的元素是一个“符号”,一个符号就是2字节的字符串表示,CSymbol枚举了常用的符号,如:@@、##、※、☆、★、○、●、◇、◆、□、■、△、▲等。除此之外,你可以指定你所想要绘制的其他符号。由于控制台的限制,对于其他画面形状,比如直线和曲线之类的画面就难以实现了,这就是只提供矩形的形状的原因。

  ■符号枚举(CSymbol)

  提供了绘制的基本符号。


  ■矩形结构(CRect)

  这个结构由位置和大小决定,表示工作区平面内的一个区域,常用于设定字符串的绘制区域,此区域内的字符串被视为有效,超过此范围的字符串将不被绘制。


  ■位置结构(CPoint)

  这个结构由控制台列和行的位置决定,表示工作区平面内的一个点,常用于设定绘制的位置。


  ■尺寸结构(CSize)

  这个结构由宽高大小决定,表示工作区某个区域的大小,常用于设定矩形的大小等。


  ■字符串处理类(CText)

  考虑到中英文构成的字符串的情况,在绘制字符串的时候要考虑字符串的字节长度问题,这个类提供了字符串的截断和换行等字符串处理功能。


  ■矩阵结构(CMatrix)

  这个结构表示由一个二维数组构成的矩阵,提供了矩阵基本的运算(加,减,乘)和矩阵的旋转(顺时针90度旋转 、180度旋转,270度旋转和逆时针90度旋转、180度旋转、270度旋转)功能。


二、绘图模块实现

  绘图模块由相关类和结构组成,下面是各个组成部分的具体实现:
  ///CText类实现
[csharp] view plaincopyprint?
  1. using System;  
  2. using System.Text;  
  3.   
  4. namespace CGraphics  
  5. {  
  6.     /// <summary>  
  7.     /// 字符串处理类  
  8.     /// </summary>  
  9.     sealed internal class CText  
  10.     {  
  11.         /// <summary>  
  12.         /// 获取字符串字节长度  
  13.         /// </summary>  
  14.         /// <param name="text"></param>  
  15.         /// <returns></returns>  
  16.         public static Int32 getLength(String text)  
  17.         {  
  18.             Byte[] bytes;  
  19.             Int32 len = 0;  
  20.             for (Int32 i = 0; i < text.Length; i++)  
  21.             {  
  22.                 bytes = Encoding.Default.GetBytes(text.Substring(i, 1));  
  23.                 len += bytes.Length > 1 ? 2 : 1;  
  24.             }  
  25.             return len;  
  26.         }  
  27.   
  28.         /// <summary>  
  29.         /// 按字节长度截字符串  
  30.         /// </summary>  
  31.         /// <param name="text">字符串</param>  
  32.         /// <param name="len">字节长度</param>  
  33.         /// <returns></returns>  
  34.         public static String cutText(String text, Int32 len)  
  35.         {  
  36.             if (len < 0 || len > getLength(text))  
  37.             {  
  38.                 throw new ArgumentOutOfRangeException();  
  39.             }  
  40.   
  41.             Int32 charLen = 0;  
  42.             StringBuilder strb = new StringBuilder();  
  43.   
  44.             for (Int32 i = 0; i < text.Length && charLen < len; i++)  
  45.             {  
  46.                 charLen += getLength(text.Substring(i, 1));  
  47.                 strb.Append(text[i]);  
  48.             }  
  49.   
  50.             return strb.ToString();  
  51.         }  
  52.   
  53.         /// <summary>  
  54.         /// 按字符串索引并截取相应字节长度  
  55.         /// </summary>  
  56.         /// <param name="text">字符串</param>  
  57.         /// <param name="index">字符串索引</param>  
  58.         /// <param name="len">字节长度</param>  
  59.         /// <returns></returns>  
  60.         public static String indexOfText(String text, Int32 index, Int32 len)  
  61.         {  
  62.             if (index < 0 || index > text.Length - 1)  
  63.             {  
  64.                 throw new ArgumentOutOfRangeException();  
  65.             }  
  66.   
  67.             if (len < 0 || len > getLength(text))  
  68.             {  
  69.                 throw new ArgumentOutOfRangeException();  
  70.             }  
  71.   
  72.             text = text.Substring(index, text.Length - index);  
  73.   
  74.             return cutText(text, len);  
  75.         }  
  76.   
  77.         /// <summary>  
  78.         /// 字符串换行  
  79.         /// </summary>  
  80.         /// <param name="text">字符串</param>  
  81.         /// <param name="cols">一列为2字节</param>  
  82.         /// <returns></returns>  
  83.         public static String lineBreakText(String text, Int32 cols)  
  84.         {  
  85.             if (cols < 0)  
  86.             {  
  87.                 throw new ArgumentOutOfRangeException();  
  88.             }  
  89.   
  90.             Int32 len = 0;  
  91.             Int32 charLen = 0;  
  92.             StringBuilder strb = new StringBuilder();  
  93.   
  94.             for (Int32 i = 0; i < text.Length; i++)  
  95.             {  
  96.                 len = getLength(text.Substring(i, 1));  
  97.                 charLen += len;  
  98.   
  99.                 if (charLen > (cols <<1))  
  100.                 {  
  101.                     strb.Append(Environment.NewLine);  
  102.                     charLen = len;  
  103.                 }  
  104.   
  105.                 strb.Append(text[i]);  
  106.             }  
  107.   
  108.             return strb.ToString();  
  109.         }  
  110.     }  
  111. }  
  ///CSymbol枚举及相关辅助类实现
[csharp] view plaincopyprint?
  1. using System;  
  2. using System.Text;  
  3.   
  4. namespace CGraphics  
  5. {  
  6.     /// <summary>  
  7.     /// 符号表 每个符号2字节  
  8.     /// </summary>  
  9.     public enum CSymbol  
  10.     {  
  11.         /// <summary>  
  12.         /// 缺省符号  
  13.         /// </summary>  
  14.         DEFAULT = (UInt16)0xA1A1,  
  15.         /// <summary>  
  16.         /// @@  
  17.         /// </summary>  
  18.         AT = (UInt16)0x4040,  
  19.         /// <summary>  
  20.         /// ##  
  21.         /// </summary>  
  22.         WELL = (UInt16)0x2323,  
  23.         /// <summary>  
  24.         /// ※  
  25.         /// </summary>  
  26.         RICE = (UInt16)0xA1F9,  
  27.         /// <summary>  
  28.         /// ☆  
  29.         /// </summary>  
  30.         STAR_EMPTY = (UInt16)0xA1EE,  
  31.         /// <summary>  
  32.         /// ★  
  33.         /// </summary>  
  34.         STAR_SOLID = (UInt16)0xA1EF,  
  35.         /// <summary>  
  36.         /// ○  
  37.         /// </summary>  
  38.         RING_EMPTY = (UInt16)0xA1F0,  
  39.         /// <summary>  
  40.         /// ●  
  41.         /// </summary>  
  42.         RING_SOLID = (UInt16)0xA1F1,  
  43.         /// <summary>  
  44.         /// ◇  
  45.         /// </summary>  
  46.         RHOMB_EMPTY = (UInt16)0xA1F3,  
  47.         /// <summary>  
  48.         /// ◆  
  49.         /// </summary>  
  50.         RHOMB_SOLID = (UInt16)0xA1F4,  
  51.         /// <summary>  
  52.         /// □  
  53.         /// </summary>  
  54.         RECT_EMPTY = (UInt16)0xA1F5,  
  55.         /// <summary>  
  56.         /// ■  
  57.         /// </summary>  
  58.         RECT_SOLID = (UInt16)0xA1F6,  
  59.         /// <summary>  
  60.         /// △  
  61.         /// </summary>  
  62.         TRIANGLE_EMPTY = (UInt16)0xA1F7,  
  63.         /// <summary>  
  64.         /// ▲  
  65.         /// </summary>  
  66.         TRIANGLE_SOLID = (UInt16)0xA1F8  
  67.     }  
  68.   
  69.     /// <summary>  
  70.     /// 符号辅助类  
  71.     /// </summary>  
  72.     internal sealed class CSymbolHelper  
  73.     {  
  74.         /// <summary>  
  75.         /// 根据符号值获取字符串表示  
  76.         /// </summary>  
  77.         /// <param name="symbol"></param>  
  78.         /// <returns></returns>  
  79.         public static String getStringFromSymbol(CSymbol symbol)  
  80.         {  
  81.             UInt16 symbolVal = (UInt16)symbol;  
  82.             Byte[] bytes = { (Byte)((symbolVal & 0xFF00) >> 8), (Byte)(symbolVal & 0x00FF) };  
  83.             return Encoding.Default.GetString(bytes);  
  84.         }  
  85.   
  86.         /// <summary>  
  87.         /// 获取符号十六进制表示  
  88.         /// </summary>  
  89.         /// <param name="symbol"></param>  
  90.         /// <returns></returns>  
  91.         public static String getSymbolHex(String symbol)  
  92.         {  
  93.             if (CText.getLength(symbol) > 2 || symbol == "")  
  94.             {  
  95.                 throw new ArgumentOutOfRangeException("符号不能为空且长度不能超过2字节!");  
  96.             }  
  97.   
  98.             String hex = "0x";  
  99.             Byte[] bytes = Encoding.Default.GetBytes(symbol);  
  100.   
  101.             foreach (Byte b in bytes)  
  102.             {  
  103.                 hex += String.Format("{0:X}", b);  
  104.             }  
  105.   
  106.             return hex;  
  107.         }  
  108.     }  
  109. }  
  为了能够用枚举来表示各种符号,我们把每个符号用16进制表示,当使用的时候,再把其转换成字符串。 
///CSize结构实现
[csharp] view plaincopyprint?
  1. using System;  
  2.   
  3. namespace CGraphics  
  4. {  
  5.     /// <summary>  
  6.     /// 尺寸结构  
  7.     /// </summary>  
  8.     public struct CSize  
  9.     {  
  10.         private Int32 m_width;  
  11.         private Int32 m_height;  
  12.   
  13.         public CSize(Int32 width, Int32 height)  
  14.         {  
  15.             if (width <= 0 || height <= 0)  
  16.             {  
  17.                 throw new ArgumentOutOfRangeException("尺寸大小不合法!");  
  18.             }  
  19.             this.m_width = width;  
  20.             this.m_height = height;  
  21.         }  
  22.   
  23.         public Int32 getWidth()  
  24.         {  
  25.             return this.m_width;  
  26.         }  
  27.   
  28.         public void setWidth(Int32 width)  
  29.         {  
  30.             this.m_width = width;  
  31.         }  
  32.   
  33.         public Int32 getHeight()  
  34.         {  
  35.             return this.m_height;  
  36.         }  
  37.   
  38.         public void setHeight(Int32 height)  
  39.         {  
  40.             this.m_height = height;  
  41.         }  
  42.     }  
  43. }  
  ///CPoint结构在上一章中已经给出具体实现,在这里就不再重复给出了,具体实现请前往上一章。
  ///CRect结构实现
[csharp] view plaincopyprint?
  1. using System;  
  2.   
  3. namespace CGraphics  
  4. {  
  5.     /// <summary>  
  6.     /// 矩形结构  
  7.     /// </summary>  
  8.     public struct CRect  
  9.     {  
  10.         /// <summary>  
  11.         /// 左上角列坐标  
  12.         /// </summary>  
  13.         private Int32 m_x;  
  14.         /// <summary>  
  15.         /// 左上角行坐标  
  16.         /// </summary>  
  17.         private Int32 m_y;  
  18.         /// <summary>  
  19.         /// 矩形宽度  
  20.         /// </summary>  
  21.         private Int32 m_width;  
  22.         /// <summary>  
  23.         /// 矩形高度  
  24.         /// </summary>  
  25.         private Int32 m_height;  
  26.   
  27.         /// <summary>  
  28.         /// 构造函数  
  29.         /// </summary>  
  30.         /// <param name="x"></param>  
  31.         /// <param name="y"></param>  
  32.         /// <param name="w"></param>  
  33.         /// <param name="h"></param>  
  34.         public CRect(Int32 x, Int32 y, Int32 w, Int32 h)  
  35.         {  
  36.             if (w <= 0 || h <= 0)  
  37.             {  
  38.                 throw new ArgumentOutOfRangeException();  
  39.             }  
  40.             this.m_x = x;  
  41.             this.m_y = y;  
  42.             this.m_width = w;  
  43.             this.m_height = h;  
  44.         }  
  45.   
  46.         public CRect(CPoint point, Int32 w, Int32 h)  
  47.         {  
  48.             this.m_x = point.getX();  
  49.             this.m_y = point.getY();  
  50.             this.m_width = w;  
  51.             this.m_height = h;  
  52.         }  
  53.   
  54.         public CRect(Int32 x, Int32 y, CSize size)  
  55.         {  
  56.             this.m_x = x;  
  57.             this.m_y = y;  
  58.             this.m_width = size.getWidth();  
  59.             this.m_height = size.getHeight();  
  60.         }  
  61.   
  62.         public CRect(CPoint point, CSize size)  
  63.         {  
  64.             this.m_x = point.getX();  
  65.             this.m_y = point.getY();  
  66.             this.m_width = size.getWidth();  
  67.             this.m_height = size.getHeight();  
  68.         }  
  69.   
  70.         /// <summary>  
  71.         /// 获取左上角列坐标  
  72.         /// </summary>  
  73.         /// <returns></returns>  
  74.         public Int32 getX()  
  75.         {  
  76.             return this.m_x;  
  77.         }  
  78.         /// <summary>  
  79.         /// 获取左上角行坐标  
  80.         /// </summary>  
  81.         /// <returns></returns>  
  82.         public Int32 getY()  
  83.         {  
  84.             return this.m_y;  
  85.         }  
  86.         /// <summary>  
  87.         /// 获取矩形宽度  
  88.         /// </summary>  
  89.         /// <returns></returns>  
  90.         public Int32 getWidth()  
  91.         {  
  92.             return this.m_width;  
  93.         }  
  94.         /// <summary>  
  95.         /// 获取矩形高度  
  96.         /// </summary>  
  97.         /// <returns></returns>  
  98.         public Int32 getHeight()  
  99.         {  
  100.             return this.m_height;  
  101.         }  
  102.         /// <summary>  
  103.         /// 获取矩形  
  104.         /// </summary>  
  105.         /// <returns></returns>  
  106.         public CRect getCRect()  
  107.         {  
  108.             return new CRect(this.m_x, this.m_y, this.m_width, this.m_height);  
  109.         }  
  110.         /// <summary>  
  111.         /// 设置左上角列坐标  
  112.         /// </summary>  
  113.         /// <param name="x"></param>  
  114.         public void setX(Int32 x)  
  115.         {  
  116.             this.m_x = x;  
  117.         }  
  118.         /// <summary>  
  119.         /// 设置左上角行坐标  
  120.         /// </summary>  
  121.         /// <param name="y"></param>  
  122.         public void setY(Int32 y)  
  123.         {  
  124.             this.m_y = y;  
  125.         }  
  126.         /// <summary>  
  127.         /// 设置矩形宽度  
  128.         /// </summary>  
  129.         /// <param name="w"></param>  
  130.         public void setWidth(Int32 w)  
  131.         {  
  132.             if (w <= 0)  
  133.             {  
  134.                 throw new ArgumentOutOfRangeException();  
  135.             }  
  136.             this.m_width = w;  
  137.         }  
  138.         /// <summary>  
  139.         /// 设置矩形高度  
  140.         /// </summary>  
  141.         /// <param name="h"></param>  
  142.         public void setHeight(Int32 h)  
  143.         {  
  144.             if (h <= 0)  
  145.             {  
  146.                 throw new ArgumentOutOfRangeException();  
  147.             }  
  148.             this.m_height = h;  
  149.         }  
  150.         /// <summary>  
  151.         /// 设置矩形  
  152.         /// </summary>  
  153.         /// <param name="x"></param>  
  154.         /// <param name="y"></param>  
  155.         /// <param name="w"></param>  
  156.         /// <param name="h"></param>  
  157.         public void setCRect(Int32 x, Int32 y, Int32 w, Int32 h)  
  158.         {  
  159.             if (w <= 0 || h <= 0)  
  160.             {  
  161.                 throw new ArgumentOutOfRangeException();  
  162.             }  
  163.             this.m_x = x;  
  164.             this.m_y = y;  
  165.             this.m_width = w;  
  166.             this.m_height = h;  
  167.         }  
  168.         /// <summary>  
  169.         /// 缩放  
  170.         /// </summary>  
  171.         /// <param name="flateX"></param>  
  172.         /// <param name="flateY"></param>  
  173.         public void inflate(Int32 flateX, Int32 flateY)  
  174.         {  
  175.             this.m_x -= flateX;  
  176.             this.m_y -= flateY;  
  177.             this.m_width +=flateX<<1;  
  178.             this.m_height +=flateY<<1;  
  179.         }  
  180.   
  181.         /// <summary>  
  182.         /// 调整矩形位置与尺寸  
  183.         /// </summary>  
  184.         /// <param name="rect"></param>  
  185.         /// <returns></returns>  
  186.         public void adjustRect(ref CRect rect)  
  187.         {  
  188.             Int32 maxX = Console.WindowWidth>>1;  
  189.             Int32 maxY = Console.WindowHeight;  
  190.   
  191.             if (rect.m_x < 0)  
  192.             {  
  193.                 rect.m_x = 0;  
  194.             }  
  195.             else if (rect.m_x > maxX)  
  196.             {  
  197.                 rect.m_x = maxX - 1;  
  198.             }  
  199.   
  200.             if (rect.m_y < 0)  
  201.             {  
  202.                 rect.m_y = 0;  
  203.             }  
  204.             else if (rect.m_y > maxY)  
  205.             {  
  206.                 rect.m_y = maxY;  
  207.             }  
  208.   
  209.             rect.m_x += rect.m_x;  
  210.         }  
  211.   
  212.         public override string ToString()  
  213.         {  
  214.             return string.Format("[{0},{1},{2},{3}]", m_x, m_y, m_width, m_height);  
  215.         }  
  216.     }  
  217. }  
///CMatrix结构实现
[csharp] view plaincopyprint?
  1. using System;  
  2. using System.Text;  
  3.   
  4. namespace CGraphics  
  5. {  
  6.     /// <summary>  
  7.     /// 旋转方式  
  8.     /// </summary>  
  9.     public enum CRotateMode  
  10.     {  
  11.         /// <summary>  
  12.         /// 不旋转  
  13.         /// </summary>  
  14.         None,  
  15.         /// <summary>  
  16.         /// 顺时针旋转90度  
  17.         /// </summary>  
  18.         R90,  
  19.         /// <summary>  
  20.         /// 顺时针旋转180度  
  21.         /// </summary>  
  22.         R180,  
  23.         /// <summary>  
  24.         /// 顺时针旋转270度  
  25.         /// </summary>  
  26.         R270,  
  27.         /// <summary>  
  28.         /// 逆时针旋转90度  
  29.         /// </summary>  
  30.         L90,  
  31.         /// <summary>  
  32.         /// 逆时针旋转180度  
  33.         /// </summary>  
  34.         L180,  
  35.         /// <summary>  
  36.         /// 逆时针旋转270度  
  37.         /// </summary>  
  38.         L270  
  39.     }  
  40.   
  41.     /// <summary>  
  42.     /// 矩阵结构  
  43.     /// </summary>  
  44.     public struct CMatrix  
  45.     {  
  46.         /// <summary>  
  47.         /// 矩阵元素  
  48.         /// </summary>  
  49.         private Int32[,] m_matrix;  
  50.         /// <summary>  
  51.         /// 矩阵行数  
  52.         /// </summary>  
  53.         private Int32 m_rows;  
  54.         /// <summary>  
  55.         /// 矩阵列数  
  56.         /// </summary>  
  57.         private Int32 m_cols;  
  58.         /// <summary>  
  59.         /// 矩阵总元素  
  60.         /// </summary>  
  61.         private Int32 m_totalCount;  
  62.         /// <summary>  
  63.         /// 旋转方式  
  64.         /// </summary>  
  65.         private CRotateMode m_rotate;  
  66.   
  67.         /// <summary>  
  68.         /// 构造函数  
  69.         /// </summary>  
  70.         /// <param name="matrix"></param>  
  71.         public CMatrix(Int32[,] matrix)  
  72.         {  
  73.             this.m_matrix = matrix;  
  74.             this.m_rows = matrix.GetUpperBound(0) + 1;  
  75.             this.m_cols = matrix.GetUpperBound(1) + 1;  
  76.             this.m_totalCount = m_rows * m_cols;  
  77.             this.m_rotate = CRotateMode.None;  
  78.         }  
  79.   
  80.         /// <summary>  
  81.         /// 构造函数  
  82.         /// </summary>  
  83.         /// <param name="row"></param>  
  84.         /// <param name="col"></param>  
  85.         public CMatrix(Int32 row, Int32 col)  
  86.         {  
  87.             this.m_matrix = new Int32[row, col];  
  88.             this.m_rows = m_matrix.GetUpperBound(0) + 1;  
  89.             this.m_cols = m_matrix.GetUpperBound(1) + 1;  
  90.             this.m_totalCount = m_rows * m_cols;  
  91.             this.m_rotate = CRotateMode.None;  
  92.         }  
  93.   
  94.         /// <summary>  
  95.         /// 可以通过索引操作  
  96.         /// </summary>  
  97.         /// <param name="x"></param>  
  98.         /// <param name="y"></param>  
  99.         /// <returns></returns>  
  100.         public Int32 this[Int32 x, Int32 y]  
  101.         {  
  102.             get  
  103.             {  
  104.                 if (x < 0 || y < 0 || x > m_rows - 1 || y > m_cols - 1)  
  105.                 {  
  106.                     throw new ArgumentOutOfRangeException();  
  107.                 }  
  108.                 return m_matrix[x, y];  
  109.             }  
  110.             set  
  111.             {  
  112.                 if (x < 0 || y < 0 || x > m_rows - 1 || y > m_cols - 1)  
  113.                 {  
  114.                     throw new ArgumentOutOfRangeException();  
  115.                 }  
  116.                 m_matrix[x, y] = value;  
  117.             }  
  118.         }  
  119.   
  120.         /// <summary>  
  121.         /// 获取矩阵数组  
  122.         /// </summary>  
  123.         /// <returns></returns>  
  124.         public Int32[,] getMatrixArray()  
  125.         {  
  126.             return this.m_matrix;  
  127.         }  
  128.   
  129.         /// <summary>  
  130.         /// 设置矩阵  
  131.         /// </summary>  
  132.         /// <param name="matrix"></param>  
  133.         public void setMatrix(Int32[,] matrix)  
  134.         {  
  135.             this.m_matrix = matrix;  
  136.             this.m_rows = matrix.GetUpperBound(0) + 1;  
  137.             this.m_cols = matrix.GetUpperBound(1) + 1;  
  138.             this.m_totalCount = m_rows * m_cols;  
  139.             this.m_rotate = CRotateMode.None;  
  140.         }  
  141.   
  142.         /// <summary>  
  143.         /// 获取矩阵行数  
  144.         /// </summary>  
  145.         /// <returns></returns>  
  146.         public Int32 getRows()  
  147.         {  
  148.             return this.m_rows;  
  149.         }  
  150.   
  151.         /// <summary>  
  152.         /// 获取矩阵列数  
  153.         /// </summary>  
  154.         /// <returns></returns>  
  155.         public Int32 getCols()  
  156.         {  
  157.             return this.m_cols;  
  158.         }  
  159.   
  160.         /// <summary>  
  161.         /// 获取矩阵元素总个数  
  162.         /// </summary>  
  163.         /// <returns></returns>  
  164.         public Int32 getTotalCount()  
  165.         {  
  166.             return m_totalCount;  
  167.         }  
  168.   
  169.         /// <summary>  
  170.         /// 设置旋转方式  
  171.         /// </summary>  
  172.         /// <param name="mode"></param>  
  173.         /// <returns></returns>  
  174.         public void setRotateMode(CRotateMode mode)  
  175.         {  
  176.             this.m_rotate = mode;  
  177.         }  
  178.   
  179.         /// <summary>  
  180.         /// 两矩阵相加  
  181.         /// </summary>  
  182.         /// <param name="left"></param>  
  183.         /// <param name="right"></param>  
  184.         /// <returns></returns>  
  185.         public static CMatrix operator +(CMatrix left, CMatrix right)  
  186.         {  
  187.             if ((left.getRows() != right.getRows()) ||  
  188.                 (left.getCols() != right.getCols()))  
  189.             {  
  190.                 throw new CMatrixException("error");  
  191.             }  
  192.   
  193.             Int32 r = left.getRows();  
  194.             Int32 c = left.getCols();  
  195.   
  196.             CMatrix newMatrix = new CMatrix(r, c);  
  197.   
  198.             for (Int32 i = 0; i < r; i++)  
  199.             {  
  200.                 for (Int32 j = 0; j < c; j++)  
  201.                 {  
  202.                     newMatrix[i, j] = left[i, j] + right[i, j];  
  203.                 }  
  204.             }  
  205.   
  206.             return newMatrix;  
  207.         }  
  208.   
  209.         /// <summary>  
  210.         /// 矩阵相加  
  211.         /// </summary>  
  212.         /// <param name="right"></param>  
  213.         /// <returns></returns>  
  214.         public CMatrix add(CMatrix right)  
  215.         {  
  216.             return this + right;  
  217.         }  
  218.   
  219.         /// <summary>  
  220.         /// 两矩阵相减  
  221.         /// </summary>  
  222.         /// <param name="left"></param>  
  223.         /// <param name="right"></param>  
  224.         /// <returns></returns>  
  225.         public static CMatrix operator -(CMatrix left, CMatrix right)  
  226.         {  
  227.             if ((left.getRows() != right.getRows()) ||  
  228.                (left.getCols() != right.getCols()))  
  229.             {  
  230.                 throw new CMatrixException("error");  
  231.             }  
  232.   
  233.             Int32 r = left.getRows();  
  234.             Int32 c = left.getCols();  
  235.   
  236.             CMatrix newMatrix = new CMatrix(r, c);  
  237.   
  238.             for (Int32 i = 0; i < r; i++)  
  239.             {  
  240.                 for (Int32 j = 0; j < c; j++)  
  241.                 {  
  242.                     newMatrix[i, j] = left[i, j] - right[i, j];  
  243.                 }  
  244.             }  
  245.   
  246.             return newMatrix;  
  247.         }  
  248.   
  249.         /// <summary>  
  250.         /// 矩阵相减  
  251.         /// </summary>  
  252.         /// <param name="right"></param>  
  253.         /// <returns></returns>  
  254.         public CMatrix sub(CMatrix right)  
  255.         {  
  256.             return this - right;  
  257.         }  
  258.   
  259.         /// <summary>  
  260.         /// 两矩阵相乘  
  261.         /// </summary>  
  262.         /// <param name="left"></param>  
  263.         /// <param name="right"></param>  
  264.         /// <returns></returns>  
  265.         public static CMatrix operator *(CMatrix left, CMatrix right)  
  266.         {  
  267.             //左矩阵列数等于右矩阵的行数时才能执行相乘运算  
  268.             if (left.getCols() != right.getRows())  
  269.             {  
  270.                 throw new CMatrixException("error");  
  271.             }  
  272.   
  273.             Int32 lr = left.getRows();  
  274.             Int32 lc = left.getCols();  
  275.             Int32 rc = right.getCols();  
  276.   
  277.             CMatrix newMatrix = new CMatrix(lr, rc);  
  278.   
  279.             for (Int32 i = 0; i < lr; i++)  
  280.             {  
  281.                 for (Int32 j = 0; j < rc; j++)  
  282.                 {  
  283.                     for (Int32 z = 0; z < lc; z++)  
  284.                     {  
  285.                         newMatrix[i, j] = newMatrix[i, j] + left[i, z] * right[z, j];  
  286.                     }  
  287.                 }  
  288.             }  
  289.   
  290.             return newMatrix;  
  291.         }  
  292.   
  293.         /// <summary>  
  294.         /// 矩阵相乘  
  295.         /// </summary>  
  296.         /// <param name="right"></param>  
  297.         /// <returns></returns>  
  298.         public CMatrix multiply(CMatrix right)  
  299.         {  
  300.             return this * right;  
  301.         }  
  302.   
  303.         /// <summary>  
  304.         /// 矩阵旋转  
  305.         /// </summary>  
  306.         /// <returns></returns>  
  307.         public void rotate()  
  308.         {  
  309.             rotate(this.m_rotate);  
  310.         }  
  311.   
  312.         /// <summary>  
  313.         /// 矩阵旋转  
  314.         /// </summary>  
  315.         /// <param name="mode">旋转模式</param>  
  316.         /// <returns></returns>  
  317.         public void rotate(CRotateMode mode)  
  318.         {  
  319.             switch (mode)  
  320.             {  
  321.                 case CRotateMode.None:  
  322.                     break;  
  323.                 case CRotateMode.R90:  
  324.                     rotateR90();  
  325.                     break;  
  326.                 case CRotateMode.R180:  
  327.                     rotateR180();  
  328.                     break;  
  329.                 case CRotateMode.R270:  
  330.                     rotateR270();  
  331.                     break;  
  332.                 case CRotateMode.L90:  
  333.                     rotateL90();  
  334.                     break;  
  335.                 case CRotateMode.L180:  
  336.                     rotateL180();  
  337.                     break;  
  338.                 case CRotateMode.L270:  
  339.                     rotateL270();  
  340.                     break;  
  341.                 default:  
  342.                     break;  
  343.             }  
  344.         }  
  345.  
  346.         #region 矩阵旋转函数  
  347.   
  348.         /// <summary>  
  349.         /// 顺时针旋转90  
  350.         /// </summary>  
  351.         /// <returns></returns>  
  352.         private void rotateR90()  
  353.         {  
  354.             Int32 r = this.getRows();  
  355.             Int32 c = this.getCols();  
  356.   
  357.             CMatrix newMatrix = new CMatrix(c, r);  
  358.   
  359.             for (Int32 i = 0; i < c; i++)  
  360.             {  
  361.                 for (Int32 j = 0; j < r; j++)  
  362.                 {  
  363.                     newMatrix[i, j] = this[r - j - 1, i];  
  364.                 }  
  365.             }  
  366.   
  367.             this = newMatrix;  
  368.         }  
  369.         /// <summary>  
  370.         /// 顺时针旋转180  
  371.         /// </summary>  
  372.         /// <returns></returns>  
  373.         private void rotateR180()  
  374.         {  
  375.             Int32 r = this.getRows();  
  376.             Int32 c = this.getCols();  
  377.   
  378.             CMatrix newMatrix = new CMatrix(r, c);  
  379.   
  380.             for (Int32 i = 0; i < r; i++)  
  381.             {  
  382.                 for (Int32 j = 0; j < c; j++)  
  383.                 {  
  384.                     newMatrix[i, j] = this[r - i - 1, c - j - 1];  
  385.                 }  
  386.             }  
  387.   
  388.             this = newMatrix;  
  389.         }  
  390.         /// <summary>  
  391.         /// 顺时针旋转270  
  392.         /// </summary>  
  393.         /// <returns></returns>  
  394.         private void rotateR270()  
  395.         {  
  396.             Int32 r = this.getRows();  
  397.             Int32 c = this.getCols();  
  398.   
  399.             CMatrix newMatrix = new CMatrix(c, r);  
  400.   
  401.             for (Int32 i = 0; i < c; i++)  
  402.             {  
  403.                 for (Int32 j = 0; j < r; j++)  
  404.                 {  
  405.                     newMatrix[i, j] = this[j, c - i - 1];  
  406.                 }  
  407.             }  
  408.   
  409.             this = newMatrix;  
  410.         }  
  411.         /// <summary>  
  412.         /// 逆时针旋转90  
  413.         /// </summary>  
  414.         /// <returns></returns>  
  415.         private void rotateL90()  
  416.         {  
  417.             Int32 r = this.getRows();  
  418.             Int32 c = this.getCols();  
  419.   
  420.             CMatrix newMatrix = new CMatrix(c, r);  
  421.   
  422.             for (Int32 i = 0; i < c; i++)  
  423.             {  
  424.                 for (Int32 j = 0; j < r; j++)  
  425.                 {  
  426.                     newMatrix[i, j] = this[j, c - i - 1];  
  427.                 }  
  428.             }  
  429.   
  430.             this = newMatrix;  
  431.         }  
  432.         /// <summary>  
  433.         /// 逆时针旋转180  
  434.         /// </summary>  
  435.         /// <returns></returns>  
  436.         private void rotateL180()  
  437.         {  
  438.             Int32 r = this.getRows();  
  439.             Int32 c = this.getCols();  
  440.   
  441.             CMatrix newMatrix = new CMatrix(r, c);  
  442.   
  443.             for (Int32 i = 0; i < r; i++)  
  444.             {  
  445.                 for (Int32 j = 0; j < c; j++)  
  446.                 {  
  447.                     newMatrix[i, j] = this[r - i - 1, c - j - 1];  
  448.                 }  
  449.             }  
  450.   
  451.             this = newMatrix;  
  452.         }  
  453.         /// <summary>  
  454.         /// 逆时针旋转270  
  455.         /// </summary>  
  456.         /// <returns></returns>  
  457.         private void rotateL270()  
  458.         {  
  459.             Int32 r = this.getRows();  
  460.             Int32 c = this.getCols();  
  461.   
  462.             CMatrix newMatrix = new CMatrix(c, r);  
  463.   
  464.             for (Int32 i = 0; i < c; i++)  
  465.             {  
  466.                 for (Int32 j = 0; j < r; j++)  
  467.                 {  
  468.                     newMatrix[i, j] = this[r - j - 1, i];  
  469.                 }  
  470.             }  
  471.   
  472.             this = newMatrix;  
  473.         }  
  474.  
  475.         #endregion  
  476.   
  477.         /// <summary>  
  478.         /// 输出矩阵  
  479.         /// </summary>  
  480.         /// <returns></returns>  
  481.         public override string ToString()  
  482.         {  
  483.             StringBuilder strB = new StringBuilder();  
  484.             for (Int32 i = 0; i < getRows(); i++)  
  485.             {  
  486.                 for (Int32 j = 0; j < getCols(); j++)  
  487.                 {  
  488.                     strB.Append(m_matrix[i, j] + "  ");  
  489.                 }  
  490.                 strB.Append(Environment.NewLine);  
  491.             }  
  492.             return strB.ToString();  
  493.         }  
  494.     }  
  495.   
  496.     /// <summary>  
  497.     /// 自定义异常  
  498.     /// </summary>  
  499.     public class CMatrixException : Exception  
  500.     {  
  501.         public CMatrixException()  
  502.             : base()  
  503.         {  
  504.   
  505.         }  
  506.   
  507.         public CMatrixException(String msg)  
  508.             : base(msg)  
  509.         {  
  510.   
  511.         }  
  512.   
  513.         public String getMessage()  
  514.         {  
  515.             return base.Message;  
  516.         }  
  517.     }  
  518. }  
  关于矩阵的知识相信你们都比我了解,我数学知识少得不敢面对江东父老,以上存在什么不正确不准确的地方还请大家批评指正。对于没有接触过矩阵的同学来说,你只需要请教度娘谷哥即可!这里就简单介绍下矩阵的运算及矩阵的旋转:
   矩阵的运算:
       设有有矩阵A和B,满足A+B、A-B运算的条件是A的行数与B的行数相等,A的列数与B的列数相等;满足A*B运算的条件是A的列数与B的行数相等。
   矩阵的旋转:
             (A)                                                   (B)
       a11  a12                                        a31  a21  a11
       a21  a22   ===顺时针90度=>>  a32  a22  a12    ===>> B[i,j]=A[r-j-1,i]
       a31  a32  
            (A)                                                   (B)
       a11  a12                                         a32  a32 
       a21  a22   ===顺时针180度=>> a22  a21          ===>>  B[i,j]=A[r - i - 1, c - j - 1]
       a31  a32                                         a12  a11
           (A)                                                     (B)
       a11  a12                                         a12  a22  a32
       a21  a22   ===顺时针270度=>> a11  a21  a32  ===>> B[i,j]=A[j, c - i - 1]

       a31  a32         

逆时针大同小异,就不在描述了。其中r为矩阵行数,c为矩阵列数;i,j为矩阵某行某列。当然,这个旋转算法并不高效,只是满足旋转基本要求。              

   如此杂乱的、毫无设计的、堆砌出来的低质量代码摆在你们面前,相信大家都晕得差不多了,请原谅我的不经意,老衲不是故意的。休息一下,晕过后再我们再看看CDraw类的具体实现(准备好晕车药):
   ///CDraw类实现
[csharp] view plaincopyprint?
  1. using System;  
  2. using System.Text;  
  3.   
  4. namespace CGraphics  
  5. {  
  6.     /// <summary>  
  7.     /// 绘图类  
  8.     /// </summary>  
  9.     public sealed class CDraw  
  10.     {  
  11.         /// <summary>  
  12.         /// 绘制样式符号  
  13.         /// </summary>  
  14.         private CSymbol m_symbol;  
  15.         /// <summary>  
  16.         /// 绘制背景颜色  
  17.         /// </summary>  
  18.         private ConsoleColor m_backcolor;  
  19.   
  20.         /// <summary>  
  21.         /// 构造函数  
  22.         /// </summary>  
  23.         public CDraw()  
  24.         {  
  25.             this.m_symbol = CSymbol.RECT_EMPTY;  
  26.             this.m_backcolor = ConsoleColor.Black;  
  27.         }  
  28.  
  29.         #region 绘制字符串  
  30.   
  31.         /// <summary>  
  32.         /// 绘制字符串  
  33.         /// </summary>  
  34.         /// <param name="text">字符串</param>  
  35.         /// <param name="rect">字符串绘制范围</param>  
  36.         /// <param name="color">前景色</param>  
  37.         public void drawText(String text, CRect rect, ConsoleColor color)  
  38.         {  
  39.             rect.adjustRect(ref rect);  
  40.   
  41.             //不处理空字符串  
  42.             if (text == "")  
  43.             {  
  44.                 return;  
  45.             }  
  46.             //反色处理  
  47.             Console.BackgroundColor = this.m_backcolor;  
  48.             Console.ForegroundColor = this.m_backcolor == color ? (ConsoleColor)(15 - (Int32)this.m_backcolor) : color;  
  49.             Console.SetCursorPosition(rect.getX(), rect.getY());  
  50.   
  51.             //获取绘制范围字节数  
  52.             Int32 charLen = rect.getWidth() * rect.getHeight()<<1;  
  53.             //字符串字节数  
  54.             Int32 textLen = CText.getLength(text);  
  55.   
  56.             //截断字符串适应绘制范围  
  57.             text = CText.cutText(text, textLen > charLen ? charLen : textLen);  
  58.   
  59.             //字符串换行  
  60.             text = CText.lineBreakText(text, rect.getWidth());  
  61.   
  62.             String[] texts = text.Split(Environment.NewLine.ToCharArray());  
  63.   
  64.             Int32 i = 0;  
  65.             foreach (String s in texts)  
  66.             {  
  67.                 if (s != "")  
  68.                 {  
  69.                     Console.SetCursorPosition(rect.getX(), rect.getY() + i);  
  70.                     Console.Write(s);  
  71.                     i++;  
  72.                 }  
  73.             }  
  74.   
  75.             Console.SetCursorPosition(0, 0);  
  76.         }  
  77.   
  78.         /// <summary>  
  79.         /// 绘制字符串  
  80.         /// </summary>  
  81.         /// <param name="text">字符串</param>  
  82.         /// <param name="x">x</param>  
  83.         /// <param name="y">y</param>  
  84.         /// <param name="width">绘制范围宽度</param>  
  85.         /// <param name="height">绘制范围高度</param>  
  86.         /// <param name="color">颜色</param>  
  87.         public void drawText(String text, Int32 x, Int32 y, Int32 width, Int32 height, ConsoleColor color)  
  88.         {  
  89.             drawText(text, new CRect(x, y, width, height), color);  
  90.         }  
  91.   
  92.         /// <summary>  
  93.         /// 绘制字符串  
  94.         /// </summary>  
  95.         /// <param name="text">字符串</param>  
  96.         /// <param name="point">位置</param>  
  97.         /// <param name="width">绘制范围宽度</param>  
  98.         /// <param name="height">绘制范围高度</param>  
  99.         /// <param name="color">颜色</param>  
  100.         public void drawText(String text, CPoint point, Int32 width, Int32 height, ConsoleColor color)  
  101.         {  
  102.             drawText(text, new CRect(point, width, height), color);  
  103.         }  
  104.   
  105.         /// <summary>  
  106.         /// 绘制字符串  
  107.         /// </summary>  
  108.         /// <param name="text">字符串</param>  
  109.         /// <param name="x">x</param>  
  110.         /// <param name="y">y</param>  
  111.         /// <param name="size">绘制范围尺寸</param>  
  112.         /// <param name="color">颜色</param>  
  113.         public void drawText(String text, Int32 x, Int32 y, CSize size, ConsoleColor color)  
  114.         {  
  115.             drawText(text, new CRect(x, y, size), color);  
  116.         }  
  117.   
  118.         /// <summary>  
  119.         /// 绘制字符串  
  120.         /// </summary>  
  121.         /// <param name="text">字符串</param>  
  122.         /// <param name="point">位置</param>  
  123.         /// <param name="size">尺寸</param>  
  124.         /// <param name="color">颜色</param>  
  125.         public void drawText(String text, CPoint point, CSize size, ConsoleColor color)  
  126.         {  
  127.             drawText(text, new CRect(point, size), color);  
  128.         }  
  129.   
  130.         /// <summary>  
  131.         /// 绘制字符串  
  132.         /// </summary>  
  133.         /// <param name="text">字符串</param>  
  134.         /// <param name="x">光标列位置</param>  
  135.         /// <param name="y">光标行位置</param>  
  136.         /// <param name="color">前景色</param>  
  137.         public void drawText(String text, Int32 x, Int32 y, ConsoleColor color)  
  138.         {  
  139.             //不处理空字符串  
  140.             if (text == "")  
  141.             {  
  142.                 return;  
  143.             }  
  144.             //反色处理  
  145.             Console.BackgroundColor = this.m_backcolor;  
  146.             Console.ForegroundColor = this.m_backcolor == color ? (ConsoleColor)(15 - (Int32)this.m_backcolor) : color;  
  147.             Console.SetCursorPosition(x >= Console.WindowWidth ? Console.WindowWidth - 1 : x, y);  
  148.   
  149.             //绘制  
  150.             Console.Write(text);  
  151.   
  152.             Console.SetCursorPosition(0, 0);  
  153.         }  
  154.   
  155.         /// <summary>  
  156.         /// 绘制字符串  
  157.         /// </summary>  
  158.         /// <param name="text"></param>  
  159.         /// <param name="point"></param>  
  160.         /// <param name="color"></param>  
  161.         public void drawText(String text, CPoint point, ConsoleColor color)  
  162.         {  
  163.             drawText(text, point.getX(), point.getY(), color);  
  164.         }  
  165.  
  166.         #endregion  
  167.  
  168.         #region 绘制矩形  
  169.   
  170.         /// <summary>  
  171.         /// 绘制矩形  
  172.         /// </summary>  
  173.         /// <param name="rect">矩形</param>  
  174.         /// <param name="color">前景色</param>  
  175.         public void drawRect(CRect rect, ConsoleColor color)  
  176.         {  
  177.             //调整矩形  
  178.             rect.adjustRect(ref rect);  
  179.   
  180.             int x = rect.getX();  
  181.             int y = rect.getY();  
  182.             int width = rect.getWidth();  
  183.             int height = rect.getHeight();  
  184.   
  185.             //根据符号设置颜色  
  186.             if (m_symbol == CSymbol.DEFAULT)  
  187.             {  
  188.                 Console.BackgroundColor = color;  
  189.             }  
  190.             else  
  191.             {  
  192.                 Console.BackgroundColor = this.m_backcolor;  
  193.                 //反色处理  
  194.                 Console.ForegroundColor = this.m_backcolor == color ? (ConsoleColor)(15 - (Int32)this.m_backcolor) : color;  
  195.             }  
  196.   
  197.             //获取符号字符串  
  198.             String charSymbol = CSymbolHelper.getStringFromSymbol(m_symbol);  
  199.   
  200.             //绘制矩形列  
  201.             for (Int32 i = 0; i < width; i++)  
  202.             {  
  203.                 Int32 ix = x + (i <<1);  
  204.                 if (ix >= Console.WindowWidth)  
  205.                     ix = Console.WindowWidth - 1;  
  206.   
  207.                 Console.SetCursorPosition(ix, y);  
  208.                 Console.Write(charSymbol);  
  209.                 Console.SetCursorPosition(ix, y + height - 1);  
  210.                 Console.Write(charSymbol);  
  211.             }  
  212.   
  213.             //绘制矩形行  
  214.             for (Int32 i = 0; i < height; i++)  
  215.             {  
  216.                 Int32 ix = x + (width <<1) - 2;  
  217.                 if (ix >= Console.WindowWidth)  
  218.                     ix = Console.WindowWidth - 1;  
  219.   
  220.                 Console.SetCursorPosition(x, y + i);  
  221.                 Console.Write(charSymbol);  
  222.                 Console.SetCursorPosition(ix, y + i);  
  223.                 Console.Write(charSymbol);  
  224.             }  
  225.   
  226.             Console.SetCursorPosition(0, 0);  
  227.         }  
  228.   
  229.         /// <summary>  
  230.         /// 绘制矩形  
  231.         /// </summary>  
  232.         /// <param name="x">列</param>  
  233.         /// <param name="y">行</param>  
  234.         /// <param name="width">宽度</param>  
  235.         /// <param name="height">高度</param>  
  236.         /// <param name="color">颜色</param>  
  237.         public void drawRect(Int32 x, Int32 y, Int32 width, Int32 height, ConsoleColor color)  
  238.         {  
  239.             drawRect(new CRect(x, y, width, height), color);  
  240.         }  
  241.   
  242.         /// <summary>  
  243.         /// 绘制矩形  
  244.         /// </summary>  
  245.         /// <param name="point">位置</param>  
  246.         /// <param name="size">尺寸</param>  
  247.         /// <param name="color">颜色</param>  
  248.         public void drawRect(CPoint point, CSize size, ConsoleColor color)  
  249.         {  
  250.             drawRect(new CRect(point, size), color);  
  251.         }  
  252.   
  253.         /// <summary>  
  254.         /// 绘制矩形  
  255.         /// </summary>  
  256.         /// <param name="x">x</param>  
  257.         /// <param name="y">y</param>  
  258.         /// <param name="size">尺寸</param>  
  259.         /// <param name="color">颜色</param>  
  260.         public void drawRect(Int32 x, Int32 y, CSize size, ConsoleColor color)  
  261.         {  
  262.             drawRect(new CRect(x, y, size), color);  
  263.         }  
  264.   
  265.         /// <summary>  
  266.         /// 绘制矩形  
  267.         /// </summary>  
  268.         /// <param name="point">位置</param>  
  269.         /// <param name="width">宽</param>  
  270.         /// <param name="height">高</param>  
  271.         /// <param name="color">颜色</param>  
  272.         public void drawRect(CPoint point, Int32 width, Int32 height, ConsoleColor color)  
  273.         {  
  274.             drawRect(new CRect(point, width, height), color);  
  275.         }  
  276.  
  277.         #endregion  
  278.  
  279.         #region 填充矩形  
  280.   
  281.         /// <summary>  
  282.         /// 填充矩形  
  283.         /// </summary>  
  284.         /// <param name="rect">矩形</param>  
  285.         /// <param name="color">前景色</param>  
  286.         public void fillRect(CRect rect, ConsoleColor color)  
  287.         {  
  288.             //调整矩形  
  289.             rect.adjustRect(ref rect);  
  290.   
  291.             int x = rect.getX();  
  292.             int y = rect.getY();  
  293.             int width = rect.getWidth();  
  294.             int height = rect.getHeight();  
  295.   
  296.             //根据符号设置颜色  
  297.             if (m_symbol == CSymbol.DEFAULT)  
  298.             {  
  299.                 Console.BackgroundColor = color;  
  300.             }  
  301.             else  
  302.             {  
  303.                 Console.BackgroundColor = this.m_backcolor;  
  304.                 Console.ForegroundColor = this.m_backcolor == color ? (ConsoleColor)(15 - (Int32)this.m_backcolor) : color;  
  305.             }  
  306.   
  307.             //获取符号字符串  
  308.             String charSymbol = CSymbolHelper.getStringFromSymbol(m_symbol);  
  309.   
  310.             StringBuilder strb = new StringBuilder();  
  311.             for (Int32 i = 0; i < width; i++)  
  312.             {  
  313.                 strb.Append(charSymbol);  
  314.             }  
  315.   
  316.             for (Int32 i = 0; i < height; i++)  
  317.             {  
  318.                 Console.SetCursorPosition(x, y + i);  
  319.                 Console.Write(strb.ToString());  
  320.             }  
  321.   
  322.             Console.SetCursorPosition(0, 0);  
  323.         }  
  324.   
  325.         /// <summary>  
  326.         /// 填充矩形  
  327.         /// </summary>  
  328.         /// <param name="x">列</param>  
  329.         /// <param name="y">行</param>  
  330.         /// <param name="width">宽度</param>  
  331.         /// <param name="height">高度</param>  
  332.         /// <param name="color">颜色</param>  
  333.         public void fillRect(Int32 x, Int32 y, Int32 width, Int32 height, ConsoleColor color)  
  334.         {  
  335.             fillRect(new CRect(x, y, width, height), color);  
  336.         }  
  337.   
  338.         /// <summary>  
  339.         /// 填充矩形  
  340.         /// </summary>  
  341.         /// <param name="point">位置</param>  
  342.         /// <param name="size">尺寸</param>  
  343.         /// <param name="color">颜色</param>  
  344.         public void fillRect(CPoint point, CSize size, ConsoleColor color)  
  345.         {  
  346.             fillRect(new CRect(point, size), color);  
  347.         }  
  348.   
  349.         /// <summary>  
  350.         /// 填充矩形  
  351.         /// </summary>  
  352.         /// <param name="x">x</param>  
  353.         /// <param name="y">y</param>  
  354.         /// <param name="size">尺寸</param>  
  355.         /// <param name="color">颜色</param>  
  356.         public void fillRect(Int32 x, Int32 y, CSize size, ConsoleColor color)  
  357.         {  
  358.             fillRect(new CRect(x, y, size), color);  
  359.         }  
  360.   
  361.         /// <summary>  
  362.         /// 填充矩形  
  363.         /// </summary>  
  364.         /// <param name="point">位置</param>  
  365.         /// <param name="width">宽</param>  
  366.         /// <param name="height">高</param>  
  367.         /// <param name="color">颜色</param>  
  368.         public void fillRect(CPoint point, Int32 width, Int32 height, ConsoleColor color)  
  369.         {  
  370.             fillRect(new CRect(point, width, height), color);  
  371.         }  
  372.  
  373.         #endregion  
  374.   
  375.         /// <summary>  
  376.         /// 用指定背景色清屏  
  377.         /// </summary>  
  378.         /// <param name="color"></param>  
  379.         public void clear(ConsoleColor color)  
  380.         {  
  381.             this.m_symbol = CSymbol.DEFAULT;  
  382.             this.m_backcolor = color;  
  383.             fillRect(0, 0, Console.WindowWidth>>1, Console.WindowHeight, color);  
  384.         }  
  385.   
  386.         /// <summary>  
  387.         /// 设置背景颜色  
  388.         /// </summary>  
  389.         /// <param name="color"></param>  
  390.         public void setBackcolor(ConsoleColor color)  
  391.         {  
  392.             this.m_backcolor = color;  
  393.         }  
  394.   
  395.         /// <summary>  
  396.         /// 获取背景颜色  
  397.         /// </summary>  
  398.         /// <returns></returns>  
  399.         public ConsoleColor getBackcolor()  
  400.         {  
  401.             return this.m_backcolor;  
  402.         }  
  403.   
  404.         /// <summary>  
  405.         /// 设置控制台绘制符号  
  406.         /// </summary>  
  407.         /// <param name="symbol"></param>  
  408.         public void setDrawSymbol(CSymbol symbol)  
  409.         {  
  410.             this.m_symbol = symbol;  
  411.         }  
  412.   
  413.         /// <summary>  
  414.         /// 获取控制台绘制符号  
  415.         /// </summary>  
  416.         /// <returns></returns>  
  417.         public CSymbol getDrawSymbol()  
  418.         {  
  419.             return this.m_symbol;  
  420.         }  
  421.     }  
  422. }  
  绘图类相对比较简单,只有绘制字符串、绘制矩形和填充矩形的功能,实现原理不过于先设定控制台输出颜色,然后定位光标的位置,最后循环符号的输出,每次输出后Console.SetCursorPosition(0, 0)定位画面,防止滚动条的抖动;其中一些操作进行了反色处理,意思是如果输出的文本颜色或符号颜色与控制台背景色相同,则把文本和符号进行反色处理,防止无意的操作导致画面被背景掩盖。此绘图类相对比较粗糙,但基本满足绘图要求。

三、绘图模块测试

  终于摆脱了实现部分,来点洗洗眼的东西,测试绘制图形。在绘制图形之前,我们也有必要测试其他部分,比如矩形、点、距阵等结构的基本运算是否正确。此模块相对来说是独立的,所以我们可以单独测试它而不使用上章的游戏测试类TestGame。为了清晰简单,我们直接在Main函数中测试绘图模块。
///Program实现
[csharp] view plaincopyprint?
  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             //初始化一个绘图对象  
  6.             CDraw draw = new CDraw();  
  7.   
  8.             //绘制字符串  
  9.             draw.drawText("测试点结构", 2, 1, ConsoleColor.Blue);  
  10.             //初始化一个点point1  
  11.             CPoint point1 = new CPoint(1, 2);  
  12.             //初始化一个点point2  
  13.             CPoint point2 = new CPoint(3, 4);  
  14.             //绘制point1  
  15.             draw.drawText("点1:" + point1, 4, 2, ConsoleColor.White);  
  16.             //绘制point2  
  17.             draw.drawText("点2:" + point2, 4, 3, ConsoleColor.White);  
  18.             //绘制两点相加  
  19.             draw.drawText("点1+点2:" + (point1 + point2), 4, 4, ConsoleColor.White);  
  20.             //绘制两点相减  
  21.             draw.drawText("点1-点2:" + (point1 - point2), 4, 5, ConsoleColor.White);  
  22.             //绘制两点是否相等  
  23.             draw.drawText("点1==点2:" + (point1 == point2), 4, 6, ConsoleColor.White);  
  24.             //绘制两点是否不等  
  25.             draw.drawText("点1!=点2:" + (point1 != point2), 4, 7, ConsoleColor.White);  
  26.   
  27.   
  28.             //绘制字符串  
  29.             draw.drawText("测试矩形结构", 1, 9, 2, 3, ConsoleColor.Red);  
  30.             //初始化一个矩形  
  31.             CRect rect = new CRect(2, 2, 5, 8);  
  32.             draw.drawText("矩形:" + rect, 4, 12, ConsoleColor.White);  
  33.             //缩放矩形  
  34.             rect.inflate(1, 1);  
  35.             draw.drawText("矩形缩放[1,1]:" + rect, 4, 13, ConsoleColor.White);  
  36.   
  37.             //设置绘制符号  
  38.             draw.setDrawSymbol(CSymbol.RECT_SOLID);  
  39.             draw.drawRect(15, 0, 25, 25, ConsoleColor.White);  
  40.             //绘制字符串  
  41.             draw.drawText("测试矩阵结构", 32, 1, ConsoleColor.Green);  
  42.   
  43.             //初始化一个矩阵  
  44.             CMatrix matrix1 = new CMatrix(3, 3);  
  45.             matrix1[0, 0] = 1;  
  46.             matrix1[2, 2] = 3;  
  47.             matrix1[0, 1] = 1;  
  48.             //初始化一个矩阵  
  49.             CMatrix matrix2 = new CMatrix(new Int32[3, 3]  
  50.             {  
  51.                 {1,2,3},  
  52.                 {4,5,6},  
  53.                 {7,8,9}  
  54.             });  
  55.             //初始化一个矩阵  
  56.             CMatrix matrix3 = new CMatrix(new Int32[2, 3]  
  57.             {  
  58.                 {1,2,3},  
  59.                 {4,5,6}  
  60.             });  
  61.             //绘制矩阵  
  62.             draw.drawText("矩阵1:", 32, 2, ConsoleColor.White);  
  63.             draw.drawText(matrix1.ToString(), 16, 3, 5, 3, ConsoleColor.White);  
  64.             //绘制矩阵  
  65.             draw.drawText("矩阵2:", 42, 2, ConsoleColor.White);  
  66.             draw.drawText(matrix2.ToString(), 21, 3, 5, 3, ConsoleColor.White);  
  67.             //绘制矩阵  
  68.             draw.drawText("矩阵3:", 52, 2, ConsoleColor.White);  
  69.             draw.drawText(matrix3.ToString(), 26, 3, 5, 3, ConsoleColor.White);  
  70.   
  71.             //绘制矩阵  
  72.             draw.drawText("矩阵1+矩阵2:", 32, 7, ConsoleColor.White);  
  73.             draw.drawText((matrix1 + matrix2).ToString(), 16, 8, 5, 3, ConsoleColor.White);  
  74.             //绘制矩阵  
  75.             draw.drawText("矩阵2-矩阵1:", 48, 7, ConsoleColor.White);  
  76.             draw.drawText((matrix2 - matrix1).ToString(), 24, 8, 5, 3, ConsoleColor.White);  
  77.             //绘制矩阵  
  78.             draw.drawText("矩阵3*矩阵2:", 64, 7, ConsoleColor.White);  
  79.             draw.drawText((matrix3 * matrix2).ToString(), 32, 8, 7, 3, ConsoleColor.White);  
  80.   
  81.             //顺时针旋转矩阵90度   
  82.             matrix2.rotate(CRotateMode.R90);  
  83.             draw.drawText("顺时针90度旋转矩阵2:", 32, 12, ConsoleColor.White);  
  84.             draw.drawText(matrix2.ToString(), 16, 13,5,3, ConsoleColor.White);  
  85.   
  86.             //为了测试先恢复矩阵状态  
  87.             matrix2.rotate(CRotateMode.L90);  
  88.             //顺时针旋转矩阵180度  
  89.             matrix2.rotate(CRotateMode.R180);  
  90.             draw.drawText("顺时针180度旋转矩阵2:", 54, 12, ConsoleColor.White);  
  91.             draw.drawText(matrix2.ToString(), 27, 13, 5, 3, ConsoleColor.White);  
  92.   
  93.             //为了测试先恢复矩阵状态  
  94.             matrix2.rotate(CRotateMode.L180);  
  95.             //顺时针旋转矩阵270度  
  96.             matrix2.rotate(CRotateMode.R270);  
  97.             draw.drawText("顺时针270度旋转矩阵2:", 32, 17, ConsoleColor.White);  
  98.             draw.drawText(matrix2.ToString(), 16, 18, 5, 3, ConsoleColor.White);  
  99.   
  100.             matrix3.rotate(CRotateMode.L90);  
  101.             draw.drawText("逆时针90度旋转矩阵3:", 54, 17, ConsoleColor.White);  
  102.             draw.drawText(matrix3.ToString(), 27, 18, 4, 4, ConsoleColor.White);  
  103.   
  104.             //设置绘制符号  
  105.             draw.setDrawSymbol(CSymbol.RECT_EMPTY);  
  106.             //填充矩形  
  107.             draw.fillRect(2,15,5,5,ConsoleColor.Yellow);  
  108.             //设置绘制符号  
  109.             draw.setDrawSymbol(CSymbol.RHOMB_SOLID);  
  110.             //填充矩形  
  111.             draw.fillRect(3, 16, 2, 3, ConsoleColor.Blue);  
  112.             //设置绘制符号  
  113.             draw.setDrawSymbol(CSymbol.RECT_SOLID);  
  114.             //填充矩形  
  115.             draw.fillRect(7, 17, 4, 3, ConsoleColor.Blue);  
  116.   
  117.             //绘制一段文字  
  118.             draw.drawText("C#游戏编程:《控制台小游戏系列》之《四、游戏渲染模块》",2,21,12,5,ConsoleColor.Cyan);  
  119.   
  120.             Console.ReadLine();  
  121.         }  
  122.     }  
  测试结果截图:
  特别要注意绘制字符串的两个不同方法,不指定字符串绘制范围的函数的绘制坐标X是按每字符设定的,而指定字符串绘制范围的函数绘制坐标X按每字设定(2字符),比如前者要在X=30处绘制,当转换成后者时X=30/2=15。

五、结语

  此章完成了绘图模块,可以完成基本的绘图操作,对于控制台类型的小游戏来说,这里提供的绘图操作已满足一定要求,然而绘图模块在设计、实现方面还很粗糙,需要以后逐步完善。在下一章中,我们将继续完善游戏框架类,让框架拥有操作绘图的能力。
原创粉丝点击