写在前面:
这个小游戏是自己学习c时的一个小练习,算是记录吧,大牛还请见怪不怪。。。
还有,头文件中包有我自己另下的头文件,不是c官方的。
也就是这玩意:EasyX_2018。
有了它就可以很方便的用c做画图等操作了。
头文件如下:
#include<graphics.h>
#include<conio.h>
#include<stdio.h>
#include<time.h>
话不多说,先看看效果。
如图:
有四块小图位置错乱,右下角置有小黑块。
(当只交换一对时,就可能会出现puzzle无解的情况,具体论证可在网上找到。)
好了,先说说整体思路。
1.建立窗口,大小足以包含两个原图。
2.导入图片,左图切分为N*N小块,右图用以参照。
3.将左图任意两对小块交换位置,左图右小角置黑块
4.当任一小块周围存在黑块时,可按‘w’,‘a’,‘s’,‘d’来控制小块向黑块方向移动。如果左图除右下角外其余小块都与右图相同,则游戏结束。
整体代码:
#include<graphics.h>
#include<conio.h>
#include<stdio.h>
#include<time.h>
#define N 5 //左图切割为N*N块的“N”
#define winw 400 //窗口宽度
#define winh 400 //窗口高度
int Isgameover(int layout[N][N]) //判断游戏是否结束
{
int ret = 0;
int i, j;
for (i = 0; i < N; ++i)
{
for (j = 0; j < N; ++j)
{
if (layout[i][j] != i*N + j)//如果数组值不正确直接跳转
{
goto lp;
}
}
}
lp: if ((i == N - 1 && j == N - 1))//如果此时i,j已经遍历到最后一个置ret为1
{
ret = 1;
}
return ret;
}
int Findblank(int layout[N][N]) //找到并返回小黑块的位置
{
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j)
{
if (layout[i][j] < 0)
{
return i*N + j; //返回其作为一维数组的下标值
}
}
}
}
void Moveleft(int layout[N][N]) //将图片向左移动
{
int index=Findblank(layout);
int i = index / N;
int j = index % N;
int t;
if (j + 1 < N) //小黑块右边不是右边界外,才能有小块左移
{
t = layout[i][j];
layout[i][j] = layout[i][j + 1];
layout[i][j + 1] = t;
}
}
void Moveright(int layout[N][N]) //将图片向右移动
{
int index = Findblank(layout);
int i = index / N;
int j = index % N;
int t;
if (j -1 >= 0) //小黑块左边不是左边界外,才能有小块右移
{
t = layout[i][j];
layout[i][j] = layout[i][j - 1];
layout[i][j - 1] = t;
}
}
void Moveup(int layout[N][N]) //将图片向上移动
{
int index = Findblank(layout);
int i = index / N;
int j = index % N;
int t;
if (i + 1 < N) //小黑块下边不是下边界外,才能有小块上移
{
t = layout[i][j];
layout[i][j] = layout[i + 1][j];
layout[i + 1][j] = t;
}
}
void Movedown(int layout[N][N]) //将图片向下移动
{
int index = Findblank(layout);
int i = index / N;
int j = index % N;
int t;
if (i - 1 >= 0) //小黑块上边不是上边界外,才能有小块下移
{
t = layout[i][j];
layout[i][j] = layout[i - 1][j];
layout[i - 1][j] = t;
}
}
void Drawpic(int layout[N][N],IMAGE* img) //画图。以及当图片有变动时的刷新,即再重新画一遍。
{
int x, y, w, h, x1, y1;
w = winw / N;
h = winh / N; //得到小块的大小
setfillcolor(RGB(0, 0, 0)); //设置填充色黑色
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j) //遍历布局数组
{
x = j*w;
y = i*h; //x,y分别为目标小块的坐标值
if (layout[i][j] >= 0)
{
x1 = layout[i][j] % N*w;
y1 = layout[i][j] / N*h; //x1,y1分别为布局数组第[i][j]项值对应的原图小块坐标值
putimage(x, y, w, h, img, x1, y1); //将x1,y1对应的小块抠出贴到目标x,y坐标位置
}
else
{
fillrectangle(x, y, x + w, y + h); //填充小黑块
}
}
}
int x2, y2;
for (int i = 0; i < N - 1; ++i)
{
x1 = 0;
x2 = winw;
y1 = y2 = winh / N*(i + 1);
line(x1, y1, x2, y2); //画N-1条横线
}
for (int i = 0; i < N - 1; ++i)
{
y1 = 0;
y2 = winw;
x1 = x2 = winw / N*(i + 1);
line(x1, y1, x2, y2); //画N-1条竖线
}
}
void Disorganize(int layout[N][N]) //将左图打乱顺序
{
int t;
srand((unsigned)time(NULL)); //随机数种子
int a, b, c, d;
a = rand() % N;
b = rand() % N;
c = rand() % N;
d = rand() % N;
t = layout[a][b];
layout[a][b] = layout[c][d];
layout[c][d] = t;
t = layout[b][a];
layout[b][a] = layout[d][c];
layout[d][c] = t;
}
int main() //主函数
{
initgraph(winw*2, winh); //绘制窗口大小
IMAGE img;
loadimage(&img,_T("./getz.jpg")); //加载图片
putimage(winw, 0, &img); //画出右边样图
/*int layout[N][N]=
{
{ 0 , 1 , 2 , 3 , 4 },
{ 5 , 6 , 7 , 8 , 9 },
{ 10, 11, 12, 13, 14},
{ 15, 16, 17, 18, 19},
{ 20, 21, 22, 23, -1}
};*/
int layout[N][N] = { 0 }; //定义一个关于各个小块位置的二维数组用于布局
for (int i = 0; i < N; ++i)
{
for (int j = 0; j < N; ++j)
{
layout[i][j] = i*N + j;
}
}
layout[N-1][N-1] = -1; //给布局数组赋值,即上面屏掉的结果(-1代表黑块)
Disorganize(layout); //调用乱序函数
Drawpic(layout, &img); //调用画图函数(画出以布局数组分布的左图,及用于分割的(N-1)*2条直线)
while (!Isgameover(layout)) //若游戏结束条件不满足,则一直循环
{
char key;
key = _getch(); //从键盘接收一个字符
switch (key)
{
case'a':
case'A':
Moveleft(layout); //如果是a或A则调用左移函数
break;
case'd':
case'D':
Moveright(layout); //如果是d或D则调用右移函数
break;
case'w':
case'W':
Moveup(layout); //如果是w或W则调用上移函数
break;
case's':
case'S':
Movedown(layout); //如果是s或S则调用下移函数
break;
}
Drawpic(layout, &img); //每次移动,即图片顺序变动,即布局数组变动,则重新绘图
}
closegraph(); //关闭窗口
puts("你真是个小天才!"); //若能到这一行说明结束条件满足
}
关于代码中的灵魂函数putimage,详情可看下面链接:
C语言EasyX_2018中的putimage(x, y, w, h, img, x1, y1)函数
谢观!