C++游戏编程--游戏名称:拼图盒子(爷青回)

 程序名称:拼图盒子

 编译环境:Mictosoft Visual Studio 2019, EasyX_2021

作  者:代码骑士<[email protected]>

最后修改:2021-11-18

游戏示例:

目录

 第一步:生成九个不相同的随机数存入二维数组。

第二步:绘制九宫格与颜色填充。

第三步:鼠标点击实现方块移动。

第四步:测试方块移动。

第五步:加载图片。

第六步:加载音乐。

第七步:程序的改进。

第一步:生成九个不相同的随机数存入二维数组。

 第二步:绘制九宫格与颜色填充。

 第三步:鼠标点击实现方块移动。

第四步:测试方块移动。

 第五步:加载图片。

 第六步:加载音乐。

 第七步:程序的改进。


====================================================================》》》

第一步:生成九个不相同的随机数存入二维数组。

(1)生成1~9的随机数:

参考了百度上面某位大佬的经典之作:

void nineDiffnum()
{
	//先是把数组a赋值1—9,然后产生1--9的随机数,作为数组a的下标,赋值到temp数组。
	srand((int)time(0));//使用随机数种子,每次生成不同的随机数
	int a[9];
	int i, index, x = 0;
	for (i = 0; i < 9; i++)
		a[i] = i + 1;
	for (i = 0; i < 9;)
	{
		index = rand() % 9;
		if (a[index] != 0)
		{
			temp[i] = a[index];
			a[index] = 0;
			++i;
		}
	}
}

上述代码中我的temp数组是全局变量,所以函数中没有定义。

为了方便编程,二维数组也设成了全局变量。

(2)将一维数组中的随机数导入二维数组:

void createPicture(int* a)//将一维数组中的数存入二维数组
{
	int it = -1;

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			Picture[i][j] = a[++it];
		}
	}
}

 第二步:绘制九宫格与颜色填充。

(1)编写绘图函数:

(1)先让除了数字9以外的数字皆涂成红色。

void Show()
{
	cleardevice();

	int i, j;

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			if (Picture[i][j] != 9)
			{
				setfillcolor(RED);
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
		}
	}
	FlushBatchDraw();

}

示例:

 第三步:鼠标点击实现方块移动。

(1)首先,引入鼠标操作:

目的:让鼠标在特定的区域内,点击左键或右键发生特定变化。

while (true) {
		ExMessage m;//定义一个消息变量
		m = getmessage(EM_MOUSE);//获取鼠标消息
		switch (m.message)
		{
		case WM_MOUSEMOVE:
			// 鼠标移动的时候画红色的小点
			putpixel(m.x, m.y, RED);
			break;

		case WM_LBUTTONDOWN://鼠标点击左键
			// 画一个小方块
			if (m.x >= 0 && m.x <= 200 && m.y>=0&&m.y<=200)
			{
				int i = 0, j = 0;
				m.x = i;
				m.y = j;
				setfillcolor(BLACK);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			break;

		case WM_RBUTTONUP:
			return;	// 按鼠标右键退出程序
		}
	}

第四步:测试方块移动。

(1)给从1~9的方块不同的颜色。点击有色方块,该方块会移动到无色区域。

void Show()
{
	cleardevice();

	int i, j;

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			if (Picture[i][j] == 1)
			{
				setfillcolor(BLUE);
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 2)
			{
				setfillcolor(GREEN);
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 3)
			{
				setfillcolor(YELLOW);
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 4)
			{
				setfillcolor(RGB(122,122,122));
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 5)
			{
				setfillcolor(RGB(250, 250, 250));
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 6)
			{
				setfillcolor(RED);
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 7)
			{
				setfillcolor(RGB(0, 122, 122));
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 8)
			{
				setfillcolor(RGB(122, 0, 122));
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
			if (Picture[i][j] == 9)
			{
				setfillcolor(BLACK);
				setlinecolor(BLUE);
				fillrectangle(j * 200, i * 200, (j + 1) * 200, (i + 1) * 200);
			}
		}
	}
	FlushBatchDraw();

}

