姓名:杨xx
学号:17272xxx/
运行环境:VS2017/DevC++
prob1:整数的划分
思路
分析示例可得如下划分规律
1.第一个划分数为n-1~1
2.每一次划分后的余下部分不得大于前一个划分数。
故设置一个全局数组用于动态存储每一次划分的结果
然后在一个for循环中先降序划分出来第一个数x,再将余下部分n-x进行再划分。
因为要满足2规律方可使划分结果不重复,所以对划分数的划分需从划分数~1,当划分后余下的部分<=0时终止划分,输出本次划分结果。
代码实现:
#include
#include
using namespace std;
int num[100]; //存储划分的数
void print(int k) //输出一次拆分的结果,k为拆分的个数
{
cout << num[0] << "=" << num[1];
for (int i = 2; i <= k; i++)
cout << "+" << num[i];
cout << endl;
}
void split(int k, int n) //n为待拆分数,即上一步拆分后最原始数剩余的部分
{
if (n <= 0) //n<0说明已拆分完全
print(k);
else
for (int i = n; i >= 1; --i) //
{
if (i <= num[k]) //确保拆分出来的数小于前一位拆分出来的数
{
num[k+1] = i; //将拆分出来的数存储进num[k+1]里
split(k + 1, n - i); //余下部分继续拆分,直到满足终止条件为止
}
}
}
int main()
{
cin >> num[0];
for (int i = num[0] - 1; i >= 1; i--) //先拆分出来第一位数
{
num[1] = i;
split(1, num[0] - i);
}
_getch();
return 0;
}
运行截图
prob2:递归实现走迷宫
代码实现:
#include
using namespace std;
//迷宫的布局放入到一个二维的数组中
// 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9
int mizu[10][10] = {1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1, //0
1 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1, //1
1 , 0 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 1, //2
1 , 0 , 0 , 0 , 0 , 1 , 1 , 0 , 0 , 1, //3
1 , 0 , 1 , 1 , 1 , 0 , 0 , 0 , 0 , 1, //4
1 , 0 , 0 , 0 , 1 , 0 , 0 , 0 , 0 , 1, //5
1 , 0 , 1 , 0 , 0 , 0 , 1 , 0 , 0 , 1, //6
1 , 0 , 1 , 1 , 1 , 0 , 1 , 1 , 0 , 1, //7
1 , 1 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 1, //8
1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 , 1 //9
} ;
int flag[10][10];//定义操作数组
void putout(int a[10][10])//输出数组,可输出不同数组
{
int i,j;
for(i=0;i<=9;i++)
for(j=0;j<=9;j++)
{
if(a[i][j]==2)
cout << "*";//2则输出路径*
if(a[i][j]==1)
cout << "x";//1则输出x
if(a[i][j]==0)
cout << " ";//0则输出 空格
if(j==9)
cout << "\n";
}
cout << endl << endl;
}
void nextstep(int x,int y)
{
if(x==8&&y==8)
putout(flag);
flag[x][y]=2;
if(flag[x+1][y]==0)//right is passable
nextstep(x+1,y);
if(flag[x-1][y]==0)//left is passable
nextstep(x-1,y);
if(flag[x][y-1]==0)//down is passable
nextstep(x,y-1);
if(flag[x][y+1]==0)//up is passable
nextstep(x,y+1);
flag[x][y]=0;
}//调用自身完成递归
int main()
{ int i,j;
for(i=0;i<=9;i++)
for(j=0;j<=9;j++)
flag[i][j]=mizu[i][j];
int x=1,y=1;
cout << "迷宫构造" << endl;
putout(mizu);
cout << "5秒后将打印所有能走的方法:" << endl;
nextstep(x,y);
return 0;
}
运行截图
二 结构/链表与堆栈
prob1:猴子选大王
思路:
分析可知,每个猴子节点应该带有三个域,一个为猴子编号;一个为猴子的定数,用于确定下一个删除猴子节点的位置;一个为指向下一个猴子的指针,用于确定猴子之间的关系。
步骤:
1.动态创建一个猴子单向循环链
2.函数DeleteNext(p):删除猴子节点p;当选中猴子p时,只需将p->next指向p->next->next,可设置一个新的节点指针指向待删除的节点。若只是p->next=p-next->next,虽然成功指向,但被删除的猴子所占并内存没得到释放,会造成内存空间浪费。
3. 挑选函数
代码实现:
#include
#include
using namespace std;
typedef struct node{//这个结构类型包括三个域
int number;//猴子的编号
int mydata;//猴子的定数
struct node*next;//指向下一个猴子的指针
}linklist;
linklist *Creatcircle(int n) //创建一个猴子的单向循环链
{
linklist *head,*p,*s;
p=head = (linklist*)malloc(sizeof(linklist));//首节点创建
p -> number = 1; //为第一个猴子编号
cin >> p->mydata;//定数,确定下一只出局的猴子
p->next = NULL;
for(int i = 2;i <= n;i++)// 创建链表
{
s=(linklist*)malloc(sizeof(linklist));//创建一个新的节点
s->number = i;//为新节点的编号赋值
cin >> s->mydata;//定数(报数),确定下一只出局的猴子
p->next = s;//将前节点尾指向新节点(添加猴子进猴子圈)
p=s;//前节点指针标志指向新节点,成为新的尾节点
}
p->next = head;//尾节点的指针指向头节点,将表链接成圈
return p;
}
linklist *DeleteNext(linklist *p)//删除单循环链表的p所指的下一个节点
{
linklist *b = p->next; //b节点指向p节点的节点指针指向的节点
p->next = b->next;//
free(b);//释放b节点,即p->next节点
return p;
}
int KingOfMonkey(int n,linklist *head) //挑选大王
{
linklist *p = head;//初始p指针指向头节点
int i,j,steps = p->mydata;//从头节点的定数开始进行遍历删除
for(j = 1;j < n;j++)//删除操作共需n-1步
{
for(i = 1;i < steps;i++) //按照定数搜索待删除的节点
p = p->next; //累加步数,直到达到定数
steps = p->next->mydata; //存储当前待删猴子的定数(既下一待删猴子的位置)
cout << p->next->number << endl; //输出当前待删猴子的编号
DeleteNext(p);//将当前节点从表中删除
}
return p->number;//返货最终胜利的猴子,既猴王
}
int main()
{
linklist *head;
int n;
cout << "请输入猴子的总数和每只猴子的定数(必须是正整数):";
cin >> n;
head = Creatcircle(n);
cout << endl << "the king if monkey[" << KingOfMonkey(n,head) << "]." << endl;
return 0;
}
运行截图
prob2:链表表示一元n次多项式,实现多项式的加/减以及乘法运算
思路:
1.分析一元n次多项式的结构,每个项节点应包含三个域,一个次数域,一个系数域,一个指针域;
2.分析一元n次多项式的加/减/乘运算可知,加法与减法较易实现,次数相同的相加/减即可,但应注意格式输出时对正负号以及对系数为0时的控制;而乘法较复杂,结果链表需伸长至多2n个节点。
3.由于运算是从低次向高次遍历计算,而规范输出是从高次向低次遍历输出,所以需构建双向链表,既指针域有两个next和pre。
步骤
代码实现
#include
using namespace std;
typedef struct linklist{
int tim; //指数
int coe; //系数
struct linklist *next;
struct linklist *pre;
}linklist;
/*构建多项式,并返回多项式的头指针*/
linklist *CreatePOOI(int n)
{
linklist *head,*end,*New;
end = head = (linklist*)malloc(sizeof(linklist));
end->tim = n;
cin >> end->coe; //输入系数
end->next =NULL;
end->pre = NULL;
for(int i = n-1;i >= 0;i--)
{
New=(linklist*)malloc(sizeof(linklist));
New->tim = i; //由高次向低次依次为多项式的次数赋值
cin >> New->coe; //由高次向低次依次为多项式的系数赋值
end->next = New; //将前一节点尾指向新节点
New->next = NULL;
New->pre = end; //将新节点的前序指针指向前一节点
end = New; //新尾节点标志设置为新节点
}
return head;
}
/*构建系数均为零的多项式,并返回多项式的头指针*/
linklist *CreateEmptyPOOI(int n)
{
linklist *head,*end,*New;
end = head = (linklist*)malloc(sizeof(linklist));
end->tim = n;
end->coe = 0; //输入系数
end->next =NULL;
end->pre = NULL;
for(int i = n-1;i >= 0;i--)
{
New=(linklist*)malloc(sizeof(linklist));
New->tim = i; //由高次向低次依次为多项式的次数赋值
New->coe = 0; //由高次向低次依次为多项式的系数赋值
end->next = New; //将前一节点尾指向新节点
New->next = NULL;
New->pre = end; //将新节点的前序指针指向前一节点
end = New; //新尾节点标志设置为新节点
}
return head;
}
/*规范输出多项式*/
void ShowPOOI(linklist *p)
{
if(p->coe == 0)
;
else
cout << p->coe << "*n^" << p->tim;
p = p->next;
while(p->next != NULL)
{
if(p->coe < 0)
cout << p->coe << "*n^" << p->tim;
else if(p->coe > 0)
cout << "+" << p->coe << "*n^" << p->tim;
else
;
p = p->next;
}
if(p->coe < 0)
cout << p->coe <coe > 0)
cout << "+" << p->coe <next != NULL)
SUM = SUM->next;
while(ls_1->next != NULL)
ls_1 = ls_1->next;
while(ls_2->next != NULL)
ls_2 = ls_2->next;
while(ls_1->pre != NULL)
{
SUM->coe=ls_1->coe + ls_2->coe;
SUM = SUM->pre;
ls_1 = ls_1->pre;
ls_2 = ls_2->pre;
}
//对正数第1位的运算
SUM->coe=ls_1->coe + ls_2->coe;
return Tail;
}
/*多项式求差,返回结果多项式的头指针*/
linklist *DiffPOOI(linklist *ls_1,linklist *ls_2,int n)//n为最高次数
{
linklist *DIFF,*Tail;
Tail = DIFF = CreateEmptyPOOI(n);
while(DIFF->next != NULL)
DIFF = DIFF->next;
while(ls_1->next != NULL)
ls_1 = ls_1->next;
while(ls_2->next != NULL)
ls_2 = ls_2->next;
while(ls_1->pre != NULL)
{
DIFF->coe=ls_1->coe - ls_2->coe;
DIFF = DIFF->pre;
ls_1 = ls_1->pre;
ls_2 = ls_2->pre;
}
//对正数第1位的运算
DIFF->coe=ls_1->coe - ls_2->coe;
return Tail;
}
/*多项式求积,返回结果多项式的头指针*/
linklist *ProdPOOI(linklist *ls_1,linklist *ls_2,int n)//n为最高次数
{
linklist *PROD,*Tail;
Tail = PROD = CreateEmptyPOOI(2*n);
while(PROD->next != NULL)//3个while作用:找到常数项,从常数项开始按指数升序计算
PROD = PROD->next;
while(ls_1->next != NULL)
ls_1 = ls_1->next;
while(ls_2->next != NULL)
ls_2 = ls_2->next;
//计算PROD的指数n对应的系数时,当ls_1的指数项为i=0~n,则j=n-i~n,Sum=i*j累加;
linklist *i,*j,*iHead,*jHead;//iHead和jHead始终指向ls_1和ls_2的表尾:常数项; 为i,j提供每次循环的初始条件
i = iHead =ls_1;
j = jHead = ls_2;
for(PROD;PROD->pre != NULL;PROD=PROD->pre)
{
for(i = iHead;i->pre != NULL;i = i->pre)
{
for(j = jHead;j->pre != NULL;j = j->pre)
{
if(i->tim + j->tim == PROD->tim)//当ls_1的指数+ls_2的指数等于PROD的指数时
{
PROD->coe += (i->coe*j->coe);
}
}
PROD->coe += (i->coe * j->coe);//为什么有这步以及line:164,line:166,因为每次循环后最高次数项都会漏算
}
PROD->coe += (i->coe * j->coe);
}
PROD->coe += (ls_1->coe * ls_2->coe);
//nice nice nice
return Tail;
}
int main()
{
int n;
linklist *ls_1,*ls_2,*ls_sum,*ls_diff,*ls_prod;
cout << "please input n:";
cin >> n;
cout << "构建链表1" << endl;
ls_1 = CreatePOOI(n);
cout << "构建链表2" << endl;
ls_2 = CreatePOOI(n);
cout << "一元多项式1:";
ShowPOOI(ls_1);
cout << "一元多项式2:";
ShowPOOI(ls_2);
ls_sum = SumPOOI(ls_1,ls_2,n);
cout << "多项式1和2的和:";
ShowPOOI(ls_sum);
ls_diff = DiffPOOI(ls_1,ls_2,n);
cout << "多项式1和2的差:";
ShowPOOI(ls_diff);
ls_prod = ProdPOOI(ls_1,ls_2,n);
cout << "多项式1和2的积:";
ShowPOOI(ls_prod);
}
运行截图
prob1:画房子
关键在于计算坐标,最简洁的方法是一个line函数搞定.
代码实现:
#include "graphics.h"
int main(void)
{
initgraph(638,512); // 初始化绘图环境
line(175, 211, 175, 391);
line(175, 211, 463, 211);
line(463, 211, 463, 391);
line(175, 391, 463, 391);
line(175, 301, 463, 301);
line(247, 199, 247, 391);
line(319, 199, 319, 391);
line(391, 211, 391, 391);
line(211, 121, 175, 211);
line(211, 121, 247, 211);
line(427, 121, 391, 211);
line(427, 121, 463, 211);
line(259, 199, 247, 199);
line(259, 199, 259, 211);
line(271, 211, 271, 199);
line(271, 199, 283, 199);
line(283, 199, 283, 211);
line(295, 211, 295, 199);
line(295, 199, 307, 199);
line(307, 199, 307, 211);
line(331, 199, 319, 199);
line(331, 199, 331, 211);
line(343, 211, 343, 199);
line(343, 199, 355, 199);
line(355, 199, 355, 211);
line(367, 211, 367, 199);
line(367, 199, 379, 199);
line(379, 199, 379, 211);
ege::getch();
closegraph();
return 0;
}
运行截图
prob2:画多边形
思路
分析多边形,可看出是由以下图形绕一点旋转20°连续旋转18次得到,且线段长度不变.
沿当前角度(第1步骤中的角度)画线->逆时针旋转60°->画线->逆时针旋转-120°->画线->逆时针旋转-60°->画线->逆时针旋转120°->画线
此步骤在draw函数中实现
实现代码
#include
#include
#include
#define PI 3.1415926
double nowangle = 0.0;//记录当前方向,正南为0,顺时针+逆时针-
double indexangle = nowangle; //...
void turn(double angle) //逆时针旋转角度angle
{
indexangle += angle;
}
void move(double distance) //沿当前方向移动笔,移动距离为distance
{
moveto((double)getx() + distance * sin(indexangle*PI / 180), (double)gety() + distance * cos(indexangle*PI / 180));
}
void forward(double distance)//沿当前方向划线,长度为distance
{
line(getx(), gety(), (double)getx() + distance * sin(indexangle*PI / 180), (double)gety() + distance * cos(indexangle*PI / 180));
move(100);
}
void draw()
{
forward(100);
turn(60); forward(100);
turn(-120); forward(100);
turn(-60); forward(100);
turn(-120); forward(100);
}
int main()
{
initgraph(812, 512);
setlinecolor(GREEN);
for (int i = 0; i < 18; i++)
{
moveto(406, 256);
draw();
nowangle += 20.0;
indexangle = nowangle;
}
_getch();
return 0;
}
运行截图
prob3:随笔画程序,当鼠标左键按下拖动时,在窗口中随着鼠标的移动画出轨迹,当鼠标抬起时则不画
思路
///
实现代码
#include
#include
void main()
{
initgraph(640, 480);// 初始化图形窗口
MOUSEMSG m;// 定义鼠标消息
while (true)
{
m = GetMouseMsg();// 获取一条鼠标消息
if (m.mkLButton)//mkLButton为鼠标左键状态
putpixel(m.x, m.y, WHITE);
}
_getch();
closegraph();// 关闭图形窗口
}
运行截图
prob4:拟文字输入界面
代码实现
#include
#include
#include
#include
#include
#include
#define SIZE 1000
void ShowCursor(int x, int y);
void CheckInput();
int main(void)
{
initgraph(800, 600); // 初始化图形窗口
CheckInput();
closegraph(); // 关闭图形窗口
return 0;
}
void CheckInput()
{
int c = 0;
settextstyle(16, 8, _T("Courier")); // 设置字体
settextcolor(WHITE); // 设置颜色
int x = getx(); //获取当前坐标
int y = gety();
while (c != '\r') // 设置循环直到用户输入回车
{
if (_kbhit()) //判断用户输入
{
int ch = _getch();
if (ch == 224) //如果高位相等
{
ch = _getch(); //那么再获取一个
if (ch == 75) //如果低位也相同(和方向键左一样)
x -= textwidth(c);
else if (ch == 77)
x += textwidth(c);//你要执行的动作.
}
else { //如果不是, 把这个字符吸收了.
c = ch; //获取该字符
if (c == '\b') //如果用户输入Backspace
{
x -= textwidth(c); //减去一个字符的像素宽度
outtextxy(x, y, ' '); //用空格代替,达到删除效果
}
else
{
outtextxy(x, y, c); //输出字符
x += textwidth(c);
}
}
}
else
ShowCursor(x, y); //输出光标
}
}
void ShowCursor(int x, int y)
{
// 绘制白色直线
setlinecolor(WHITE);
line(x, y + 18, x + 8, y + 18);
// 延时
Sleep(500);
// 绘制黑色直线(即擦掉之前画的白线)
setlinecolor(BLACK);
line(x, y + 18, x + 8, y + 18);
// 延时
Sleep(500);
}
运行截图
图形界面
(输入)
(光标右移)
(光标左移和空格键)
(删除)
回车键|终端输出
prob5:Koch雪花分形
思路
对雪花的分形,实质是对雪花每一条边的分形.
实现代码
#include
#include
#include
#include
using namespace std;
void Koch(float x1, float y1, float x2, float y2, int n, int m) //(x1,y1)/(x2,y2)为分形直线的起点和终点,n为分形的阶数,m为当下分形的阶数
{
float x3, y3, x4, y4, x5, y5;
x3 = (x2 - x1) / 3 + x1;
y3 = (y2 - y1) / 3 + y1;
x4 = (x2 - x1) / 3 * 2 + x1;
y4 = (y2 - y1) / 3 * 2 + y1;
x5 = x3 + (((x2 - x1) - (y2 - y1)*sqrt(3)) / 6);
y5 = y3 + (((x2 - x1)*sqrt(3) + (y2 - y1)) / 6);
n = n + 1;
if (n == m) //分形的终止条件
{
moveto(x1, y1);
lineto(x3, y3);
lineto(x5, y5);
lineto(x4, y4);
lineto(x2, y2);
return;
}
//对直线的三等分直线分别进行分形
Koch(x1, y1, x3, y3, n, m);
Koch(x3, y3, x5, y5, n, m);
Koch(x5, y5, x4, y4, n, m);
Koch(x4, y4, x2, y2, n, m);
}
int main()
{
float x1, x2, x3, y1, y2, y3;
int n = 0, rdepth, i;
cout << "请输入分形的阶数(任意键继续):";
cin >> rdepth;
initgraph(980, 760);
setbkcolor(BLACK);
setcolor(GREEN);
//初始图形的顶点坐标
x1 = 200;y1 = 180;
x2 = 400;y2 = 180;
x3 = 300;y3 = 180 + 200 * sqrt(3) / 2;
moveto(x1, y1);
lineto(x2, y2);
lineto(x3, y3);
lineto(x1, y1);
_getch();
for (i = 1; i <= rdepth; i++) //输出每一阶的图案
{
cleardevice(); //清空屏幕内容
Koch(x1, y1, x3, y3, n, i);
Koch(x3, y3, x2, y2, n, i);
Koch(x2, y2, x1, y1, n, i);
_getch();
}
closegraph();
return 0;
}
运行截图
prob6:CAD
思路
1.将界面分为左右两个区域:选择界面/作图界面
2.当鼠标在选择界面不同坐标范围内单击左键时,记录此时鼠标坐标(m.x,m.y),用以选择对应功能。
3.分析可知放置功能较易实现,但删除/改变大小/移动功能需获取目标的具体位置信息,所以在放置时就需要一个数据库来存储相关信息。分析图形信息可知,均为两个坐标点便可准确表示,所以定义一个coord结构,如下:
typedef struct coord {
double x1;
double y1;
double x2;
double y2;
}coord;
文字部分:需记录下起始坐标和文字内容。所以定义一个Str结构,如下:
typedef struct coordd {
double x;
double y;
char words[100];
}Str;
四个coord数组用于存储各种图形/文字的信息
coord Line[100];
coord Rectangle[100];
coord Ellipse[100];
coord Word[100];
四个static int变量用于记录各种图形/文字的数目
static int temp_l = 0;//分别为 直线/矩形/椭圆/文字 的数目
static int temp_r = 0;
static int temp_e = 0;
static int temp_w = 0;
4.界面设计,如图
5.{X1,Y1,X2,Y2}表示各个功能区间对应的坐标范围
功能选择实现代码布局如下
GetMouseCoor(m.x,m.y)
{
if (10 <= m.x && m.x <= 210 && 108 <= m.y && m.y <= 228)
{
if (m.y <= 138) {放置直线}
else if (m.y <= 168) {删除直线}
else if (m.y <= 198) {改变大小}
else if (m.y <= 228) {移动直线}
}
if (10 <= m.x && m.x <= 210 && 282 <= m.y && m.y <= 402)
{
if (m.y <= 312) {放置矩形}
else if (m.y <= 342) {删除矩形}
else if (m.y <= 372) {改变大小}
else if (m.y <= 402) {移动直线}
}
if (10 <= m.x && m.x <= 210 && 456 <= m.y && m.y <= 576)
{
if (m.y <= 486) {放置椭圆}
else if (m.y <= 516) {删除椭圆}
else if (m.y <= 546) {改变大小}
else if (m.y <= 228) {移动椭圆}
}
if (10 <= m.x && m.x <= 210 && 630 <= m.y && m.y <= 750)
{
if (m.y <= 660) {放置文字}
else if (m.y <= 690) {删除文字}
else if (m.y <= 720) {改变大小}
else if (m.y <= 750) {移动文字}
}
…
}
6.所有状态(除“改变大小”需在键盘上敲打除w/s外的任意键外)下点击右键,重返功能选择区域
7.各功能的实现
直线部分
(1)放置直线:
/左键按下,记录鼠标坐标作为直线起点;左键弹起,记录鼠标坐标作为直线终点;画线并 存储直线信息,temp_l加一;
//左键(借助goto Flag_LineAgain)可实现重复画线操作/右 键(借助goto Flag_ChoiceAgain)可 实现功能重新选择
(2)删除直线(将原有(红色)直线加黑成背景颜色,便达到和删除一样的效果):
/外层定义一个死循环,结束条件为获取到一个符合条件的直线信息;死循环里,得到一个有效鼠标 坐标,便for循环遍历直线数组Line[100]检索符合条件的直线,检索条件从斜率考虑;
//检索到直线并进行删除操作后,由于是线性存储,所以后续直线信息向前进一;
///左键(借助goto Flag_DeleteAgain)进入死循环可实现重复画线操作/右键(借助goto Flag_ChoiceAgain)跳出循环,实现功能重新选择
(3)改变大小:
/外层定义一个死循环,结束条件为获取到一个符合条件的直线信息;死循环里,得到一个有效鼠标 坐标,便for循环遍历直线数组Line[100]检索符合条件的直线,检索条件从斜率考虑;//以上部分 与删除直线一样,代码实现可参考删除直线部分代码
//检索到直线后,将直线两段放大,x±50,y±50×斜率k;”w”伸长/“w”缩小/其他键退出对当 前直线的操作;
///左键(借助goto Flag_ChoiceLineAgain)重新选择直线/右键(借助goto Flag_ChoiceAgain)跳出 循环,实现功能重新选择.
(4)移动直线:
/外层定义一个死循环,结束条件为获取到一个符合条件的直线信息;死循环里,得到一个有效鼠标 坐标,便for循环遍历直线数组Line[100]检索符合条件的直线,检索条件从斜率考虑;//以上部分 与删除直线一样,代码实现可参考删除直线部分代码
//检索到直线后,记录当前鼠标坐标(X1,Y1)作为起点;左键弹起,记录鼠标坐标作为终点;将检索 到的直线加黑(删除),并在终点处建立平移后的直线,更新被删直线信息为新的直线信息;point:平 移后坐标的计算
///左键(借助goto Flag_MoveAgain)重新选择直线移动/右键(借助goto Flag_ChoiceAgain)跳出 循环,实现功能重新选择.
矩形/椭圆部分与直线部分高度类似,以下是其中差异部分
(1)放置矩形/椭圆
(2)删除矩形/椭圆
/矩形:检索条件从四个顶点入手
椭圆:检索条件从左右端点入手
//
///
(3)改变大小:
/
//矩形:检索到矩形后,将矩形左上和右下两个顶点放大,x±50,y±50×长宽比k;”w”伸长/“w” 缩小
椭圆:检索到椭圆后,将椭圆外接矩形的左上和右下顶点放大,x±50,y±50×外接矩形的长宽比 k;”w”伸长/“w“缩小
///
(4)移动矩形/椭圆:
/
//
///
文字部分与三个图形部分类似,唯一的区别在于文字的信息存储除起始坐标外还需记录文字的信息。文字部分的录入参照本专题第四题”模拟文字录入”。
实现代码
#include
#include
#include
#include
using namespace std;
#define MAXELEM 100
#define wordsize 10
int main()
{
typedef struct coord {
double x1;
double y1;
double x2;
double y2;
}coord;
typedef struct coordd {
double x;
double y;
char words[100];
}Str;
coord Line[MAXELEM + 111];
coord Rectangle[MAXELEM];
coord Ellipse[MAXELEM];
Str Word[MAXELEM];
static int temp_l = 0;//分别为 直线/矩形/椭圆/文字 的数目
static int temp_r = 0;
static int temp_e = 0;
static int temp_w = 0;
initgraph(980, 756);//初始化图形
/*LINE: 29-68 界面设计*/
/*边框部分*/
setlinecolor(GREEN);
for (int i = 54, k = 0; i < 756; i += 30, k++)
{
if (k % 5 == 0)
i += 24;
rectangle(10, i, 210, i + 30);
}
/*虚线部分*/
setlinestyle(PS_DASH);
line(220, 0, 220, 756);
line(0, 60, 980, 60);
setlinestyle(PS_SOLID);
/*文字部分*/
settextstyle(13, 13, NULL);
outtextxy(84, 24, "选择界面");
outtextxy(512, 24, "作图界面");
settextstyle(8, 8, NULL);
outtextxy(866, 42, "wrote by:Yangxin");
settextstyle(11, 11, NULL);
outtextxy(102, 83, "直线");
outtextxy(102, 257, "矩形");
outtextxy(102, 431, "椭圆");
outtextxy(102, 605, "文字");
settextstyle(10, 10, NULL);
outtextxy(12, 113, "放置直线");
outtextxy(12, 143, "删除直线");
outtextxy(12, 173, "改变大小");
outtextxy(12, 203, "移动直线");
outtextxy(12, 292, "放置矩形");
outtextxy(12, 322, "删除矩形");
outtextxy(12, 352, "改变大小");
outtextxy(12, 382, "移动矩形");
outtextxy(12, 461, "放置椭圆");
outtextxy(12, 491, "删除椭圆");
outtextxy(12, 521, "改变大小");
outtextxy(12, 551, "移动椭圆");
outtextxy(12, 640, "放置文字");
outtextxy(12, 670, "删除文字");
outtextxy(12, 700, "改变大小");
outtextxy(12, 730, "移动文字");
/*LINE: 74-709 功能部分*/
MOUSEMSG m; // 定义鼠标消息
while (true)
{
Flag_ChoiceAgain:
double START_X, START_Y, END_X, END_Y;
m = GetMouseMsg();
/*作图区单击左键,选择功能*/
if (m.uMsg == WM_LBUTTONDOWN)
{
/*作图区选择直线相关的操作*/
/*LINE: 97-291 直线操作*/
if (10 <= m.x && m.x <= 210 && 108 <= m.y && m.y <= 228)
{
/*1:放置直线*/
if (m.y <= 138)
{
Flag_LineAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,获取起点
{
START_X = m.x;
START_Y = m.y;
Line[temp_l].x1 = m.x;
Line[temp_l].y1 = m.y;
while (START_X >= 220 && START_Y >= 60)//确保起点在作图区内
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONUP)//左键弹起,获取终点
{
END_X = m.x;
END_Y = m.y;
Line[temp_l].x2 = m.x;
Line[temp_l].y2 = m.y;
if (END_X >= 220 && END_Y >= 60)//确保终点在作图区内
{
setlinecolor(RED);
line(START_X, START_Y, END_X, END_Y);
temp_l++; //直线的数量加一
goto Flag_LineAgain; //重复画线
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键回到功能选择区域
goto Flag_ChoiceAgain;
}
}
/*2:删除直线*/
else if (m.y <= 168)
{
Flag_DeleteAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,删除线段
{
int i;
for (i = 0; i < temp_l; i++) //遍历直线数组,寻找符合条件的直线
{
if (m.x >= 220 && m.y >= 60)//限制区域为作图区域
if (fabs((Line[i].y2 - Line[i].y1) / (Line[i].x2 - Line[i].x1) - (Line[i].y2 - m.y) / (Line[i].x2 - m.x)) <= 0.1)//只要是一条直线上,即选中
{
setlinecolor(BLACK);
line(Line[i].x1, Line[i].y1, Line[i].x2, Line[i].y2);
for (int k = i; k < temp_l - 1; k++)//线性存储,所以后续直线需要向前移一位
{
Line[k].x1 = Line[k + 1].x1;
Line[k].y1 = Line[k + 1].y1;
Line[k].x2 = Line[k + 1].x2;
Line[k].y2 = Line[k + 1].y2;
}
temp_l--;
FlushMouseMsgBuffer();
goto Flag_DeleteAgain;//重复删除
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
/*3:改变直线大小*/
else if (m.y <= 198)
{
Flag_ChoiceLineAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选中线段
{
int i;
for (i = 0; i < temp_l; i++)
{
if (m.x >= 220 && m.y >= 60) //限制区域为作图区域
if (fabs((Line[i].y2 - Line[i].y1) / (Line[i].x2 - Line[i].x1) - (Line[i].y2 - m.y) / (Line[i].x2 - m.x)) <= 0.1)//只要是一条直线上,即选中
{
double k = (Line[i].y2 - Line[i].y1) / (Line[i].x2 - Line[i].x1);//计算斜率
again:
char ch;
ch = _getche();
if (ch == 'w') //键盘w增大
{
setlinecolor(BLACK);
line(Line[i].x1, Line[i].y1, Line[i].x2, Line[i].y2);
Line[i].x1 -= 50;
Line[i].y1 -= 50 * k;
Line[i].x2 += 50;
Line[i].y2 += 50 * k;
setlinecolor(RED);
line(Line[i].x1, Line[i].y1, Line[i].x2, Line[i].y2);
goto again;
}
if (ch == 's') //键盘s减小
{
setlinecolor(BLACK);
line(Line[i].x1, Line[i].y1, Line[i].x2, Line[i].y2);
Line[i].x1 += 50;
Line[i].y1 += 50 * k;
Line[i].x2 -= 50;
Line[i].y2 -= 50 * k;
setlinecolor(RED);
line(Line[i].x1, Line[i].y1, Line[i].x2, Line[i].y2);
goto again;
}
goto Flag_ChoiceLineAgain;
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,重新功能选择
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
/*4:移动直线*/
else if (m.y <= 228)
{
Flag_MoveAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选择线段
{
int i;
for (i = 0; i < temp_l; i++) //筛选线段
{
if (m.x >= 220 && m.y >= 60)//限制鼠标移动区域为作图区域
if (fabs((Line[i].y2 - Line[i].y1) / (Line[i].x2 - Line[i].x1) - (Line[i].y2 - m.y) / (Line[i].x2 - m.x)) <= 0.1)//只要是一条直线上,即选中
{
double START_X, START_Y, END_X, END_Y;
START_X = m.x;
START_Y = m.y;
setlinecolor(BLACK);
line(Line[i].x1, Line[i].y1, Line[i].x2, Line[i].y2);
while (START_X >= 220 && START_Y >= 60)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONUP)//左键弹起,获取终点
{
END_X = m.x;
END_Y = m.y;
if (END_X >= 220 && END_Y >= 60)
{
setlinecolor(RED);
double D_x = END_X - START_X;
double D_y = END_Y - START_Y;
Line[i].x1 += D_x;
Line[i].x2 += D_x;
Line[i].y1 += D_y;
Line[i].y2 += D_y;
line(Line[i].x1, Line[i].y1, Line[i].x2, Line[i].y2);
goto Flag_MoveAgain;//重复选择线段移动
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
goto Flag_MoveAgain;//重新选择线段移动
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
}
/*作图区选择矩形相关的操作*/
/*LINE: 296-508 矩形操作*/
if (10 <= m.x && m.x <= 210 && 282 <= m.y && m.y <= 402)
{
/*1:放置矩形*/
if (m.y <= 312)
{
Flag_RectangleAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,获取矩形左上顶点
{
START_X = m.x;
START_Y = m.y;
Rectangle[temp_r].x1 = m.x;
Rectangle[temp_r].y1 = m.y;
while (START_X >= 220 && START_Y >= 60)//确保起点在作图区内
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONUP)//左键弹起,获取矩形右下顶点
{
END_X = m.x;
END_Y = m.y;
Rectangle[temp_r].x2 = m.x;
Rectangle[temp_r].y2 = m.y;
if (END_X >= 220 && END_Y >= 60)//确保终点在作图区内
{
setlinecolor(RED);
rectangle(START_X, START_Y, END_X, END_Y);
temp_r++; //矩形的数量加一
goto Flag_RectangleAgain; //重复画矩形
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键回到功能选择区域
goto Flag_ChoiceAgain;
}
}
/*2:删除矩形*/
else if (m.y <= 342)
{
Flag_DeleteRectangleAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,删除矩形
{
int i;
for (i = 0; i < temp_r; i++) //遍历矩形数组,寻找符合条件的矩形
{
if (m.x >= 220 && m.y >= 60)//限制区域为作图区域
{
bool a = (fabs(m.x - Rectangle[i].x1) < 5);
bool b = (fabs(m.x - Rectangle[i].x2) < 5);
bool c = (fabs(m.y - Rectangle[i].y1) < 5);
bool d = (fabs(m.y - Rectangle[i].y2) < 5);
if ((a || b) && (c || d))//点击矩形任一顶点即选中
{
setlinecolor(BLACK);
rectangle(Rectangle[i].x1, Rectangle[i].y1, Rectangle[i].x2, Rectangle[i].y2);
for (int k = i; k < temp_r - 1; k++)//线性存储,所以后续矩形需要向前进一位
{
Rectangle[k].x1 = Rectangle[k + 1].x1;
Rectangle[k].y1 = Rectangle[k + 1].y1;
Rectangle[k].x2 = Rectangle[k + 1].x2;
Rectangle[k].y2 = Rectangle[k + 1].y2;
}
temp_r--;
FlushMouseMsgBuffer();
goto Flag_DeleteRectangleAgain;//重复删除
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
/*3:改变矩形大小*/
else if (m.y <= 372)
{
Flag_ChoiceRectangleAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选中矩形
{
int i;
for (i = 0; i < temp_r; i++)
{
if (m.x >= 220 && m.y >= 60) //限制区域为作图区域
{
bool a = (fabs(m.x - Rectangle[i].x1) < 5);
bool b = (fabs(m.x - Rectangle[i].x2) < 5);
bool c = (fabs(m.y - Rectangle[i].y1) < 5);
bool d = (fabs(m.y - Rectangle[i].y2) < 5);
if ((a || b) && (c || d))//点击矩形任一顶点即选中
{
double k = (Rectangle[i].y2 - Rectangle[i].y1) / (Rectangle[i].x2 - Rectangle[i].x1);//长宽比
Again:
char ch;
ch = _getche();
if (ch == 'w') //键盘w增大
{
setlinecolor(BLACK);
rectangle(Rectangle[i].x1, Rectangle[i].y1, Rectangle[i].x2, Rectangle[i].y2);
Rectangle[i].x1 -= 50;
Rectangle[i].y1 -= 50 * k;
Rectangle[i].x2 += 50;
Rectangle[i].y2 += 50 * k;
setlinecolor(RED);
rectangle(Rectangle[i].x1, Rectangle[i].y1, Rectangle[i].x2, Rectangle[i].y2);
goto Again;
}
if (ch == 's') //键盘s减小
{
setlinecolor(BLACK);
rectangle(Rectangle[i].x1, Rectangle[i].y1, Rectangle[i].x2, Rectangle[i].y2);
Rectangle[i].x1 += 50;
Rectangle[i].y1 += 50 * k;
Rectangle[i].x2 -= 50;
Rectangle[i].y2 -= 50 * k;
setlinecolor(RED);
rectangle(Rectangle[i].x1, Rectangle[i].y1, Rectangle[i].x2, Rectangle[i].y2);
goto Again;
}
goto Flag_ChoiceRectangleAgain;
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,重新功能选择
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
/*4:移动矩形*/
else if (m.y <= 402)
{
Flag_MoveRectangleAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选择线段
{
int i;
for (i = 0; i < temp_r; i++) //筛选线段
{
if (m.x >= 220 && m.y >= 60)//限制鼠标移动区域为作图区域
{
bool a = (fabs(m.x - Rectangle[i].x1) < 5);
bool b = (fabs(m.x - Rectangle[i].x2) < 5);
bool c = (fabs(m.y - Rectangle[i].y1) < 5);
bool d = (fabs(m.y - Rectangle[i].y2) < 5);
if ((a || b) && (c || d))//点击矩形任一顶点即选中
{
double START_X, START_Y, END_X, END_Y;
START_X = m.x;
START_Y = m.y;
setlinecolor(BLACK);
rectangle(Rectangle[i].x1, Rectangle[i].y1, Rectangle[i].x2, Rectangle[i].y2);
while (START_X >= 220 && START_Y >= 60)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONUP)//左键弹起,获取终点
{
END_X = m.x;
END_Y = m.y;
if (END_X >= 220 && END_Y >= 60)
{
setlinecolor(RED);
double D_x = END_X - START_X;
double D_y = END_Y - START_Y;
Rectangle[i].x1 += D_x;
Rectangle[i].x2 += D_x;
Rectangle[i].y1 += D_y;
Rectangle[i].y2 += D_y;
rectangle(Rectangle[i].x1, Rectangle[i].y1, Rectangle[i].x2, Rectangle[i].y2);
goto Flag_MoveRectangleAgain;//重复选择线段移动
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
goto Flag_MoveAgain;//重新选择线段移动
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
}
/*作图区选择椭圆相关的操作*/
/*LINE: 513-725 椭圆操作*/
if (10 <= m.x && m.x <= 210 && 456 <= m.y && m.y <= 576)
{
/*1:放置椭圆*/
if (m.y <= 486)
{
Flag_EllipseAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,获取起点
{
START_X = m.x;
START_Y = m.y;
Ellipse[temp_e].x1 = m.x;
Ellipse[temp_e].y1 = m.y;
while (START_X >= 220 && START_Y >= 60)//确保起点在作图区内
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONUP)//左键弹起,获取终点
{
END_X = m.x;
END_Y = m.y;
Ellipse[temp_e].x2 = m.x;
Ellipse[temp_e].y2 = m.y;
if (END_X >= 220 && END_Y >= 60)//确保终点在作图区内
{
setlinecolor(RED);
ellipse(START_X, START_Y, END_X, END_Y);
temp_e++; //直线的数量加一
goto Flag_EllipseAgain; //重复画线
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键回到功能选择区域
goto Flag_ChoiceAgain;
}
}
/*2:删除椭圆*/
else if (m.y <= 516)
{
Flag_DeleteEAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,删除椭圆
{
int i;
for (i = 0; i < temp_e; i++) //遍历椭圆数组,寻找符合条件的直线
{
if (m.x >= 220 && m.y >= 60)//限制区域为作图区域
{
double evey = (Ellipse[i].y1 + Ellipse[i].y2) / 2;
bool a = (fabs(m.x - Ellipse[i].x1) < 5);
bool b = (fabs(m.x - Ellipse[i].x2) < 5);
bool c = (fabs(m.y - evey) < 5);
if ((a || b) && c)//点击椭圆左右任一顶点即选中
{
setlinecolor(BLACK);
ellipse(Ellipse[i].x1, Ellipse[i].y1, Ellipse[i].x2, Ellipse[i].y2);
for (int k = i; k < temp_e - 1; k++)//线性存储,所以后续直线需要向前移一位
{
Ellipse[k].x1 = Ellipse[k + 1].x1;
Ellipse[k].y1 = Ellipse[k + 1].y1;
Ellipse[k].x2 = Ellipse[k + 1].x2;
Ellipse[k].y2 = Ellipse[k + 1].y2;
}
temp_e--;
FlushMouseMsgBuffer();
goto Flag_DeleteEAgain;//重复删除
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
/*3:改变椭圆大小*/
else if (m.y <= 546)
{
Flag_ChoiceEAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选中椭圆
{
int i;
for (i = 0; i < temp_e; i++)
{
if (m.x >= 220 && m.y >= 60) //限制区域为作图区域
{
double evey = (Ellipse[i].y1 + Ellipse[i].y2) / 2;
bool a = (fabs(m.x - Ellipse[i].x1) < 10);
bool b = (fabs(m.x - Ellipse[i].x2) < 10);
bool c = (fabs(m.y - evey) < 10);
if ((a || b) && c)//点击椭圆左右任一顶点即选中
{
double k = (Ellipse[i].y2 - Ellipse[i].y1) / (Ellipse[i].x2 - Ellipse[i].x1);//长宽比
_Eagain:
char ch;
ch = _getche();
if (ch == 'w') //键盘w增大
{
setlinecolor(BLACK);
ellipse(Ellipse[i].x1, Ellipse[i].y1, Ellipse[i].x2, Ellipse[i].y2);
Ellipse[i].x1 -= 50;
Ellipse[i].y1 -= 50 * k;
Ellipse[i].x2 += 50;
Ellipse[i].y2 += 50 * k;
setlinecolor(RED);
ellipse(Ellipse[i].x1, Ellipse[i].y1, Ellipse[i].x2, Ellipse[i].y2);
goto _Eagain;
}
if (ch == 's') //键盘s减小
{
setlinecolor(BLACK);
ellipse(Ellipse[i].x1, Ellipse[i].y1, Ellipse[i].x2, Ellipse[i].y2);
Ellipse[i].x1 += 50;
Ellipse[i].y1 += 50 * k;
Ellipse[i].x2 -= 50;
Ellipse[i].y2 -= 50 * k;
setlinecolor(RED);
ellipse(Ellipse[i].x1, Ellipse[i].y1, Ellipse[i].x2, Ellipse[i].y2);
goto _Eagain;
}
goto Flag_ChoiceEAgain;
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,重新功能选择
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
/*4:移动椭圆*/
else if (m.y <= 576)
{
Flag_MoveEAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选择椭圆
{
int i;
for (i = 0; i < temp_e; i++) //筛选椭圆
{
if (m.x >= 220 && m.y >= 60)//限制鼠标移动区域为作图区域
{
double evey = (Ellipse[i].y1 + Ellipse[i].y2) / 2;
bool a = (fabs(m.x - Ellipse[i].x1) < 5);
bool b = (fabs(m.x - Ellipse[i].x2) < 5);
bool c = (fabs(m.y - evey) < 5);
if ((a || b) && c)//点击椭圆左右任一顶点即选中
{
double START_X, START_Y, END_X, END_Y;
START_X = m.x;
START_Y = m.y;
setlinecolor(BLACK);
ellipse(Ellipse[i].x1, Ellipse[i].y1, Ellipse[i].x2, Ellipse[i].y2);
while (START_X >= 220 && START_Y >= 60)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONUP)//左键弹起,获取终点
{
END_X = m.x;
END_Y = m.y;
if (END_X >= 220 && END_Y >= 60)
{
setlinecolor(RED);
double D_x = END_X - START_X;
double D_y = END_Y - START_Y;
Ellipse[i].x1 += D_x;
Ellipse[i].x2 += D_x;
Ellipse[i].y1 += D_y;
Ellipse[i].y2 += D_y;
ellipse(Ellipse[i].x1, Ellipse[i].y1, Ellipse[i].x2, Ellipse[i].y2);
goto Flag_MoveEAgain;//重复选择椭圆移动
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
goto Flag_MoveEAgain;//重新选择椭圆移动
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
}
/*作图区选择文字相关的操作*/
/*LINE: 731-916 矩形操作*/
/*文字*/
if (10 <= m.x && m.x <= 210 && 630 <= m.y && m.y <= 750)
{
if (m.y <= 660)
{
/*1:放置文字*/
Flag_WordAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,获取起点
{
START_X = m.x;
START_Y = m.y;
Word[temp_w].x = m.x;
Word[temp_w].y = m.y;
if (START_X >= 220 && START_Y >= 60)//确保起点在作图区内
{
settextcolor(RED);
gets_s(Word[temp_w].words);
settextstyle(wordsize, wordsize, NULL);
outtextxy(Word[temp_w].x, Word[temp_w].y, Word[temp_w].words);
temp_w++;
goto Flag_WordAgain; //重复写字
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
else if (m.y <= 690)
{
/*2:删除文字*/
Flag_DeleteWAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,删除文字
{
int i;
for (i = 0; i < temp_w; i++) //遍历文字数组,寻找符合条件的文字
{
if (m.x >= 220 && m.y >= 60)//限制区域为作图区域
{
if (fabs(m.x - Word[i].x) < 15 || fabs(m.y - Word[i].y)<15)//点击文字开头即选中
{
settextcolor(BLACK);
outtextxy(Word[i].x, Word[i].y, "can't see me !can't see me !can't see me !");
for (int k = i; k < temp_e - 1; k++)//线性存储,所以后续文字需要向前移一位
{
Word[k].x = Word[k + 1].x;
Word[k].y = Word[k + 1].y;
for (int t = 0; t<100; t++)
Word[k].words[t] = Word[k + 1].words[t];
}
temp_e--;
FlushMouseMsgBuffer();
goto Flag_DeleteWAgain;//重复删除
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
else if (m.y <= 720)
{
/*3:改变大小*/
Flag_ChoiceWAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选中文字
{
int i;
for (i = 0; i < temp_w; i++)
{
if (m.x >= 220 && m.y >= 60) //限制区域为作图区域
{
if (fabs(m.x - Word[i].x) < 15 || fabs(m.y - Word[i].y)<15)
{
int wsz = wordsize;
_Wagain:
char ch;
ch = _getche();
if (ch == 'w') //键盘w增大
{
outtextxy(Word[i].x, Word[i].y, " ");
wsz *= 2;
settextstyle(wsz, wsz, NULL);
outtextxy(Word[i].x, Word[i].y, Word[i].words);
goto _Wagain;
}
if (ch == 's') //键盘s减小
{
outtextxy(Word[i].x, Word[i].y, " ");
wsz /= 2;
settextstyle(wsz, wsz, NULL);
outtextxy(Word[i].x, Word[i].y, Word[i].words);
goto _Wagain;
}
goto Flag_ChoiceWAgain;
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,重新功能选择
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
else if (m.y <= 750)
{
/*4:移动文字*/
Flag_MoveWAgain:
while (true)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONDOWN) //单击左键,选择文字
{
for (int i = 0; i < temp_w; i++) //筛选文字
{
if (m.x >= 220 && m.y >= 60)//限制鼠标移动区域为作图区域
{
if (fabs(m.x - Word[i].x) < 15 && fabs(m.y - Word[i].y)<15)//点击文字起点即选中
{
double START_X, START_Y, END_X, END_Y;
START_X = m.x;
START_Y = m.y;
settextcolor(BLACK);
outtextxy(Word[i].x, Word[i].y, "can't see me!can't see me!can't see me!");
while (START_X >= 220 && START_Y >= 60)
{
m = GetMouseMsg();
if (m.uMsg == WM_LBUTTONUP)//左键弹起,获取终点
{
END_X = m.x;
END_Y = m.y;
if (END_X >= 220 && END_Y >= 60)
{
Word[i].x = END_X;
Word[i].y = END_Y;
settextcolor(RED);
outtextxy(END_X, END_Y, Word[i].words);
goto Flag_MoveWAgain;//重复选择文字移动
}
}
else if (m.uMsg == WM_RBUTTONUP)
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
goto Flag_MoveWAgain;//重新选择文字移动
}
}
}
}
else if (m.uMsg == WM_RBUTTONDOWN)//单击右键,回到功能选择界面
{
FlushMouseMsgBuffer();
goto Flag_ChoiceAgain;
}
}
}
}
}
}
_getch();
return 0;
}
运行截图
prob4:洗牌算法
实现代码
//遍历数组,遇到第i个元素时,产生一个i到n-1之间的随机数,然后两个位子的数互换。
#include
#include
#include
using namespace std;
void shuffle(int array[], int n)
{
srand(time(NULL));
for (int i = 0; i< n; i++)
{
int index = rand() % n;//产生一个随机位置
while(index < i)
{
index = rand() % n;//如果选中了之前选择过的位置,则重新选择
}
int temp = array[index];
array[index] = array[i];
array[i] = temp;
}
}
int main()
{
int a[100];
for (int i = 1; i<53; i++)
a[i - 1] = i;
shuffle(a, 52);
for (int i = 0; i<52; i++)
{
if (i % 13 == 0)
cout << endl;
cout << a[i] << " ";
}
cout << endl;
_getch();
return 0;
}
运行截图
prob6:快速排序
文件in.txt截图如下(内容由第四题程序制作。第一行为10000,其余为1~10000的随机组合)
实现代码
#include
#include
#include
#include
using namespace std;
int a[10000];
int n;
//double timeStart, timeExit;
void quicksort(int left, int right)
{
if (left > right)
return;
int baseAim = a[left]; //每个数组左边的数作为当前数组的基准数
int i = left;
int j = right;
while (i != j)//line:15~26实现对于一个基准数的完整挑选
{
while (a[j] >= baseAim && i < j)//从右向左寻找第一个比基准数小的数
j--;
while (a[i] <= baseAim && i < j) //从左向右寻找第一个比基准数大的数/从基准数开始
i++;
if (i < j)
{
int t = a[i];
a[i] = a[j];
a[j] = t;
}
}
a[left] = a[i];//
a[i] = baseAim;
quicksort(left, i - 1);//继续处理左边的
quicksort(i + 1, right);//继续处理右边的
}
int main()
{
freopen("in.txt", "r", stdin);//将1.txt文件中的数据定向到输入缓冲区
cin >> n;
for(int i = 0;i < n;i++)
cin >> a[i];
DWORD entry = GetTickCount();//获取quicksort函数运行之前的系统时间
quicksort(0,n-1);
Sleep(3000); //??结果刚好3000 ,岂不是函数时间只用了0?
DWORD exit = GetTickCount();//获取quicksort函数运行之后的系统时间
freopen("out.txt","w",stdout);
cout << "Time Consumption:";
printf("%lld\n",exit-entry);
for(int i = 0;i < n;i++)
cout << a[i] << " ";
cout << endl;
fclose(stdin);//关闭文件
fclose(stdout);
return 0;
}
out.txt的截图如下
prob7:归并法原理(融合法不会TT)
文件in.txt截图如下
实现代码
/*递归实现*/
#include
#include
#include
using namespace std;
void merge(int *a, int beg, int mid, int end)// 合并子序列
{
int i=beg, j=mid+1, cnt=0;
int *tmpArray=(int*)malloc((end-beg+1)*sizeof(int));
while(i<=mid && j<=end)
{
tmpArray[cnt++]=a[i]<=a[j]? a[i++]:a[j++];//注意此处。选中i则i自加j不自加
}
//line:16~23两个while最多只有一个还会被用到
while(i<=mid)
{
tmpArray[cnt++]=a[i++];
}
while(j<=end)
{
tmpArray[cnt++]=a[j++];
}
for(cnt=0, i=beg; i<=end; cnt++,i++)
{
a[i]=tmpArray[cnt];
}
}
void merge_sort(int*a, int beg, int end)//二路归并排序
{
if(beg> n;
for(int i = 0;i < n;i++)
cin >> a[i];
DWORD entry = GetTickCount();//获取quicksort函数运行之前的系统时间
merge_sort(a, 0, n-1);
Sleep(3000); //??结果刚好3000 ,岂不是函数时间只用了0?
DWORD exit = GetTickCount();//获取quicksort函数运行之后的系统时间
freopen("out.txt","w",stdout);
cout << "Time Consumption:";
printf("%lld\n",exit-entry);
for(int i = 0;i < n;i++)
cout << a[i] << " ";
cout << endl;
fclose(stdin);//关闭文件
fclose(stdout);
return 0;
}
out.txt的截图如下
END...