所用素材若有侵权,联系我删除。
素材和源码在文末
另外,其实这是从我的一个大一点的项目中摘取出来的,尽管有所修改,但是难免有些问题,而且代码非常繁琐,没有简化,注释也写的不够全面……
点击这里下载如下图,点击右上角黄色区域下载。
安装:如下图,安装对应版本即可
新建文件的时候要注意,文件后缀使用.cpp而不是.c,因为easyx库的一些东西使用了C++,所以这样最为保险。
我们先进行一定的分析,理一下思路。
void main()
{
//主函数
}
void set_map()
{
//地图的初始化
}
int play()
{
//游戏过程
}
int begin_menu()
{
//开始界面
}
int game_over()
{
//结束界面
}
素材分析
事实上,这个游戏的实现就是通过调用不同的图片来实现的。我收集了一些图片:
#include //引用easyx库
#define UP 1
#define DOWN 2
#define LEFT 3
#define RIGHT 4
int map[6][6] = {{1,1,1,1,2,2},{2,2,5,5,2,2},{3,3,3,3,4,4},{5,5,6,6,6,6},{7,7,1,1,7,7},{8,8,4,4,8,8} };
我们用数组来表示地图内容,数字分别代表图片。
开始界面int begin_menu()
{
initgraph(1152, 648);//界面绘制
IMAGE menu;//开始菜单图片
loadimage(&menu, _T("begin_menu0.jpg"), 1152, 648);
IMAGE shuoming;//游戏说明
loadimage(&shuoming, _T("begin_menu01.jpg"), 1152, 648);
putimage(0, 0, &menu);
MOUSEMSG mouse;
MOUSEMSG mouse2;
int x2, y2;
int x, y;
while (1)
{
mouse = GetMouseMsg();
if (mouse.uMsg == WM_LBUTTONDOWN)//左键按下
{
x = mouse.x;
y = mouse.y;//鼠标坐标
if (x = 461 && y >= 185 && y <= 238)//开始游戏
{
break;
}
else if (x = 461 && y >= 281 && y <= 330)//说明
{
cleardevice;
putimage(0, 0, &shuoming);
while (1)
{
mouse2 = GetMouseMsg();
if (mouse2.uMsg == WM_LBUTTONDOWN)
{
mouse2 = GetMouseMsg();
x2 = mouse2.x;
y2 = mouse2.y;
if (x2 = 52 && y2 >= 15 && y2 <= 65)//返回
{
putimage(0, 0, &menu);
break;
}
}
Sleep(10);
}
continue;
}
}
Sleep(10);
}
return 0;
closegraph();
}
地图初始化(打乱)
void set_maps()
{
initgraph(800, 600);
setlinecolor(WHITE);
setfillcolor(BLACK);
fillrectangle(602, 1, 799, 599);
srand((unsigned int)time(NULL));//随机数种子
for (int a = 0; a < 5; a++)//反复打乱
{
for (int x = 0; x < 6; x++)
{
for (int y = 0; y 50)
{
chang_one(x, y, RIGHT)//和右边数字交换
}
else
{
chang_one(x, y, DOWN);
}
}
//………………此处省略很多行
}
}
}
}
因为涉及到边角等块的情况不同,所以我分类很多,而且用了随机数来增加随机性,所以分类就更多了。这里为了数字交换方便起见,我定义了一个change_one
函数,用于交换两个数字。
void chang_one(int x, int y, int direction)
{
int t;
if (direction == RIGHT)
{
t = map[x][y];
map[x][y] = map[x][y + 1];
map[x][y + 1] = t;
}
else if (direction == DOWN)
{
t = map[x][y];
map[x][y] = map[x + 1][y];
map[x + 1][y] = t;
}
else if (direction == LEFT)
{
t = map[x][y];
map[x][y] = map[x][y - 1];
map[x][y - 1] = t;
}
else if (direction == UP)
{
t = map[x][y];
map[x][y] = map[x - 1][y];
map[x - 1][y] = t;
}
}
游戏过程实现
int plays()
{
IMAGE imgs[10];//不同的图片
loadimage(&imgs[0], _T("0.jpg"), 100, 100);
loadimage(&imgs[1], _T("1.jpg"), 100, 100);
loadimage(&imgs[2], _T("2.jpg"), 100, 100);
loadimage(&imgs[3], _T("3.jpg"), 100, 100);
loadimage(&imgs[4], _T("4.jpg"), 100, 100);
loadimage(&imgs[5], _T("5.jpg"), 100, 100);
loadimage(&imgs[6], _T("6.jpg"), 100, 100);
loadimage(&imgs[7], _T("7.jpg"), 100, 100);
loadimage(&imgs[8], _T("8.jpg"), 100, 100);
loadimage(&imgs[9], _T("yuanshi.jpg"), 100, 100);//背景图
for (int x = 0; x < 6; x++)
{
for (int y = 0; y < 6; y++)
{
putimage(100 * y, 100 * x, &imgs[0]);//先放满背景图
Sleep(25);
}
}
MOUSEMSG mouse;
int x, y;//鼠标数组下标
int times = 0;
int t, x0 = -1, y0 = -1;
number_write(30, 650, 350, 0, WHITE);///自己定义的函数。用于书写数字
while (1)
{
mouse = GetMouseMsg();
if (mouse.uMsg == WM_LBUTTONDOWN)
{
x = mouse.y / 100;
y = mouse.x / 100;
if (map[x][y] != 0 && mouse.x < 600)//防止点击到右边界面
{
if (((x0 != x) | (y0 != y)))//保证两次点击的不是同一张图片
{
times++;
putimage(100 * y, 100 * x, &imgs[map[x][y]]);
}
if (times % 2 == 0)
{
if (map[x][y] != t)
{
Sleep(100);
putimage(100 * y0, 100 * x0, &imgs[0]);
putimage(100 * y, 100 * x, &imgs[0]);
t = -1;
x0 = -1;
y0 = -1;
}
else if (map[x][y] == t && ((x0 != x) | (y0 != y)))
{
Sleep(100);
putimage(100 * y0, 100 * x0, &imgs[9]);
putimage(100 * y, 100 * x, &imgs[9]);
map[x][y] = 0;
map[x0][y0] = 0;
jishuqi += 2;
}
}
else if (times % 2 == 1 && ((x0 != x) | (y0 != y)))
{
t = map[x][y];//记录上一次点击的数字
x0 = x;
y0 = y;
}
}
}
Sleep(2);
if (jishuqi == 36)//成功检测
return SUCCESS;
}
}
主函数的实现
void main()
{
begin:begin_menu();
set_maps();
int result = plays();
int choice = game_over(result);
if (choice == 1)
{
closegraph();
initgraph(1152, 648);
goto begin;
}
system("pause");
}
测试
主界面大概就是这样,下面看看游戏界面,勉强凑活吧(太丑了)………………
其实,上面的过程中有很多的问题没有解决,下面优化一部分:
1、游戏分数游戏的计分方式没有设定,我就暂时先设定一下,
我的规则是下面这样:
补充一点,游戏最低分为0分。
我认为游戏应该是随时显示时间,并且不能无限玩下去吧??我就暂时先设置成60s吧……
3、number_write函数没有给出void number_write(int number_size, int x, int y, int number, COLORREF color)
{
TCHAR s[30];
_stprintf_s(s, _T("%d"), number);//需要先把数字进行转换
settextstyle(number_size, 0, _T("黑体"));
settextcolor(color);
outtextxy(x, y, s);
}
4、游戏结束函数
int game_over(int result)//1返回,0下一关
{
IMAGE over[2];
loadimage(&over[0], _T("success.jpg"), 500, 350);
loadimage(&over[1], _T("failed.jpg"), 500, 350);
if (result == 1)//游戏成功
{
putimage(50, 125, &over[0]);
MOUSEMSG mouse;
int x, y;
while (1)
{
mouse = GetMouseMsg();
if (mouse.uMsg == WM_LBUTTONDOWN)
{
x = mouse.x;
y = mouse.y;
if (x >= 200 && x = 248 && y = 383 && x = 248 && y = 204 && x1 = 340 && y1 <= 405)//返回
{
return 1;
}
}
Sleep(10);
}
}
}
5、游戏下一关的设定
这一块由于时间仓促,暂时还没有给出………………
6、游戏重新进入这里有一个问题,如果退出以后,其实数组的值就已经改变了,,再次开始以后,不能初始化了??
这里,我们做一个修改
int map1[6][6] = { {1,1,1,1,2,2},{2,2,5,5,2,2},{3,3,3,3,4,4},{5,5,6,6,6,6},{7,7,1,1,7,7},{8,8,4,4,8,8} };
//定义一个数组来记录原来数组的值
void main()
{
……
if (choice == 1)
{
closegraph();
initgraph(1152, 648);
for (int x = 0; x < 6; x++)
{
for (int y = 0; y < 6; y++)
{
map[x][y] = map1[x][y];//数组值初始化
}
}
goto begin;
}
system("pause");
}
7、分数显示
其实这里有一个问题。文伟我的分数模式会导致分数上升以后还有下降可能,所以会有问题。
比如,我的分数是10分,但是后来又变成了9分,由于分数书写时覆盖原来数字的,所以,9(一位数)不能完全覆盖10(两位数),所以,就会呈现出90分的样子……
所以,我的解决方法是用黑图片覆盖原来分数……
如果游戏中想要返回呢?我就增加一个返回按钮吧。
******************初始化函数的一点修改
IMAGE back;
loadimage(&back, _T("back.jpg"), 160, 50);
putimage(620, 500, &back);
……………………^…………^……
……………………………………主函数一点修改
if (mouse.x >= 620 && mouse.x = 500 && mouse.y <= 550)
{
return FAIL;
}
else if (map[x][y] != 0 && mouse.x < 600)
…………………………………………
效果展示
[video(video-b7mY7LSX-1586435967267)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=540220179)(image-https://ss.csdn.net/p?http://i1.hdslb.com/bfs/archive/31c99aafc885d0a09f192c2f1ba03e9b16c7492c.jpg)(title-翻翻乐游戏效果展示)]
待优化部分1、下一关的问题,大家自行解决吧,也不难……
2、背景音乐的问题,虽然这个不难,但是没找到合适的素材,大家自己解决吧。
3、重点问题,
时间的问题,因为循环中,如果你的鼠标没有动作,那么程序就停在那里了????这咋办??
我放在微信公众号后台了。
点击获取…………