(2)有色块与无色块互换位置,此程序无色块默认是数字9所在的区域。

示例中,黑色为数字9所在的无色块。

(3)判断方块移动需要判断每个方块是否与无色块相邻,若相邻,点击此块,则与无色块进行交换,算法代码:

在此给出,第一排第一个方块的判断,剩余八个与之同理。

case WM_LBUTTONDOWN:
			//第一排:
			if (m.x >= 0 && m.x <= 200 && m.y >= 0 && m.y <= 200)//鼠标在第一个格子时:判断2、4格子是否为九
			{
				if (Picture[0][1] == 9)//1、2换位
				{
					int temp = Picture[0][1];
					Picture[0][1] = Picture[0][0];
					Picture[0][0] = temp;

					Show();//更新图片
				}
				else if (Picture[1][0] == 9)//1、4换位
				{
					int temp = Picture[1][0];
					Picture[1][0] = Picture[0][0];
					Picture[0][0] = temp;

					Show();//更新图片
				}
			}

 第五步:加载图片。

把正方形的照片切割成9块,依次导入和放在相应位置。

(1)加载图片

IMAGE s1, s2, s3, s4, s5, s6, s7, s8, s9;
void Start()
{
	initgraph(600, 600);
	loadimage(&s1, "s1.jpg", 200, 200);
	loadimage(&s2, "s2.jpg", 200, 200);
	loadimage(&s3, "s3.jpg", 200, 200);
	loadimage(&s4, "s4.jpg", 200, 200);
	loadimage(&s5, "s5.jpg", 200, 200);
	loadimage(&s6, "s6.jpg", 200, 200);
	loadimage(&s7, "s7.jpg", 200, 200);
	loadimage(&s8, "s8.jpg", 200, 200);
	//loadimage(&s9, "s9.jpg", 200, 200);
}

 (2)放置图片

注意:图片坐标位置不要算错!!!

for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			if (Picture[i][j] == 1)
			{
				putimage(j * 200, i * 200, &s1);
			}
			else if (Picture[i][j] == 2)
			{
				putimage(j * 200, i * 200, &s2);
			}
			else if (Picture[i][j] == 3)
			{
				putimage(j * 200, i * 200, &s3);
			}
			else if (Picture[i][j] == 4)
			{
				putimage(j * 200, i * 200, &s4);
			}
			else if (Picture[i][j] == 5)
			{
				putimage(j * 200, i * 200, &s5);
			}
			else if (Picture[i][j] == 6)
			{
				putimage(j * 200, i * 200, &s6);
			}
			else if (Picture[i][j] == 7)
			{
				putimage(j * 200, i * 200, &s7);
			}
			else if (Picture[i][j] == 8)
			{
				putimage(j * 200, i * 200, &s8);
			}
			else if (Picture[i][j] == 9)
			{
				putimage(j * 200, i * 200, &s9);
			}
		}
	


 示例:

 第六步:加载音乐。

	#pragma comment(lib,"Winmm.lib")
    mciSendString(_T("open 121.mp3 alias bkmusic"), NULL, 0, NULL);//播放音乐
	mciSendString(_T("play bkmusic repeat"), NULL, 0, NULL);//循环播放
    mciSendString(_T("close bkmusic"), NULL, 0, NULL);//停止播放

 完整程序代码:

///
// 程序名称:拼图盒子
// 编译环境:Mictosoft Visual Studio 2019, EasyX_2021
// 作  者:代码骑士<[email protected]>
// 最后修改:2021-11-18
//
#include<iostream>
#include<cstdlib>
#include<ctime>
#define random(x)rand()%x

#include<graphics.h>
#include<conio.h>

using namespace std;

//全局变量

int temp[9] = { 0 };

int Picture[4][4];

IMAGE s1, s2, s3, s4, s5, s6, s7, s8, s9;


//Tip:因为在二位数组中判断数据重复的时间复杂度是O(n2)一维数组是O(n),所以先把随机数存入一维数组中好进行判断随机数是否重复
void createPicture(int* a)//将一维数组中的数存入二维数组
{
	int it = -1;

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			Picture[i][j] = a[++it];
		}
	}
}

