拼图游戏

来源:互联网 发布:淘宝上首页多少钱 编辑:程序博客网 时间:2024/06/07 02:05

时间:2017年8月28日


呼,感觉小游戏里拼图(puzzle)游戏算是最简单的几个游戏之一了吧


代码比较简单,因为今天是七夕,所以用了单身狗为主题,学c挺好,单身到老啊!

哈哈,各位码农节日快乐



编程语言:c语言

编译环境:vs,easyx图形库

基本操作:方向键,WASD键控制方向,esc退出游戏



1.找到一张图,用ps分成3*3的小方格,标记为1-9.jpg(方便函数调用),

这里我选取了273*300的图片,可以分成9张91*100的图片

另外加了一张91*100的白色图片

准备了一首音乐,前段时间挺火的single dog……微笑


这样放入exe目录下的编辑好的文件夹里,素材就准备好了




2.有这样几个函数,有几个是类似于推箱子游戏的,相信做过推箱子游戏的会比较了解

这里先放一下函数声明

#include<conio.h>#include<stdio.h>#include"graphics.h"#include<time.h>#include<mmsystem.h>#pragma comment(lib,"winmm.lib")void GameInit();void draw();void game();int judge();void menu();
IMAGE img[11];//封面图1张,3*3拼图的9小张,1张空白小图int p[3][3];//拼图的数组int gn= 0;//变为空白小图的地方HWND hWnd;//窗口句柄

重点说一下这里的逆序数和曼哈顿距离运用,

我们用1-9数值代表拼图的图片

百度上关于逆序数的介绍如下

点击打开链接


曼哈顿距离

点击打开链接


总状态数=行数*列数-1+gn到左下角数组的曼哈顿距离

拼图的当前状态数=逆序数+空白图片到左下角数组(这里是[2][2])的曼哈顿距离

逆序数为0(拼好了);

状态数与总状态数奇偶性一致,才能顺利拼图(排除不能还原拼图的情况)


在3*3拼图里,

总状态数为3*3-1=8,为偶数


所以有

状态数为奇数,不可以拼图;

状态数为偶数,可以拼图,但尚未拼好;


int judge(){int i, j,x=0;int s;s= 0;int manha=0;int b[9];for (i = 0; i < 3; i++)for (j = 0; j < 3; j++){if (p[i][j])b[x++] = p[i][j];else b[x++] = gn;}for (i = 0; i < 8;i++)for (j = 8; j>i; j--){if (b[i]>b[j])s++;}int m, n;for (i = 0; i < 3; i++)for (j = 0; j < 3; j++){if (p[i][j] == 0){m = i; n = j; break;//记录0图片的值,并返回坐标}}manha = 2 - m + 2 - n;//计算0到左下角的曼哈顿距离if (s==0)return 2;if ((s + manha) % 2 == (3 * 3 - 1 + 2 - (gn - 1) / 3+ 2 - gn + ((gn - 1) / 3) * 3 + 1) % 2)return 0;//判断当前状态数与总状态数是否一致return 1;}
根据这个judge函数,最终返回值可以为

0,可以拼图;

1,无法拼图;

2,拼图按拼好的顺序,1-9依次排列,游戏胜利。



GameInit函数里,初始化函数时,结合judge函数打乱了一下拼图

void GameInit(){int i, j, x = 1;for (i = 0; i < 3; i++)for (j = 0; j < 3; j++){p[i][j] = x++;}srand((unsigned)time(NULL));int temp;while (gn== 0)gn= rand() % 10;p[(gn- 1) / 3][2 - gn % 3] = 0;while (judge() != 0)                 //取状态为偶数,而且未还原的状态{for (int t = 0; t < 2; t++){temp = p[t][t]; p[t][t] =p[t][t+1]; p[t][t + 1] = temp;}for (int t = 0; t < 2; t++){temp = p[t][t];p[t][t] = p[t + 1][t ];p[t + 1][t] = temp;}}}

这里int了gn(gn是全局变量),

用rand()对它进行取值,使gn的值在1-9之间

(使得9张图中一张变为空白,进行游戏)

p[(gn- 1) / 3][gn-((gn-1)/3+1)*3] = 0;

用这一段使gn数值的方块变为空白图,也就是文件夹里的0.jpg空白图

(gn- 1) / 3
为gn的行数

gn-((gn-1)/3+1)*3
为gn的列数

红色的代码部分有待争议,

因为是我自己临时编的打乱拼图顺序的代码,

有建议更改的欢迎指出


之后是和推箱子游戏等类似的draw画图函数,和利用getch()读取输入

的game()游戏函数

放一段w,和方向键向上控制的代码


void game(){char ch;int m, n;int i, j;for (i = 0; i < 3; i++)for (j = 0; j < 3; j++){if (p[i][j] == 0){m = i; n = j;//保留下0空白位置的数组下标}}ch = getch();switch (ch){case 'w':case 'W':case 72:if (m != 2){p[m][n] = p[m + 1][n];p[m + 1][n] = 0;}break;

其余的A,S,D的情况就有劳大家自行脑补了,哈哈


外加一个开始的menu()函数

做出这样的效果:

放置一张封面图,并给出messagebox,提示是否开始游戏



这里放一下播放音乐的代码

需要嵌入相应的头文件

mciSendString(L"open ./res/单身狗之歌.mp3 alias bgm", 0, 0, 0);mciSendString(L"play bgm repeat", 0, 0, 0);

主函数里主要的部分为

menu();GameInit();while (1){draw();game();if (judge()==2)break;}hWnd=GetForegroundWindow();MessageBoxA(hWnd, "恭喜通关,节日快乐!", "恭喜通关", MB_OK);return 0;

之后再拼好图,judge会返回2,循环也就break掉,

游戏结束,会出现messagebox的弹窗,

算是一点节日的小创意吧



以上就是所谓的“单身狗拼图游戏”了,逆序数的想法是之前看的网上的

因为博主还没学过线代,所以自己也有些云里雾里的

导致了代码还是有点问题,在有些情况下拼图是不能还原

(无法进行游戏,但大部分还是可以的,应该是我逆序数的运用方式不对)

如果之后解决了,会给出相应的博文,

哈哈,当然也算是抛砖引玉了,也希望有懂的人指出来


谢谢你的观看,欢迎评论互相学习,互相进步。



原创粉丝点击