大一学了C语言有什么用,写个拼图小游戏表白女神,快学起来吧

国庆长假,男朋友女朋友们都出去旅游了,而我只能和我的idol隔着手机单相思,不过我可以用表白神器代码来一波骚操作,自慰一下我苦涩又空虚的灵魂。亲测可行,运行时在文件夹下插入两张图片即可女神\空白,空白图片可自行截取网页等空白区域,整体游戏效果图如下,附以源码链接:https://paste.ubuntu.com/p/z39f7HKGSn/

一、.h与main

  1. 首先,若想使用#include<graphics.h>需要安装EasyX。EasyX是一个轻量级的简单的C++图形库,可以用来做些简单的演示2d类游戏。现提供官网下载地址:EasyX
    注意当安装过程检测到支持的编程软件,Visual C++2017、Visual C++2019即是本机上的VS2017、VS2019,小编在此亲测过,直接安装打开VS即可编译调用该图形库
  2. 当程序调用getchar()时,程序就等着用户按键。用户输入的字符被存放在键盘缓冲区中,直到用户按回车为止,用在此处是为了防止闪屏
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<graphics.h>
IMAGE img, blank;
int array1D[9] = { 0 };
int array2D[3][3] = { 0 };
int main()
{
	drawmenu();
	initgraph(300, 300);
	loadresource();


	playgame();
	closegraph();
	return 0;
}

二、绘制菜单

字体样式设置通过查找路径 C:\Windows\Fonts,打开字体库对应字体名称,最终菜单界面如下图所示

void drawmenu()
{
	initgraph(500, 600);
	setbkcolor(WHITE);//窗口设置为白色
	cleardevice();
	setfillcolor(BLUE);
	settextstyle(20, 0, "华文行楷");//宽、高、字体,0:自适应
	setbkmode(TRANSPARENT);//透明方式去掉文字背景
	fillrectangle(200, 100, 300, 150);//(int x,int y,int xx,int yy)
	fillrectangle(200, 100 + 70, 300, 150 + 70);
	outtextxy(200 + 15, 100 + 15, "开始游戏");
	outtextxy(200 + 15, 100 + 70 + 15, "退出游戏");
	settextcolor(RED);
	outtextxy(200, 400, "made by xiexie");
	MOUSEMSG m;
	while (1)
	{
		m = GetMouseMsg();
		if (m.x >= 200 && m.x <= 300 && m.y >= 100 && m.y <= 150)
		{
			setlinecolor(RED);
			rectangle(200 - 5, 100 - 5, 300 + 5, 150 + 5);
			if (m.uMsg == WM_LBUTTONDOWN)
				break;
		}
		else if (m.x >= 200 && m.x <= 300 && m.y >= 100 + 70 && m.y <= 150 + 70)
		{
			setlinecolor(RED);
			rectangle(200 - 5, 170 - 5, 300 + 5, 220 + 5);
			if (m.uMsg == WM_LBUTTONDOWN)
				break;
		}
		else
		{
			setlinecolor(WHITE);
			rectangle(200 - 5, 100 - 5, 300 + 5, 150 + 5);
			rectangle(200 - 5, 170 - 5, 300 + 5, 220 + 5);
		}
	}
	closegraph();
}

三、加载资源

  1. srand函数是随机数发生器的初始化函数。原形:void srand(unsigned seed) srand根据seed返回一个随机数但是一个伪随机数,多次编译产生的随机数是一样的,除非给一个变化的种子 因此使用系统时间来初始化
  2. time函数可获得当前系统时间srand ((unsigned)time(NULL)) 从单目运算符的优先级别从右到左考虑,返回秒数后,最后强制转化为unsigned int 型整数
  3. rand函数经常和srand函数一起使用,rand函数每一次被调用的时候,都会先查看srand函数是否被调用。如果被调用,则会调用srand(seed)初始化它的随机值,如果没被调用,则会默认调用srand(1)初始化
  4. 此部分代码段为拼图游戏的核心,将随机初始化一维数组的值赋给二维数组,使得每次拼图的原始界面都不同
  5. 图片的加载需要将两张图片 女神\空白 存储在工程文件夹的直接层下面,空白图用于制作右下角可供周围拼图块移动调整的区域
