人工智能作业——八数码问题 BFS+A* C# WindowsFormApplication
2015-01-21 12:28
411 查看
C#界面程序写起来和C++还是有很多区别的,比如在C++里重载运算符在C#里要重载Objective类的函数,而且C#的API居然没有优先队列。
这里面状态判重是用哈希表判重。A*算法用的是距离和,启发能力比不在位更强。
其实HCI方面还有很多可以改进的地方,水过验收之后就懒得改了><
Form1.cs
ChooseStart.cs
目标状态输入窗口
ChooseEnd.cs
这里面状态判重是用哈希表判重。A*算法用的是距离和,启发能力比不在位更强。
其实HCI方面还有很多可以改进的地方,水过验收之后就懒得改了><
Form1.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; using System.Diagnostics; namespace EightDigitPuzzle { public partial class Form1 : Form { string[] figpath; int[] pic; int[] now; int[] tmpst; Puzzle sample; int subindex; public Form1() { InitializeComponent(); figpath = new string[9];//保存PictureBox的图片路径 pic = new int[2]; now = new int[2]; tmpst = new int[9]; sample = new Puzzle(); subindex = 0; string p = "C:\\Users\\dell\\Documents\\Visual Studio 2008\\Projects\\EightDigitPuzzle\\NumberJpg\\"; for (int i = 0; i < 9; i++) { figpath[i] = p + i.ToString() + ".jpg"; } } public void LoadFig(int n, int f)//给PictureBox加载图片 { switch (n) { case 0: pictureBox1.Load(figpath[f]); break; case 1: pictureBox2.Load(figpath[f]); break; case 2: pictureBox3.Load(figpath[f]); break; case 3: pictureBox4.Load(figpath[f]); break; case 4: pictureBox5.Load(figpath[f]); break; case 5: pictureBox6.Load(figpath[f]); break; case 6: pictureBox7.Load(figpath[f]); break; case 7: pictureBox8.Load(figpath[f]); break; case 8: pictureBox9.Load(figpath[f]); break; } } public void ShowFigure(int[] sta)//在PictureBox中显示图片 { for (int i = 0; i < 9; i++) { LoadFig(i, sta[i]); } } public string getfigpath(int pic)//获取第i个PictureBox的图片路径 { string path = ""; switch (pic) { case 0: path = pictureBox1.ImageLocation; break; case 1: path = pictureBox2.ImageLocation; break; case 2: path = pictureBox3.ImageLocation; break; case 3: path = pictureBox4.ImageLocation; break; case 4: path = pictureBox5.ImageLocation; break; case 5: path = pictureBox6.ImageLocation; break; case 6: path = pictureBox7.ImageLocation; break; case 7: path = pictureBox8.ImageLocation; break; case 8: path = pictureBox9.ImageLocation; break; } return path; } public void dynamicshow(int[] pic, int[] now)//根据result[i]中s数组的值改变PictureBox中对应的图片 { if (timer1.Enabled == false) { string oldpath = getfigpath(pic[0]); string newpath = getfigpath(pic[1]); string oldfig = figpath[now[0]]; string newfig = figpath[now[1]]; switch (pic[0]) { case 0: pictureBox1.Load(newfig); break; case 1: pictureBox2.Load(newfig); break; case 2: pictureBox3.Load(newfig); break; case 3: pictureBox4.Load(newfig); break; case 4: pictureBox5.Load(newfig); break; case 5: pictureBox6.Load(newfig); break; case 6: pictureBox7.Load(newfig); break; case 7: pictureBox8.Load(newfig); break; case 8: pictureBox9.Load(newfig); break; } switch (pic[1]) { case 0: pictureBox1.Load(oldfig); break; case 1: pictureBox2.Load(oldfig); break; case 2: pictureBox3.Load(oldfig); break; case 3: pictureBox4.Load(oldfig); break; case 4: pictureBox5.Load(oldfig); break; case 5: pictureBox6.Load(oldfig); break; case 6: pictureBox7.Load(oldfig); break; case 7: pictureBox8.Load(oldfig); break; case 8: pictureBox9.Load(oldfig); break; } } } private void button1_Click(object sender, EventArgs e) { this.ShowFigure(tmpst); sample = new Puzzle(); sample.run_bfs();//output message box after form changed. if (sample.sol == true) { this.subindex = 0; timer3.Enabled = true; } //dynamicshow(pic, now); //MessageBox.Show(i.ToString()); // System.Threading.Thread.Sleep(1000); } private void button2_Click(object sender, EventArgs e) { this.ShowFigure(tmpst); sample = new Puzzle(); sample.run_astar_bfs(); if (sample.sol == true) { this.subindex = 0; timer3.Enabled = true; } } private void button3_Click(object sender, EventArgs e) { ChooseStart st = new ChooseStart();//弹出初始状态的输入窗口 DialogResult dr = st.ShowDialog(); //int[] tmpst = new int[9]; for (int i = 0; i < 9; i++) { //tmpst[i] = new State(); tmpst[i] = st.start[i]; } if (dr == DialogResult.Yes)//如果用户确认输入,则在界面中显示初始状态的八个数字 { st.Dispose(); ShowFigure(tmpst); } } private void button4_Click(object sender, EventArgs e) { ChooseEnd ed = new ChooseEnd();//弹出输入目标状态的窗口 DialogResult dr = ed.ShowDialog(); if (dr == DialogResult.Yes)//用户确认输入,则返回 { ed.Dispose(); } } private void timer1_Tick(object sender, EventArgs e)//使得窗体越来越透明 { this.Opacity = Math.Max(this.Opacity - 0.05, 0.05); if (this.Opacity == 0.05) { timer1.Enabled = false; timer2.Enabled = true;//是窗体慢慢恢复可见 //dynamicshow(pic, now); } } private void pictureBox1_Click(object sender, EventArgs e) { } private void timer2_Tick(object sender, EventArgs e)//使得窗体透明度慢慢减小 { timer1.Enabled = false; this.Opacity = Math.Min(this.Opacity + 0.05, 1); if (this.Opacity >= 1) { timer2.Enabled = false; } } private void timer3_Tick(object sender, EventArgs e)//根据result数组的结果,动态最优解的路径 { int idx = 0; Array.Clear(pic, 0, 2); Array.Clear(now, 0, 2); for (int j = 0; j < 9; j++) { if (sample.result[subindex].s[j] != sample.result[subindex + 1].s[j])//找出result数组中相邻两个状态中变化的两个格子 { pic[idx] = j; now[idx++] = sample.result[subindex].s[j]; } } subindex++; dynamicshow(pic, now);//改变PictureBox中对应的图片 if (subindex == (sample.totalstep - 1))//result数组遍历结束,则timer3控件停止工作 { timer3.Enabled = false; } timer1.Enabled = true;//使窗体显示透明变化的效果 } } public partial class State { public int[] s;//存储棋盘(9个整数) public int pre;//记录前驱节点的下标 public int dis;//记录走过的步数 public int index;//记录下标 //public int maxn; public int f;//A*算法中的f值 public State()//构造函数 { pre = 0; dis = 0; index = 0; f = 0; s = new int[9]; Array.Clear(s, 0, 9); } public State(int[] ss, int p, int d, int id) { s = new int[9]; Array.Clear(s, 0, 9); for (int i = 0; i < 9; i++) { s[i] = ss[i]; } pre = p; dis = d; index = id; f = 0; } public static bool operator <(State a, State b)//重载<运算符,将九个数字映射成一个九位整数 { int numa = 0; int numb = 0; for (int i = 0; i < 9; i++) { numa += numa * 10 + a.s[i]; numb += numb * 10 + b.s[i]; } return numa < numb; } public static bool operator >(State a, State b)//重载>运算符,将九个数字映射成一个九位整数 { int numa = 0; int numb = 0; for (int i = 0; i < 9; i++) { numa += numa * 10 + a.s[i]; numb += numb * 10 + b.s[i]; } return numa > numb; } public static bool operator ==(State a, State b)//重载==运算符 { for (int i = 0; i < 9; i++) { if (a.s[i] != b.s[i]) { return false; } } return true; } public static bool operator !=(State a, State b)//重载!=运算符 { for (int i = 0; i < 9; i++) { if (a.s[i] != b.s[i]) { return true; } } return false; } public override bool Equals(System.Object obj)//重载Object类中的Equals函数(为了对State类使用HashSet) { if (obj == null) return false; State p = obj as State; if ((System.Object)p == null) { return false; } return this == p; } public bool Equals(State p) { if ((object)p == null) { return false; } return this == p; } public override int GetHashCode()//重载Object类中的GetHashCode函数(为了对State类使用HashSet) { int num = 0; for (int i = 0; i < 9; i++) { num += num * 10 + s[i]; } return num; } public void print()//将该状态输出到.txt文件中(为了方便debug) { StreamWriter sw = new StreamWriter("C:\\Users\\dell\\Documents\\Visual Studio 2008\\Projects\\EightDigitPuzzle\\EightDigitPuzzle\\testoutput.txt", true); for (int i = 0; i < 9; i++) { sw.Write(s[i].ToString() + " "); if ((i + 1) % 3 == 0) { sw.WriteLine(); } } sw.WriteLine(); sw.Close(); } } public class PriorityQueue<T>//优先队列 { IComparer<T> comparer; T[] heap; public int Count { get; private set; } public PriorityQueue() : this(null) { } public PriorityQueue(int capacity) : this(capacity, null) { } public PriorityQueue(IComparer<T> comparer) : this(16, comparer) { } public PriorityQueue(int capacity, IComparer<T> comparer) { this.comparer = (comparer == null) ? Comparer<T>.Default : comparer; this.heap = new T[capacity]; } public void Push(T v)//入队操作 { if (Count >= heap.Length) Array.Resize(ref heap, Count * 2); heap[Count] = v; SiftUp(Count++); } public T Pop()//出队操作 { var v = Top(); heap[0] = heap[--Count]; if (Count > 0) SiftDown(0); return v; } public T Top()//返回队列首个元素 { if (Count > 0) return heap[0]; throw new InvalidOperationException("优先队列为空"); } void SiftUp(int n) { var v = heap ; for (var n2 = n / 2; n > 0 && comparer.Compare(v, heap[n2]) > 0; n = n2, n2 /= 2) heap = heap[n2]; heap = v; } void SiftDown(int n)//筛降函数 { var v = heap ; for (var n2 = n * 2; n2 < Count; n = n2, n2 *= 2) { if (n2 + 1 < Count && comparer.Compare(heap[n2 + 1], heap[n2]) > 0) n2++; if (comparer.Compare(v, heap[n2]) >= 0) break; heap = heap[n2]; } heap = v; } } class SortState : IComparer<State>//自定义比较器,该优先队列(大顶堆)的优先序是按照f的大小排序 { #region IComparer Members public int Compare(State x, State y) { return y.f.CompareTo(x.f); } #endregion } public partial class Puzzle { public int maxn;//状态数目的最大值 public State[] save;//closed表,存放已经扩展的节点 public State finalstate;//最终状态 public HashSet<State> vis;//用HashSet泛型类判断状态是否重复,重复的状态不必再扩展 public int[] dx;//x坐标可扩展的方向 public int[] dy;//y坐标可扩展的方向 public int Index;//扩展的节点的编号 public int[] c;//归并排序求逆序数用到的数组 public int cnt;//归并排序求逆序数用到的返回值 public State[] result;//保存最优解的路径 public int totalstep;//最优解的步数 public bool sol;//标记该问题是否有解 FileStream fs;//用于在程序运行前清空文件 public Puzzle()//构造函数 { maxn = 362880;//状态数最多有9!个 save = new State[maxn]; vis = new HashSet<State>(); c = new int[maxn]; totalstep = 0; result = new State[maxn]; sol = true; for (int i = 0; i < maxn; i++) { save[i] = new State(); result[i] = new State(); } dx = new int[4]; dy = new int[4]; dx[0] = -1; dx[1] = 1; dx[2] = 0; dx[3] = 0; dy[0] = 0; dy[1] = 0; dy[2] = -1; dy[3] = 1; Index = 0; vis.Clear(); fs = new FileStream("C:\\Users\\dell\\Documents\\Visual Studio 2008\\Projects\\EightDigitPuzzle\\EightDigitPuzzle\\testoutput.txt", FileMode.OpenOrCreate, FileAccess.Write); fs.SetLength(0);//清空input.txt文件 fs.Close(); } public int ManhattanDis(State a)//A*算法中计算曼哈顿距离和 { int ret = 0; for (int i = 0; i < 9; i++) { int tmp = finalstate.s[i]; for (int j = 0; j < 9; j++) { if (a.s[j] == tmp) { ret += Math.Abs(i / 3 - j / 3) + Math.Abs(i % 3 - j % 3); break; } } } return ret; } public void input()//从input.txt文件中读入数据 { Index = 0; vis.Clear(); int[] a = new int[9]; //MessageBox.Show(a.Length.ToString()); StreamReader sr = new StreamReader("C:\\Users\\dell\\Documents\\Visual Studio 2008\\Projects\\EightDigitPuzzle\\EightDigitPuzzle\\input.txt"); for (int i = 0; i < 9; i++)//输入初始状态 { a[i] = Convert.ToInt32(sr.ReadLine()); //a[i] = 1; } State tmp = new State(a, -1, 0, 0); //tmp.f = tmp.dis + ManhattanDis(tmp); save[Index++] = tmp;//在save数组中先放入初始节点 vis.Add(save[0]);//标记初始节点已访问 Array.Clear(a, 0, 9); for (int i = 0; i < 9; i++)//输入目标状态 { a[i] = Convert.ToInt32(sr.ReadLine()); } finalstate = new State(a, 0, 0, 0); save[0].f = save[0].dis + ManhattanDis(save[0]); sr.Close(); } public bool try_to_insert(State a)//判断该状态之前是否出现过 { if (vis.Contains(a)) { return false; } vis.Add(a);//若该状态没出现过,加入HashSet中 return true; } public int bfs() { Queue<State> q = new Queue<State>();//用队列存储open表 while (q.Count != 0) q.Dequeue(); q.Enqueue(save[0]); State tmp = new State(); while (q.Count != 0) { tmp = q.Peek(); q.Dequeue(); if (tmp == finalstate)//到达目标状态,则返回在save数组中对应的下标 { return tmp.index; } int z = 0; for (z = 0; z < 9; z++) { if (tmp.s[z] == 0)//找出0所在的位置 { break; } } int x = z / 3;//计算0的行坐标 int y = z % 3;//计算0的列坐标 for (int d = 0; d < 4; d++) { int newx = x + dx[d];//计算新的行坐标 int newy = y + dy[d];//计算新的列坐标 int newz = newx * 3 + newy; if (newx < 0 || newx >= 3 || newy < 0 || newy >= 3) continue;//坐标越界,则不扩展这个节点 State news = new State(); for (int i = 0; i < 9; i++) { news.s[i] = tmp.s[i]; } news.s[newz] = tmp.s[z];//0和newz的位置互换 news.s[z] = tmp.s[newz]; news.dis = tmp.dis + 1;//该节点的步数是tmp的步数+1 news.pre = tmp.index;//该节点的前驱是tmp news.index = Index; //StreamWriter sw = new StreamWriter("C:\\Users\\dell\\Documents\\Visual Studio 2008\\Projects\\EightDigitPuzzle\\EightDigitPuzzle\\testout.txt", true); //bool b=try_to_insert(news); //sw.Write(b.ToString() + " "); //sw.Close(); if (try_to_insert(news))//如果该状态之前未出现过,则扩展该节点 { save[Index++] = news; q.Enqueue(news); } } } return 0; } int astar_bfs() { PriorityQueue<State> q = new PriorityQueue<State>(maxn, new SortState());//用优先队列存储open表(f值越小越优先) while (q.Count != 0) q.Pop(); q.Push(save[0]); State tmp = q.Top(); while (q.Count != 0) { tmp = q.Pop(); if (tmp == finalstate)//到达目标状态,则返回在save数组中对应的下标 { return tmp.index; } int z = 0; for (z = 0; z < 9; z++)//找出0所在的位置 { if (tmp.s[z] == 0) { break; } } int x = z / 3;//计算0的行坐标 int y = z % 3;//计算0的列坐标 for (int d = 0; d < 4; d++) { int newx = x + dx[d];//计算新的行坐标 int newy = y + dy[d];//计算新的列坐标 int newz = newx * 3 + newy; if (newx < 0 || newx >= 3 || newy < 0 || newy >= 3) continue;//坐标越界,则不扩展这个节点 State news = new State(); for (int i = 0; i < 9; i++) { news.s[i] = tmp.s[i]; } news.s[newz] = tmp.s[z];//0和newz的位置互换 news.s[z] = tmp.s[newz]; news.dis = tmp.dis + 1;//该节点的步数是tmp的步数+1 news.index = Index; news.pre = tmp.index;//该节点的前驱是tmp news.f = news.dis + ManhattanDis(news);//该节点的f值是该节点走过的步数+与目标状态的距离和 if (try_to_insert(news))//如果该状态之前未出现过,则扩展该节点 { save[Index++] = news; q.Push(news); } } } return 0; } public void show(int id)//递归输出最优解的路径 { if (id == 0) { save[id].print(); result[totalstep++] = save[id];//最优解的路径保存在result数组中 return; } show(save[id].pre); save[id].print(); result[totalstep++] = save[id]; } public int mergesort(int[] a, int l, int r)//归并排序计算逆序数(不包括0) { if (l == r) return 0; int mid = (l + r) / 2; int ret = mergesort(a, l, mid) + mergesort(a, mid + 1, r); int mvl = l, mvr = mid + 1, mv = l; while (mvl <= mid || mvr <= r) { if (mvr > r || (mvl <= mid && a[mvl] <= a[mvr])) { c[mv++] = a[mvl++]; } else { ret += mid - mvl + 1; c[mv++] = a[mvr++]; } } for (int i = l; i <= r; i++) a[i] = c[i]; return ret; } public bool judge() { int[] tmpst = new int[9]; int idx = 0; for (int i = 0; i < 9; i++) { if (save[0].s[i] == 0)//计算不包括0的八个数字的逆序数 { continue; } tmpst[idx++] = save[0].s[i]; } int invst = mergesort(tmpst, 0, idx-1); int[] tmped = new int[9]; idx = 0; for (int i = 0; i < 9; i++) { if (finalstate.s[i] == 0)//计算不包括0的八个数字的逆序数 { continue; } tmped[idx++] = finalstate.s[i]; } cnt = 0; Array.Clear(c, 0, c.Length); int inved = mergesort(tmped, 0, idx-1); if ((invst % 2) == (inved % 2))//初始状态和目标状态逆序数相等时则有解 { return true; } return false;//否则无解 } public void run_bfs()//BFS算法 { input(); DateTime bef = System.DateTime.Now; if (judge() == false) { sol = false; MessageBox.Show("No Answer.\r\n"); return; } int ans = bfs(); show(ans); DateTime aft = System.DateTime.Now; TimeSpan ts = aft.Subtract(bef);//计算运行时间 Index--; MessageBox.Show("Total steps: " + save[ans].dis.ToString() + " Total status: " + Index.ToString() + " Time consumed: " + ts.TotalMilliseconds + "ms\r\n"); } public void run_astar_bfs()//A*算法 { input(); DateTime bef = System.DateTime.Now; if (judge() == false) { sol = false; MessageBox.Show("No Answer.\r\n"); return; } int ans = astar_bfs(); show(ans); DateTime aft = System.DateTime.Now; TimeSpan ts = aft.Subtract(bef);//计算运行时间 Index--; MessageBox.Show("Total steps: " + save[ans].dis.ToString() + " Total status: " + Index.ToString() + " Time consumed: " + ts.TotalMilliseconds + "ms\r\n"); } } }初始状态输入窗口
ChooseStart.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace EightDigitPuzzle { public partial class ChooseStart : Form { public int[] start; public int[] vis; public StreamWriter sw; public ChooseStart() { InitializeComponent(); start = new int[9];//记录的棋盘初始状态 vis = new int[9];//判断该数字是否已经输入过 Array.Clear(start, 0, 9); Array.Clear(vis, 0, 9); sw = new StreamWriter("C:\\Users\\dell\\Documents\\Visual Studio 2008\\Projects\\EightDigitPuzzle\\EightDigitPuzzle\\input.txt"); } public void judge(int i) { if (vis[i] == 1) { MessageBox.Show("不可输入重复的数字"); } else { vis[i] = 1; } } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { start[0] = Convert.ToInt32(comboBox1.SelectedItem); judge(start[0]); } private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) { start[1] = Convert.ToInt32(comboBox2.SelectedItem); judge(start[1]); } private void comboBox3_SelectedIndexChanged(object sender, EventArgs e) { start[2] = Convert.ToInt32(comboBox3.SelectedItem); judge(start[2]); } private void comboBox4_SelectedIndexChanged(object sender, EventArgs e) { start[3] = Convert.ToInt32(comboBox4.SelectedItem); judge(start[3]); } private void comboBox5_SelectedIndexChanged(object sender, EventArgs e) { start[4] = Convert.ToInt32(comboBox5.SelectedItem); judge(start[4]); } private void comboBox6_SelectedIndexChanged(object sender, EventArgs e) { start[5] = Convert.ToInt32(comboBox6.SelectedItem); judge(start[5]); } private void comboBox7_SelectedIndexChanged(object sender, EventArgs e) { start[6] = Convert.ToInt32(comboBox7.SelectedItem); judge(start[6]); } private void comboBox8_SelectedIndexChanged(object sender, EventArgs e) { start[7] = Convert.ToInt32(comboBox8.SelectedItem); judge(start[7]); } private void comboBox9_SelectedIndexChanged(object sender, EventArgs e) { start[8] = Convert.ToInt32(comboBox9.SelectedItem); judge(start[8]); } private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 9; i++) { sw.WriteLine(start[i].ToString());//将结果输出到.txt文件中 } sw.Close(); this.Close(); } } }
目标状态输入窗口
ChooseEnd.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.IO; namespace EightDigitPuzzle { public partial class ChooseEnd : Form { public int[] end;//保存输入的目标状态 public int[] vis;//记录该数字是否已经输入过 public StreamWriter sw; public ChooseEnd() { InitializeComponent(); end = new int[9]; vis = new int[9]; Array.Clear(end, 0, 9); Array.Clear(vis, 0, 9); sw = new StreamWriter("C:\\Users\\dell\\Documents\\Visual Studio 2008\\Projects\\EightDigitPuzzle\\EightDigitPuzzle\\input.txt",true); } public void judge(int i) { if (vis[i] == 1) { MessageBox.Show("不可输入重复的数字"); } else { vis[i] = 1; } } private void comboBox5_SelectedIndexChanged(object sender, EventArgs e) { end[4] = Convert.ToInt32(comboBox5.SelectedItem); judge(end[4]); } private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) { end[0] = Convert.ToInt32(comboBox1.SelectedItem); judge(end[0]); } private void comboBox2_SelectedIndexChanged(object sender, EventArgs e) { end[1] = Convert.ToInt32(comboBox2.SelectedItem); judge(end[1]); } private void comboBox3_SelectedIndexChanged(object sender, EventArgs e) { end[2] = Convert.ToInt32(comboBox3.SelectedItem); judge(end[2]); } private void comboBox4_SelectedIndexChanged(object sender, EventArgs e) { end[3] = Convert.ToInt32(comboBox4.SelectedItem); judge(end[3]); } private void comboBox6_SelectedIndexChanged(object sender, EventArgs e) { end[5] = Convert.ToInt32(comboBox6.SelectedItem); judge(end[5]); } private void comboBox7_SelectedIndexChanged(object sender, EventArgs e) { end[6] = Convert.ToInt32(comboBox7.SelectedItem); judge(end[6]); } private void comboBox8_SelectedIndexChanged(object sender, EventArgs e) { end[7] = Convert.ToInt32(comboBox8.SelectedItem); judge(end[7]); } private void comboBox9_SelectedIndexChanged(object sender, EventArgs e) { end[8] = Convert.ToInt32(comboBox9.SelectedItem); judge(end[8]); } private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 9; i++) { sw.WriteLine(end[i].ToString());//将结果输出到.txt文件中 } sw.Close(); this.Close(); } } }
相关文章推荐
- SharpZipLib.dll 压缩文件,可以应用于MVC, webform. C# windows application 等等地方
- C# Windows form application 播放小视频
- 关于c#的问题,执行application.exit();的时候会触发Form1_FormClosing
- C# Windows form application 播放小视频
- 深入浅出C#2008从入门到提高Step By Step(五)Windows应用程序常用控件类(1)-Form
- 深入浅出C#2008从入门到提高Step By Step(五)Windows应用程序常用控件类(1)-Form
- [C#问题--WebBrowser继续追踪]WebBrowser在Form程序中使用的感想3
- 八数码问题的三种算法解答(C#源代码)
- form认证和windows认证间切换的问题
- c#中windows窗体调用问题
- C#WindowsForm拖拽事件一例bug分析
- [人工智能]八数码问题
- C# windows服务程序中的Timer控件的问题
- Intercept and Manage Windows Originated by Third-party Components Hosted in C# Application
- 编写C#程序-Windows Application应用程序
- 初始WindowsFormApplication
- [C#问题--WebBrowser继续追踪]WebBrowser在Form程序中使用的感想2
- C#2005 Windows Application 启动对象的设置
- 解决了c#捕获sql错误号的问题和将sql连接用application放在global中作全局变量问题
- c# 的Windows应用程序问题