public class DotNetPlatform
{
private int _size;
private Random _random;
private DataTable _dataTable;
private string[] symbols = new string[] { "+", "-", "*" };
/// <summary>
/// 构造函数
/// </summary>
/// <param name="size">图片高度</param>
public DotNetPlatform(int size=35)
{
_size = size;
_random = new Random();
_dataTable=new DataTable();
}
/// <summary>
/// 获取验证码
/// </summary>
/// <param name="result">返回四则运算结果</param>
/// <param name="digit">参与四则运算的数字个数,默认3</param>
/// <param name="randomNumberRangeMin">参与四则运算随机数字最小值</param>
/// <param name="randomNumberRangeMax">参与四则运算随机数字最大值</param>
/// <returns>返回图片的byte数组</returns>
public byte[] GenerateImg(out string result, int digit=3,int randomNumberRangeMin=0, int randomNumberRangeMax=10)
{
if (digit < 2)
digit = 3;
StringBuilder sb = new StringBuilder();
for (int i = 0; i < digit; i++)
{
sb.Append(_random.Next(randomNumberRangeMin, randomNumberRangeMax) + symbols[_random.Next(0, symbols.Length)]);
}
sb.Remove(sb.Length - 1, 1);
#region 不需要括号干掉下面代码
if (digit >= 3)
{
int[] num=new int[digit-1];
int j = 0,index;
string flag;
string code = sb.ToString();
for (int i = 0; i < code.Length; i++)
{
flag = symbols.LastOrDefault(t => t == code[i].ToString());
if (flag!=null)
num[j++] = i;
}
j = _random.Next(0, num.Length);
index =num[j];
if(j!=0)
index = num[j-1]+1;
else
index = j;
sb.Insert(index,"(");
if (j == num.Length-1)
index = code.Length+1;
else
index = num[j+1]+1;
sb.Insert(index, ")");
}
#endregion
result = Calculate(sb.ToString());
sb.Replace("*", "×");
sb.Append("=?");
return GenerateImg(sb.ToString());
}
private string Calculate(string operationExpre)
{
return _dataTable.Compute(operationExpre, null).ToString();
}
/// <summary>
/// 生成验证码图片
/// </summary>
/// <param name="code"></param>
/// <returns></returns>
private byte[] GenerateImg(string code)
{
Bitmap image = new Bitmap(_size* ((int)(code.Length*0.6)), _size);//code.Length * 15
Graphics g = Graphics.FromImage(image);
// 定义验证码字体
Font font = new Font("黑体", 12, (FontStyle.Bold | FontStyle.Italic));
// 干扰线
Pen penLine = new Pen(Color.FromArgb(186, 212, 231));
// 定义验证码的刷子,这里采用渐变的方式,颜色可自定义
LinearGradientBrush brush = new LinearGradientBrush(new Rectangle(0, 0, image.Width, image.Height), Color.FromArgb(67, 93, 230), Color.FromArgb(70, 128, 228), 1.5f, true);
// 边框
Pen penFrame = new Pen(Color.FromArgb(93, 142, 228));
// 保存图片数据
MemoryStream stream = new MemoryStream();
try
{
// 清空图片背景色
g.Clear(Color.White);
// 增加背景干扰线
for (int i = 0; i < 30; i++)
{
int x1 = _random.Next(image.Width);
int x2 = _random.Next(image.Width);
int y1 = _random.Next(image.Height);
int y2 = _random.Next(image.Height);
// 颜色可自定义
g.DrawLine(penLine, x1, y1, x2, y2);
}
// 增加干扰点
for (int i = 0; i < 100; i++)
{
int x = _random.Next(image.Width);
int y = _random.Next(image.Height);
// 颜色可自定义
image.SetPixel(x, y, Color.FromArgb(_random.Next()));
}
// 将验证码写入图片
int wx = (image.Width >> 2) - (code.Length );
if (_random.Next(0, 2) == 0)
wx += _random.Next(1, 10);
else
wx -= _random.Next(1, 10);
int hy = (image.Height >> 1) - (code.Length >> 1)-3;
g.DrawString(code, font, brush,wx,hy);
// 图片边框
g.DrawRectangle(penFrame, 0, 0, image.Width - 1, image.Height - 1);
image.Save(stream, ImageFormat.Jpeg);
return stream.ToArray();
}
catch(Exception ex)
{
throw ex;
}
finally
{
stream.Dispose();
penFrame.Dispose();
brush.Dispose();
penLine.Dispose();
font.Dispose();
g.Dispose();
image.Dispose();
}
}
}
调用:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
DotNetPlatform dotNetp =new DotNetPlatform();
private void button1_Click(object sender, EventArgs e)
{
var img= dotNetp.GenerateImg(out string result);
this.pictureBox1.Image = Image.FromStream(new MemoryStream(img));
this.label1.Text = result;
}
}
计算数字结果采用下面这种方法更快
private int Calculate(string s)
{
char preSign = '+';
int num = 0;
int n = s.Length;
Stack<int> stack = new Stack<int>(n);
for (int i = 0; i < n; ++i)
{
if (char.IsDigit(s[i]))
{
num = num * 10 + s[i] - '0';
}
if (!char.IsDigit(s[i]) && s[i] != ' ' || i == n - 1)
{
stack.Push(preSign switch
{
'+' => num,
'-' => -num,
'*' => stack.Pop() * num,
'/' => stack.Pop() / num
});
preSign = s[i];
num = 0;
}
}
int ans = 0;
while (stack.Count > 0)
{
ans += stack.Pop();
}
stack.Clear();
stack = null;
return ans;
}