/*此代码块使用的头文件
#include<stdlib.h>
#include<time.h>
#include<graphics.h>
*/
void loadresource()
{
	srand((unsigned int)time(NULL));
	int length = 8;
	int pos = 0;
	int i, j;
	//1.给一维数组初始化0-15
	for (i = 0; i < 8; i++)
	{
		array1D[i] = i;
	}
	//2.随机出来一个下表
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 3; j++)
		{
			//单独处理最后一个位置
			if (i == 2 && j == 2)
			{
				array2D[2][2] = 8;
				break;
			}
			pos = rand() % length;
			array2D[i][j] = array1D[pos];
			for (int k = pos; k < length; k++)
			{
				array1D[k] = array1D[k + 1];
			}
			length--;
		}
		if (i == 2 && j == 2)
		{
			array2D[2][2] = 8;
			break;
		}
	}
//缩放加载
	loadimage(&img, "圣经经.jpg", 300, 300);
	loadimage(&blank, "blank.jpg", 100, 100);
}

四、绘制拼图

// 绘制图像的各个参数(指定宽高和起始位置)
void putimage(
   int dstX,              // 绘制位置的 x 坐标
   int dstY,              // 绘制位置的 y 坐标
   int dstWidth,          // 绘制的宽度
   int dstHeight,         // 绘制的高度
   IMAGE *pSrcImg,        // 要绘制的 IMAGE 对象指针
   int srcX,              // 绘制内容在 IMAGE 对象中的左上角 x 坐标
   int srcY,              // 绘制内容在 IMAGE 对象中的左上角 y 坐标
);

根据打乱顺序的二维数组中的值去拿照片中相应的位置,效果图如下:

void drawmap()
{    
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			int x = i * 100;
			int y = j * 100;
			switch (array2D[i][j])
			{

			case 0:
			case 1:
			case 2:
				putimage(x, y, 100, 100, &img, (array2D[i][j] % 3) * 100, 0);
				break;
			case 3:
			case 4:
			case 5:
				putimage(x, y, 100, 100, &img, (array2D[i][j] % 3) * 100, 100);
				break;
			case 6:
			case 7:
				putimage(x, y, 100, 100, &img, (array2D[i][j] % 3) * 100, 200);
				break;
			case 8:
				putimage(x, y, &blank);
				break;
			}
		}
	}
}

五、游戏过程

  1. 这里是我被坑最久的代码区,主要原因是鼠标操作导致二维数组下标溢出。VS2019会显示报错(好评++),同时我还用了VC++6.0,编译通过也能加载拼图资源(没有显示具体报错内容),但在playgame,某些边界的拼图块无法和空白块交换位置导致界面卡住

  2. 解决之路还挺曲折的,先是自己盯着警告,最后也明白错误的可能根源,但没有想出合适的解决办法,最后万分感谢莫老师,远程控制帮我写了两个子函数,bug消失了,游戏过程如下

//温馨提示,不要采用这种定位方式
   	for (i = 0; i < 3; i++)
   	{
   		for (j = 0; j < 3; j++)
   		{
   			if (array2D[i][j] == 8)
   			{
   				break;
   			}
   		}
   		if (array2D[i][j] == 8)
   		{
   			break;
   		}
   	}
//此处为正解
int searchPos_i()
{
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			if (array2D[i][j] == 8)
			{
				return i;
			}
		}
	}
	return -1;
}
int searchPos_j()
{

	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			if (array2D[i][j] == 8)
			{
				return j;
			}
		}
	}
	return -1;
}
void playgame()
{
	MOUSEMSG m;
	int i, j;
	int j_Mouse, i_Mouse;
	while (1)
	{
		drawmap();//每次循环开始都要重新定位白块的坐标位置
		i = searchPos_i();
		j = searchPos_j();
		m = GetMouseMsg();
		switch (m.uMsg)
		{
		case WM_LBUTTONDOWN:
			i_Mouse = m.x / 100;
			j_Mouse = m.y / 100;
			if (j_Mouse == j + 1 && i_Mouse == i)
			{
				array2D[i][j] = array2D[i_Mouse][j_Mouse];
				array2D[i_Mouse][j_Mouse] = 8;
			}
			if (j_Mouse == j - 1 && i_Mouse == i)
			{
				array2D[i][j] = array2D[i_Mouse][j_Mouse];
				array2D[i_Mouse][j_Mouse] = 8;
			}
			if (i_Mouse == i - 1 && j_Mouse == j)
			{
				array2D[i][j] = array2D[i_Mouse][j_Mouse];
				array2D[i_Mouse][j_Mouse] = 8;
			}
			if (i_Mouse == i + 1 && j_Mouse == j)
			{
				array2D[i][j] = array2D[i_Mouse][j_Mouse];
				array2D[i_Mouse][j_Mouse] = 8;
			}
			break;
		}
	}
}

最后,感谢大家抽出时间阅读小编的文章,我会继续努力,用代码写出好玩的东西的!

祝大家国庆快乐呀

  • 7
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值