文章目录:
一:题目要求
C++GUI实现逆序排列 77页 解决一些小的n值谜题,将会给你指明正确方向 188页 1.基于Windows GUI(图形用户界面)的应用程序 2.让用户通过观看和操作,理解数据结构和算法的内部过程 3.设计相应的剧情、玩法、视觉元素、背景音乐与事件音效等 4.动画展示:数据结构和算法的每一步变化过程
题目
问题: 有n张卡片排成一行,并且有n个不同的数字写在卡片上(每张卡片上一个),使得卡片呈降序排列状态 现在允许你交换任何一对卡片的位置,只要它们之间只有一张卡片即可 对于什么样的n值,在这样一组操作序列以后,能使得卡片呈升序排列? 如果这样n值存在的话,请设计使得交换次数最小的算法 解析: n张卡片排列成一排,每个都有数字,初始为降序 交换一对卡片(中间必须隔一张),那么经过多少次交换成升序排列 求:如果存在n 需要交换多少次
答案
二:相关代码
1.倒序排序算法动画项目代码
#include <iostream> #include <stdio.h> //头文件 #include <easyx.h> #include <stdlib.h> #include <windows.h> #include <graphics.h> //图形库头文件 #include <conio.h> //案件操作防止闪屏 getch #include <mmsystem.h> //多媒体库 #pragma comment(lib,"winmm.lib") //加载静态库文件 #pragma warning(default: 4996) //鼠标交互 将报警设置为默认 #include <ctime> using namespace std; int n =9; //卡片数 int liu=(n+1)/2; //卡片数和位置数关系 void fristgui(); //第一界面按钮 void bk(); //第二界面背景 void dongtai(); //第二界面按钮 void loadResource2(); void loadResource1(); void title(); void endnum(); /**第一界面按钮**/ void fristgui() { //1.移动矩形 for(int i=80;i<630;i++) { for (int j = 20; j < 300; j++) { solidrectangle(20,200,i,j); } } //2.准备文字 char beginString[]="开始排列"; char closeString[]="退出排列"; char tishiString[]="排列说明"; char tipsString[]="倒序排列算法"; char nameString[]="物联网3班刘鑫磊"; //3.界面布局 //set设置 fill填充 color颜色 LIGHT:淡 setfillcolor(CYAN); //4.画按钮矩形 solidrectangle(240,40,380,90); solidrectangle(240,100,380,150); solidrectangle(240,160,380,160+50); //5.文字布局 settextcolor(BLACK); setbkmode(TRANSPARENT); //去掉文字背景 settextstyle(30,0,"楷体"); outtextxy(240+15,40+10,tishiString); outtextxy(240+15,100+10,beginString); outtextxy(240+15,160+10,closeString); outtextxy(255,50,tishiString); outtextxy(220,250,tipsString); outtextxy(200,310,nameString); //6.鼠标交互 while(1) { MOUSEMSG m = GetMouseMsg(); if(m.x>=240 && m.x<=380 && m.y>=100 && m.y<=150) { setlinecolor(RED); rectangle(240-5,100-5,380+5,150+5); //开始游戏 if(m.uMsg==WM_LBUTTONDOWN) { break; } }else if (m.x>=240 && m.x<=380 && m.y>=160 && m.y<=210) { setlinecolor(RED); rectangle(240-5,160-5,380+5,210+5); //退出游戏 if(m.uMsg==WM_LBUTTONDOWN) { exit(0); } }else if (m.x>=240 && m.x<=380 && m.y>=40 && m.y<=90) { setlinecolor(RED); rectangle(240-5,40-5,380+5,90+5); //游戏说明 if(m.uMsg==WM_LBUTTONDOWN) { setbkmode(0); //去掉文字背景 settextcolor(BLUE); //设置文字颜色 settextstyle(15,0,TEXT("楷体")); //(高,宽<0为自适应>,字体) outtextxy(10,350,"排列说明:"); outtextxy(70,370,"n张卡片排列成一排,每个都有数字,初始为降序交换一对卡片(中间必须隔一张),"); outtextxy(70,390,"那么经过多少次交换成升序排列,如果存在这样n张卡片,那么需要交换多少次"); } } else { setlinecolor(WHITE); rectangle(240-5,100-5,380+5,150+5); rectangle(240-5,160-5,380+5,210+5); rectangle(240-5,40-5,380+5,90+5); } } } /**第二界面背景**/ void bk() { //1.背景 //一:图片 //1.创建一个窗口 属性:宽高 658 369 initgraph(1300,800); //2.显示图片到窗口上面,为图片取名字 IMAGE bei; //3.把名字分配给图片 loadimage(&bei,"bei.jpg",1300,800); //显示图片:图片坐标 putimage(0,0,&bei); //2.音乐 //播放音乐 //打开 alias起别名 mciSendString("open 1.mp3 alias music",0,0,0); //播放 mciSendString("play music repeat",0,0,0); //3.移动条 IMAGE niao; //把名字分配给图片 loadimage(&niao,"brid.jpg",60,60); //左 for (int i = 0; i < 1250; i++) { putimage(0+i,0,&niao); Sleep(1); } //下 for (int i = 0; i < 798; i++) { putimage(1250,0+i,&niao); Sleep(1); } //右 for (int i = 0; i < 1250; i++) { putimage(1250-i,740,&niao); Sleep(1); } //上 for (int i = 0; i < 750; i++) { putimage(0,750-i,&niao); Sleep(1); } } /**第二界面按钮**/ void dongtai() { //1.准备文字 char beginString[]="动态演示"; //2.界面布局 //set设置 fill填充 color颜色 LIGHT:淡 setfillcolor(CYAN); //CYAN //3.画椭圆 solidellipse(570,180,720,230); //4.文字布局 settextcolor(BLACK); setbkmode(TRANSPARENT); //去掉文字背景 settextstyle(30,0,"楷体"); outtextxy(570+15,180+10,beginString); //5.鼠标交互 while(1) { MOUSEMSG m = GetMouseMsg(); if(m.x>=570 && m.x<=720 && m.y>=180 && m.y<=230) { setlinecolor(RED); rectangle(570-5,180-5,720+5,230+5); //开始游戏 if(m.uMsg==WM_LBUTTONDOWN) { break; } } else { setlinecolor(CYAN); rectangle(570-5,180-5,720+5,230+5); } } } //第二界面:排序每一步 void loadResource2() { //图片 LPCTSTR arr[9] = {"one.PNG","two.PNG","three.PNG","four.PNG","five.PNG","six.PNG","seven.PNG","eight.PNG","nine.PNG"}; // int * b = new int[n]; for(int i=n;i>0;i--) //i =9 8 7 6 5 4 3 2 1 { b[n-i] = i; //n-i=0 1 2 3 4 5 6 7 8 //b } int y=60; //排序 for (int i=0;i<n-1;i++)//每次最大元素就像气泡一样浮到数组的最后 { //输出图片数字 for (int i = 0; i < n; i++) { IMAGE img; //把名字分配给图片 loadimage(&img,arr[b[i]-1],50,50);//图片 8 7 6 5 4 3 2 1 0 //显示图片: putimage(270+90*i,y+200,&img); Sleep(200); } //向下 y+=60; int j; if(i%2==0)j=0; //偶数 else j=1; //奇数 int max_index = j; //默认最大值 for(;j<n-i;j+=2) //依次比较相邻的两个元素,使较大的那个向后移 { //交换 if(b[j]<b[max_index]) { int temp = b[max_index]; b[max_index] = b[j]; b[j] = temp; max_index = j; //当前最大值 } } } } //第二界面:排序动态 void loadResource1() { //正序输出 LPCTSTR arr[9] = {"one.PNG","two.PNG","three.PNG","four.PNG","five.PNG","six.PNG","seven.PNG","eight.PNG","nine.PNG"}; int * b = new int[n]; for(int i=n;i>0;i--) { b[n-i] = i; } int y=60; //排序 for (int i=0;i<n-1;i++)//每次最大元素就像气泡一样浮到数组的最后 { //输出 y=60; int j; if(i%2==0)j=0; //偶数 else j=1; //奇数 int max_index = j; //默认最大值 for(;j<n-i;j+=2) //依次比较相邻的两个元素,使较大的那个向后移 { //交换 if(b[j]<b[max_index]) { int temp = b[max_index]; b[max_index] = b[j]; b[j] = temp; max_index = j;//当前最大值 } for (int i = 0; i < n; i++) { IMAGE img; //把名字分配给图片 loadimage(&img,arr[b[i]-1],50,50); //显示图片: putimage(270+90*i,y+50,&img); Sleep(200); } } } } //彩色提示标题 void title() { srand((unsigned)time(NULL)); while(1) //检测按键函数,输入按键返回1,不输返回0,我们这里要相反的 { setcolor(RGB(rand()%256,rand()%256,rand()%256)); settextstyle(50,0,TEXT("楷体")); //RGB是三原色红,绿,蓝,颜色范围是0~255 outtextxy(480,0,"排序已经完成"); Sleep(50); } } void endnum() { //卡片数 char num3[100]; sprintf(num3, "%d", n); setbkmode(0); //去掉文字背景 settextcolor(BLACK); //设置文字颜色 settextstyle(25,0,TEXT("楷体")); //(高,宽<0为自适应>,字体) outtextxy(110,65,"存在这样的卡片数(你输入的数)为:"); outtextxy(550,65,num3); //(x,y,内容) //交换次数 char num1[100]; int num2=2*liu+1; //次数和 sprintf(num1, "%d",( num2-1)* num2-1/4); setbkmode(0); //去掉文字背景 settextcolor(BLACK); //设置文字颜色 settextstyle(25 ,0,TEXT("楷体")); //(高,宽<0为自适应>,字体) outtextxy(670,65,"按照规则采用冒泡排序交换次数最小为:"); outtextxy(1130,65,num1); //(x,y,内容) outtextxy(1170,65,"次"); } int main() { initgraph(650,420); //第一界面大小 setbkcolor(CYAN); //第一界面颜色 cleardevice(); //用于图形显示 fristgui(); //第一界面按钮 if (n%2==0) //判断是不是偶数 exit(0); bk(); //第二界面背景 endnum(); loadResource2(); //第二界面依次排序 dongtai(); //动态按钮 loadResource1(); //第二界面动态 title(); while(1); //第一界面进入 _getch(); closegraph(); system("pause"); return 0; }
2.冒泡排序
//冒泡插入排序 for (int i=0;i<num-1;i++)//每次最大元素就像气泡一样浮到数组的最后 { for(int j=0;j<num-1-i;j++) //依次比较相邻的两个元素,使较大的那个向后移 { if(a[j]>a[j+1]) //如果条件改为arr[j] >= arr[j+1] 则变为不稳定的排序算法 { int temp=a[j]; a[j] = a[j+1]; a[j+1] = temp; } } }
3.题目命令行形式
#include <iostream> #include <cmath> using namespace std; int num; int a[1000] ; //定义数组长度 int i,j; //定义变量 void change() { //冒泡插入排序 for (int i=0;i<num-1;i++)//每次最大元素就像气泡一样浮到数组的最后 { for(int j=0;j<num-1-i;j++) //依次比较相邻的两个元素,使较大的那个向后移 { if(a[j]>a[j+1]) //如果条件改为arr[j] >= arr[j+1] 则变为不稳定的排序算法 { int temp=a[j]; a[j] = a[j+1]; a[j+1] = temp; } } } } int main(){ cout <<"请输入元素的个数:"; cin>>num; if(num%2==0) { cout<<"抱歉偶数不能运行成功!因为没有答案,第1个最大的数永远到不了最后形成倒序"<<endl; }else { int liu=(num+1)/2; cout<<"提示:请降序输入数字!"<<endl; //键盘循环输入数 for (i = 0; i < num; i++) { cout<< "请输入"<<num<<"个整数存到数组,第"<<i+1<<"次输入为:"; cin >>a[i]; } //输出键盘的个数 cout<<"你输入的数组为:"; for(int i=0;i<num;i++) { cout<<a[i]<<" "; } cout<<endl; cout << "-----------------------------------------------------"<<endl; for (int i = 1; i < num; i++) { if (i%2==1) { change(); }else { change(); } } cout<<"其冒泡排序后为:"; for(int i=0;i<num;i++) { cout<<a[i]<<" "; } cout<<endl; cout<<endl; cout<<"如果有"<<num<<"张卡片,那么采用冒泡排序将要交换:"<<2*liu+1<<"次!"<<endl; } system("pause"); return 0; }
三:网上资源
C/C++游戏开发教程:C语言实现—飞翔的小鸟(可视化编程+背景音乐+分数+边界设置+小鸟碰撞)
【C/C++编程】GUI/GDI绘图技术,图形化编程终极篇!你所看到的一切皆可进行人机交互!_哔哩哔哩_bilibili 图片移动
四:基础知识
1.颜色
红色:255,0,0 绿色:0,255,0 蓝色:0,0,255 黄色:255,255,0 紫色:255,0,255
2.形状
{//语句块 hdc = BeginPaint(hWnd, &ps); //画矩形 Rectangle(hdc,0,0,200,100); //正方形 Rectangle(hdc,10,10,200,200); //画圆 Ellipse(hdc,200,200,400,400); //椭圆 Ellipse(hdc,300,300,400,100); //画线 MoveToEx(hdc,100,100,NULL); LineTo(hdc,300,200); }
3.画笔
//1.画笔 HPEN hpen1,hpen2,hpen3,hpen4,hpen5; //创建画笔第一种方式 //啥子笔,宽度,颜色 //hpen1=CreatePen(PS_SOLID,4,RGB(255,0,0)); //实线 //红色:255,0,0 //hpen2=CreatePen(PS_DASH,1,RGB(0,255,0)); //虚线 //绿色:0,255,0 1才是虚线大于九不是了 //hpen3=CreatePen(PS_DASHDOT,1,RGB(0,0,255)); //线点 //蓝色:0,0,255 //hpen4=CreatePen(PS_DASHDOTDOT,1,RGB(0,0,255));//线点点 //蓝色:0,0,255 //创建画笔第二种方式 LOGPEN logPen; logPen.lopnStyle=PS_SOLID; logPen.lopnWidth.x=5; logPen.lopnColor=RGB(255,255,0); //黄色 hpen5=CreatePenIndirect(&logPen); //拿笔 //SelectObject(hdc,hpen1); //SelectObject(hdc,hpen2); //SelectObject(hdc,hpen3); //SelectObject(hdc,hpen4); SelectObject(hdc,hpen5); //正方形 Rectangle(hdc,10,10,200,200);
4.画刷
//2.画刷(填充颜色 一个封闭区域) 白色默认画刷 //创建画刷 HBRUSH hBrush1=CreateSolidBrush(RGB(255,0,255)); //紫色 //拿画刷 SelectObject(hdc,hBrush1); //正方形 Rectangle(hdc,10,10,200,200);
5.画坦克
#define TANK_WIDTH 40//坦克的宽度 #define TANK_HEIFHT 40//坦克的高度 //坦克 typedef struct _Trank { int x; int y; }Tank;
//定义坦克 static Tank tank; switch (message) { case WM_CREATE://窗口创建消息 { //获取窗口的宽和高 RECT rect; GetClientRect(hWnd,&rect); tank.x=(rect.right-rect.left)/2; tank.y=(rect.bottom-rect.top)- (TANK_HEIFHT/2); } break;
//绘制坦克 void DrawTank(HDC hDC,Tank tank);
//绘制坦克 void DrawTank(HDC hDC,Tank tank) { //画刷 HBRUSH hBrush=CreateSolidBrush(RGB(255,238,114)); HBRUSH hOldBrush=(HBRUSH)SelectObject(hDC,hBrush); //画矩形 Rectangle(hDC,tank.x-TANK_WIDTH/2,tank.y-TANK_HEIFHT/2,tank.x+TANK_WIDTH/2,tank.y+TANK_HEIFHT/2); SelectObject(hDC,hOldBrush); }
case WM_KEYDOWN://键盘按下 switch (wParam) { case VK_LEFT: tank.x -=5; break; case VK_RIGHT: tank.x +=5; break; case VK_UP: tank.y -=5; break; case VK_DOWN: tank.y +=5; break; } //刷新 InvalidateRect(hWnd,NULL,TRUE); break;