问题描述
首先,说明一下这个问题是研究生期间c++课的综合作业,本来有好多选择但最后还是选择了约瑟夫环问题。下面是约瑟夫环的问题描述以及设计要求:
约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3…n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到m的那个人出列;他的下一个人又从1开始报数,数到m的那个人又出列;依此规律重复下去,直到圆桌周围的人全部出列。
要求实现下面功能:
1.要求在实现约瑟夫环的同时,应该满足以下要求:
2.完整的图形用户界面,可以配置程序的运行参数,如:n的值,k的值、m的值、执行动画的速度等;
3.算法支持多线程;
4.执行过程可以暂停/继续;
5.算法执行的结果(包括中间结果)可以持久化(以自定义数据格式保存到文件中;
6.可从文件中读取数据,并在此基础上继续执行;
7.实时图形化显示执行结果;
8.可在执行完成后,或暂停时,打印执行的当前结果。
设计思路
在不考虑实现上面8个功能的前提下,我们应该实现下面一个简单的约瑟夫环问题:
在基于控制台程序情况下,对给定的n,k,m,输出报数的序列。然后将程序移植到基于mfc的程序当中,将功能分为几大块,最后组合到一起。具体源代码已经上传。
约瑟夫问题
约瑟夫环问题看做一个不断变小的环的数据提取:
以n=4,k=1,m=2为例:
这样我们将每次取下来的数存放在一个容器中[2,4,3,1],然后在显示程序中,逐个放进去:
这样就完成了约瑟夫环问题。程序流程如下:
用户界面设计
通过创建MFC AppWizard 基于对话框工程HOMEWORK2,自动生成HOMEWORK2App以及HOMEWORK2Dlg两类,在资源视图中手动画出下面两个界面:
一个用于初始化,用户可以配置程序的运行参数,如:n的值,k的值、m的值、执行动画的速度。另一个用于显示算法执行的过程。
并修改它们的属性ID值分别为:IDD_HOMEWORK2_DIALOG,IDD_DIALOGSHOW。
通过类向导将对话框IDD_DIALOGSHOW与类CDialogShow关联。接下来将两个界面上的所有组件修改属性ID,以及添加相应的消息映射函数。
自定义控件
执行的结果不是直接画在IDD_DIALOGSHOW上的,而是在IDD_DIALOGSHOW添加一个静态文本(IDC_STATICTU),并添加变量,变量类型为CMystatic类,这里需要自己在类视图中自己添加(基类选择CStatic),并重载OnPaint()函数:
其中OnPaint()用于初始化显示界面,即是在IDC_STATICTU中画一个圆桌(用圆表示),m个人(用空白方框表示),并创建线程用于算法执行。
创建线程函数
将约瑟夫环算法嵌入到线程函数中,可以实现在点击开始按钮后,创建IDD_DIALOGSHOW对话框的同时,初始化IDC_STATICTU,然后创建一个线程(因为在OnPaint()中添加了创建线程m_ThreadSpeed的语句),这样就开始了约瑟夫环算法。最后通过线程的挂起、唤醒、终结实现执行过程的暂停/继续,以及终结。对于控制动画的显示速度则是通过Sleep()函数来控制。为了方便将线程函数,显示程序定义为CMystatic的成员函数。
实现打印
通过mfc里面已有的打印对话框类CPringDialog类实现对当前执行结果的打印功能。通过在类视图中添加类CMyPrintDialog类(基类为CPringDialog类)。最后在IDD_DIALOGSHOW中终结按钮的消息映射函数中写入打印程序。
// 创建一个打印机设备句柄
if((hdcprint=CreateDC(szDriver,szDevice,szOutput,NULL))!=0) {if(StartDoc(hdcprint,&di)>0) {//开始执行一个打印作业StartPage(hdcprint); //打印机走纸,开始打印SaveDC(hdcprint); //保存打印机设备句柄// 打印当前的结果,将list1里面的结果以字符串的形式打印出来TextOut(hdcprint,1000,800,"约瑟夫环打印结果为:",20);CString str;for(vector<int>::iterator it = list1.begin();it!=list1.end();it++){CString temp;temp.Format("%d",*it);str += "-->";str += temp;}}TextOut(hdcprint,1000,1000,str,str.GetLength()); RestoreDC(hdcprint,-1); //恢复打印机设备句柄EndPage(hdcprint); //打印机停纸,停止打印EndDoc(hdcprint); //结束一个打印作业MessageBox("打印完毕!","提示",MB_ICONINFORMATION);
}
实现结果
由于时间紧迫,以及个人能力有限,所以做的界面比较ugly。只实现了老师要求的一些功能:
默认n=16, k=1, m=3, s=1000ms, 数据读入在data.txt,结果保存在result.txt。
总结
由于是第一次写,所以排版什么的比较丑陋。约瑟夫环问题也是自己做的第一个关于用户界面的问题了,由于自己的能力有限,所以只能做到这种程度,中间会有福多错误,希望大家批评指正,以后会努力学习。