void PrintPic()
{
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			cout << Picture[i][j];
		}
		cout << endl;
	}
}

void nineDiffnum()
{
	//先是把数组a赋值1—9,然后产生1--9的随机数,作为数组a的下标,赋值到temp数组。
	srand((int)time(0));//使用随机数种子,每次生成不同的随机数
	int a[9];
	int i, index, x = 0;
	for (i = 0; i < 9; i++)
		a[i] = i + 1;
	for (i = 0; i < 9;)
	{
		index = rand() % 9;
		if (a[index] != 0)
		{
			temp[i] = a[index];
			a[index] = 0;
			++i;
		}
	}
}

void Start()
{
	initgraph(600, 600);
	loadimage(&s1, "s1.jpg", 200, 200);
	loadimage(&s2, "s2.jpg", 200, 200);
	loadimage(&s3, "s3.jpg", 200, 200);
	loadimage(&s4, "s4.jpg", 200, 200);
	loadimage(&s5, "s5.jpg", 200, 200);
	loadimage(&s6, "s6.jpg", 200, 200);
	loadimage(&s7, "s7.jpg", 200, 200);
	loadimage(&s8, "s8.jpg", 200, 200);
	//loadimage(&s9, "s9.jpg", 200, 200);
}

void Show()
{
	cleardevice();

	int i, j;

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			if (Picture[i][j] == 1)
			{
				putimage(j * 200, i * 200, &s1);
			}
			else if (Picture[i][j] == 2)
			{
				putimage(j * 200, i * 200, &s2);
			}
			else if (Picture[i][j] == 3)
			{
				putimage(j * 200, i * 200, &s3);
			}
			else if (Picture[i][j] == 4)
			{
				putimage(j * 200, i * 200, &s4);
			}
			else if (Picture[i][j] == 5)
			{
				putimage(j * 200, i * 200, &s5);
			}
			else if (Picture[i][j] == 6)
			{
				putimage(j * 200, i * 200, &s6);
			}
			else if (Picture[i][j] == 7)
			{
				putimage(j * 200, i * 200, &s7);
			}
			else if (Picture[i][j] == 8)
			{
				putimage(j * 200, i * 200, &s8);
			}
			else if (Picture[i][j] == 9)
			{
				putimage(j * 200, i * 200, &s9);
			}
		}
	}
	FlushBatchDraw();

}


