程序设计综合实训报告整理

姓名:杨xx

学号:17272xxx/

运行环境:VS2017/DevC++

 

  • 模块化程序与递归函数设计

prob1:整数的划分

思路

分析示例可得如下划分规律

1.第一个划分数为n-1~1

2.每一次划分后的余下部分不得大于前一个划分数。

故设置一个全局数组用于动态存储每一次划分的结果

然后在一个for循环中先降序划分出来第一个数x,再将余下部分n-x进行再划分。

因为要满足2规律方可使划分结果不重复,所以对划分数的划分需从划分数~1,当划分后余下的部分<=0时终止划分,输出本次划分结果。

代码实现:

#include<iostream>
#include<conio.h>
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<iostream>
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<iostream>
#include<stdlib.h>
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。

步骤

  1. 输入n
  2. 动态创建两个长度为n的链表
  3. 加法运算,需要一个长度为n的链表存储结果
  4. 减法运算,需要一个长度为n的链表存储结果
  5. 乘法运算,需要一个长度为2n的链表存储结果
  6. 将加/减/乘的结果输出

 

代码实现

#include<iostream>
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 <<endl;
	else if(p->coe > 0)
		cout << "+" << p->coe <<endl;
	else
		;
	cout << endl;
}

/*多项式求和,返回结果多项式的头指针*/
linklist *SumPOOI(linklist *ls_1,linklist *ls_2,int n)//n为最高次数 
{
	linklist *SUM,*Tail;
	Tail = SUM = CreateEmptyPOOI(n);
	while(SUM->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. 可设置一个循环,在循环里设置一个初始为0°,每一次增加20°的角度变量(因为要用到sin和cos函数所以需转换为弧度制),再对每一次旋转后进行画线操作。
  2. 分析每一次的画线操作,可得到如下相同的画线规律

沿当前角度(第1步骤中的角度)画线->逆时针旋转60°->画线->逆时针旋转-120°->画线->逆时针旋转-60°->画线->逆时针旋转120°->画线

此步骤在draw函数中实现

  1. 旋转角度函数turn
  2. 移动画线的起始坐标函数move
  3. 沿特定角度画线函数forward

实现代码

#include<graphics.h>
#include<conio.h>
#include<cmath>
#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 <graphics.h>
#include <conio.h>
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 <conio.h>
#include <graphics.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <Windows.h>
#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<iostream>
#include<conio.h>
#include<graphics.h>
#include<math.h>

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±50y±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±50y±50×长宽比k”w”伸长/w”   缩小

      椭圆:检索到椭圆后,将椭圆外接矩形的左上和右下顶点放大,x±50y±50×外接矩形的长宽比       k”w”伸长/w“缩小

    ///

(4)移动矩形/椭圆:

    /

    //

    ///

文字部分与三个图形部分类似,唯一的区别在于文字的信息存储除起始坐标外还需记录文字的信息。文字部分的录入参照本专题第四题”模拟文字录入”。

实现代码

#include<iostream>
#include<conio.h>
#include<graphics.h>
#include<stdio.h>
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 <iostream>    
#include<conio.h>
#include <time.h>  
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<iostream>
#include<stdio.h> 
#include<stdio.h>
#include<windows.h>
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<iostream>
#include<malloc.h>
#include<windows.h>
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<end)
  	{
	   	int mid=(beg+end)/2;		//左右两部分分解
	   	merge_sort(a, beg, mid);	//对左半部分拆分
	   	merge_sort(a, mid+1, end);	//对右半部分拆分 
   		merge(a, beg, mid, end);	//左右两部分排序并合并
	}
}

int main()
{
	int n;
	int a[10000];
 	
 	freopen("in.txt", "r", stdin);//将1.txt文件中的数据定向到输入缓冲区 
	cin >> 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...

  • 5
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值