void Player()
{
	while (true) {
		ExMessage m;//定义一个消息变量
		m = getmessage(EM_MOUSE);//获取鼠标消息
		switch (m.message)
		{
		case WM_MOUSEMOVE:
			// 鼠标移动的时候画红色的小点
			putpixel(m.x, m.y, RED);
			break;

		case WM_LBUTTONDOWN:
			//第一排:
			if (m.x >= 0 && m.x <= 200 && m.y >= 0 && m.y <= 200)//鼠标在第一个格子时:判断2、4格子是否为九
			{
				if (Picture[0][1] == 9)//1、2换位
				{
					int temp = Picture[0][1];
					Picture[0][1] = Picture[0][0];
					Picture[0][0] = temp;

					Show();//更新图片
				}
				else if (Picture[1][0] == 9)//1、4换位
				{
					int temp = Picture[1][0];
					Picture[1][0] = Picture[0][0];
					Picture[0][0] = temp;

					Show();//更新图片
				}
			}
			else if (m.x >= 200 && m.x <= 400 && m.y >= 0 && m.y <= 200)//鼠标在第二个格子时:判断1、3、5格子是否为九
			{
				if (Picture[0][0] == 9)//2、1换位
				{
					int temp = Picture[0][0];
					Picture[0][0] = Picture[0][1];
					Picture[0][1] = temp;

					Show();//更新图片
				}
				else if (Picture[0][2] == 9)//2、3换位
				{
					int temp = Picture[0][2];
					Picture[0][2] = Picture[0][1];
					Picture[0][1] = temp;

					Show();//更新图片
				}
				else if (Picture[1][1] == 9)//2、5换位
				{
					int temp = Picture[1][1];
					Picture[1][1] = Picture[0][1];
					Picture[0][1] = temp;

					Show();//更新图片
				}
			}
			else if (m.x >= 400 && m.x <= 600 && m.y >= 0 && m.y <= 200)//鼠标在第三个格子时:判断2、6格子是否为九
			{
				if (Picture[0][1] == 9)//3、2换位
				{
					int temp = Picture[0][1];
					Picture[0][1] = Picture[0][2];
					Picture[0][2] = temp;

					Show();//更新图片
				}
				else if (Picture[1][2] == 9)//3、6换位
				{
					int temp = Picture[1][2];
					Picture[1][2] = Picture[0][2];
					Picture[0][2] = temp;

					Show();//更新图片
				}
			}
			//第二排:
			else if (m.x >= 0 && m.x <= 200 && m.y >= 200 && m.y <= 400)//鼠标在第四个格子时:判断1、5、7格子是否为九
			{
				if (Picture[0][0] == 9)//4、1换位
				{
					int temp = Picture[0][0];
					Picture[0][0] = Picture[1][0];
					Picture[1][0] = temp;

					Show();//更新图片
				}
				else if (Picture[1][1] == 9)//4、5换位
				{
					int temp = Picture[1][1];
					Picture[1][1] = Picture[1][0];
					Picture[1][0] = temp;

					Show();//更新图片
				}

				else if (Picture[2][0] == 9)//4、7换位
				{
					int temp = Picture[2][0];
					Picture[2][0] = Picture[1][0];
					Picture[1][0] = temp;

					Show();//更新图片
				}
			}
			else if (m.x >= 200 && m.x <= 400 && m.y >= 200 && m.y <= 400)//鼠标在第五个格子时:判断2、4、6、8格子是否为九
			{
				if (Picture[0][1] == 9)//5、2换位
				{
					int temp = Picture[0][1];
					Picture[0][1] = Picture[1][1];
					Picture[1][1] = temp;

					Show();//更新图片
				}
				else if (Picture[1][0] == 9)//5、4换位
				{
					int temp = Picture[1][0];
					Picture[1][0] = Picture[1][1];
					Picture[1][1] = temp;

					Show();//更新图片
				}

				else if (Picture[1][2] == 9)//5、6换位
				{
					int temp = Picture[1][2];
					Picture[1][2] = Picture[1][1];
					Picture[1][1] = temp;

					Show();//更新图片
				}
				else if (Picture[2][1] == 9)//5、8换位
				{
					int temp = Picture[2][1];
					Picture[2][1] = Picture[1][1];
					Picture[1][1] = temp;

					Show();//更新图片
				}
			}
			else if (m.x >= 400 && m.x <= 600 && m.y >= 200 && m.y <= 400)//鼠标在第六个格子时:判断3、5、9格子是否为九
			{
				if (Picture[0][2] == 9)//6、3换位
				{
					int temp = Picture[0][2];
					Picture[0][2] = Picture[1][2];
					Picture[1][2] = temp;

					Show();//更新图片
				}
				else if (Picture[1][1] == 9)//6、5换位
				{
					int temp = Picture[1][1];
					Picture[1][1] = Picture[1][2];
					Picture[1][2] = temp;

					Show();//更新图片
				}

				else if (Picture[2][2] == 9)//6、9换位
				{
					int temp = Picture[2][2];
					Picture[2][2] = Picture[1][2];
					Picture[1][2] = temp;

					Show();//更新图片
				}
			}
			//第三排:
			else if (m.x >= 0 && m.x <= 200 && m.y >= 400 && m.y <= 600)//第七个格子:判断4、8是否为九
			{
				if (Picture[1][0] == 9)//7、4换位
				{
					int temp = Picture[1][0];
					Picture[1][0] = Picture[2][0];
					Picture[2][0] = temp;

					Show();//更新图片
				}
				else if (Picture[2][1] == 9)//7、8换位
				{
					int temp = Picture[2][1];
					Picture[2][1] = Picture[2][0];
					Picture[2][0] = temp;

					Show();//更新图片
				}
			}
			else if (m.x >= 200 && m.x <= 400 && m.y >= 400 && m.y <= 600)//第八个格子:判断7、5、9是否为九
			{
				if (Picture[2][0] == 9)//8、7换位
				{
					int temp = Picture[2][0];
					Picture[2][0] = Picture[2][1];
					Picture[2][1] = temp;

					Show();//更新图片
				}
				else if (Picture[1][1] == 9)//8、5换位
				{
					int temp = Picture[1][1];
					Picture[1][1] = Picture[2][1];
					Picture[2][1] = temp;

					Show();//更新图片
				}
				else if (Picture[2][2] == 9)//8、9换位
				{
					int temp = Picture[2][2];
					Picture[2][2] = Picture[2][1];
					Picture[2][1] = temp;

					Show();//更新图片
				}
			}
			else if (m.x >= 400 && m.x <= 600 && m.y >= 400 && m.y <= 600)//第九个格子:判断8、6是否为九
			{
				if (Picture[2][1] == 9)//9、8换位
				{
					int temp = Picture[2][1];
					Picture[2][1] = Picture[2][2];
					Picture[2][2] = temp;

					Show();//更新图片
				}
				else if (Picture[1][2] == 9)//9、6换位
				{
					int temp = Picture[1][2];
					Picture[1][2] = Picture[2][2];
					Picture[2][2] = temp;

					Show();//更新图片
				}
			}
			break;

		case WM_RBUTTONUP:
			return;	// 按鼠标右键退出程序
		}
	}
}

int main()
{
	nineDiffnum();//生成九个不同随机数存入一维数组
	createPicture(temp);//将一维数组导入二维数组

	Start();

	while (1)
	{
		Show();
		Player();
	}


	_getch();


	return 0;
}

示例:

 

 第七步:程序的改进。

增加开始界面和多选择性

 附加代码:
 

void Seclet()
{
	setbkcolor(WHITE);

	cleardevice();

	setlinecolor(RED);

	line(0, 200, 600, 200);

	line(0, 300, 600, 300);

	line(0, 400, 600, 400);

	line(0, 500, 600, 500);

	setbkmode(TRANSPARENT);//显示透明文字

	settextcolor(RED);//设置字体颜色

	settextstyle(50, 0, _T("宋体"));//设置字体大小,字体

	outtextxy(200, 100, _T("拼图盒子"));//输出字体

	settextcolor(BLUE);//设置字体颜色

	settextstyle(30, 0, _T("宋体"));//设置字体大小,字体

	outtextxy(230, 250, _T("图一"));//输出字体

	settextcolor(RGB(220, 0, 0));//设置字体颜色

	settextstyle(30, 0, _T("宋体"));//设置字体大小,字体

	outtextxy(230, 330, _T("图二"));//输出字体

	settextcolor(GREEN);//设置字体颜色

	settextstyle(30, 0, _T("宋体"));//设置字体大小,字体

	outtextxy(230, 430, _T("图三"));//输出字体

	while (1)
	{
		ExMessage m;//定义一个消息变量
		m = getmessage(EM_MOUSE);//获取鼠标消息
		switch (m.message)
		{
		case WM_MOUSEMOVE:
			// 鼠标移动的时候画红色的小点
			putpixel(m.x, m.y, RED);
			break;

		case WM_LBUTTONDOWN:
			// 画一个小方块
			rectangle(m.x - 5, m.y - 5, m.x + 5, m.y + 5);
			if (m.x >= 0 && m.x <= 600 && m.y >= 200 && m.y <= 300)
			{
				key = 1; return;
			}
			else if (m.x >= 0 && m.x <= 600 && m.y >= 300 && m.y <= 400)
			{
				key = 2; return;
			}
			else if (m.x >= 0 && m.x <= 600 && m.y >= 400 && m.y <= 500)
			{
				key = 3; return;
			}
			break;
		}
	}
}

改进方法还有很多很多,代码骑士在这里只起到抛砖引玉的作用,更多创意和想法期待读者自己去实现!

Guess you like

Origin blog.csdn.net/qq_51701007/article/details/121405380