基于EasyX的拼图游戏

一、预备知识

1.使用EasyX必须要知道的一些基础函数
2.选择结构 if , switch
3.循环结构 for, while
4.多维数组 arr1[N], arr2[N][N] , arr3[N][N][N](不喜欢玩拼图,就写一关)
5.函数封装

二、游戏逻辑

首先明确拼图游戏元素和规则

1.拼图元素

一张完整的图片被切成若干个小图片,下面直接按老程序员命名方式走起
素材
有人会问了,“为什么拼锐雯呢,二次元它不香嘛?”
当然是“断剑重铸之日,骑士归来之时”,都的都懂
但是,这还不够,还需要一张纯黑或者纯白的图片,当然啥颜色看你心情了
素材都有了,这不赶紧写个初始化函数

#define SIZE_X 245
#define SIZE_Y 125
//小图片的长宽

IMAGE img[40];//存放小图片
IMAGE nothing;//存放空图

void Loadimg()
{//素材初始化函数
	loadimage(&nothing,L"./images/-1.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[0] ,L"./images/00.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[1] ,L"./images/01.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[2] ,L"./images/02.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[3] ,L"./images/03.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[10],L"./images/10.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[11],L"./images/11.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[12],L"./images/12.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[13],L"./images/13.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[20],L"./images/20.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[21],L"./images/21.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[22],L"./images/22.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[23],L"./images/23.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[30],L"./images/30.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[31],L"./images/31.jpg",SIZE_X,SIZE_Y);   
	loadimage(&img[32],L"./images/32.jpg",SIZE_X,SIZE_Y);
	loadimage(&img[33],L"./images/33.jpg",SIZE_X,SIZE_Y);
}

2.拼图规则

拼图就是少一小块图片,然后点击空图附近的图,空图附近的图就是移动到空图的位置上去,我们可以理解为,空图和它附近的图片交换位置,这个很重要,划重点了
其次就是,所有图移动到它本来的位置,游戏获胜

三、游戏设计

知道游戏元素和规则就可以开始设计游戏了

1.地图设计

看过我推箱子博客的都知道,地图就是个二维数组,定义一个全局变量map数组存放地图,先写简单一点,想复杂可以自己再调位置

int map[4][4]=
{//数字是图片编号,-1表示没图片
	  1, 2, 3,13,
	 20,10,11,12,
	 21,22,23,33,
	 -1,30,31,32,
};

有地图了就开始画图吧,写一个Drawmap()函数

void Drawmap()
{
	int i,j,x,y;
	for(i=0;i<4;i++)
	{
		for(j=0;j<4;j++)
		{
			x=0,y=0;
			x+=j*SIZE_X;y+=i*SIZE_Y;//确定图片位置
			switch(map[i][j])
			{
			case -1:
				putimage(x,y,&nothing);
				break;
			case 0:
				putimage(x,y,&img[0]);
				break;
			case 1:
				putimage(x,y,&img[1]);
				break;
			case 2:
				putimage(x,y,&img[2]);
				break;
			case 3:
				putimage(x,y,&img[3]);
				break;
			case 10:
				putimage(x,y,&img[10]);
				break;
			case 11:
				putimage(x,y,&img[11]);
				break;
			case 12:
				putimage(x,y,&img[12]);
				break;
			case 13:
				putimage(x,y,&img[13]);
				break;
			case 20:
				putimage(x,y,&img[20]);
				break;
			case 21:
				putimage(x,y,&img[21]);
				break;
			case 22:
				putimage(x,y,&img[22]);
				break;
			case 23:
				putimage(x,y,&img[23]);
				break;
			case 30:
				putimage(x,y,&img[30]);
				break;
			case 31:
				putimage(x,y,&img[31]);
				break;
			case 32:
				putimage(x,y,&img[32]);
				break;
			case 33:
				putimage(x,y,&img[33]);
				break;
			}
		}
		printf("\n");
	}
	system("cls");
}

2.移动设计

上文提到,移动就是交换图片的位置

空图和它附近的图片交换位置

这次不用键盘控制移动了,换一换,改用鼠标操作
想交换位置,首先要定义一些全局变量保存空图和鼠标的位置

int ipos,jpos;//由鼠标确定的图片位置
int bipos=3,bjpos=0;//当前黑图位置

注意空图位置是上面地图里-1的位置

然后就要得到鼠标点击图片区域对应的数组坐标位置,写一个Getimgxy()函数

ExMessage m;//消息全局变量
void Getimgxy()
{
	m = getmessage(EM_MOUSE);//得到鼠标消息
	if (m.message == WM_LBUTTONDOWN)
	{//如果鼠标左键按下
		if(m.y>0 && m.y<SIZE_Y)
		{//如果鼠标点第一行
			if(m.x>0 && m.x<SIZE_X)
			{//第一行第一个
				ipos=0;jpos=0;//确定鼠标点击的图片位置	
			}
			else if(m.x>SIZE_X && m.x<SIZE_X*2)
			{//第一行第二个
				ipos=0;jpos=1;
			}
			else if(m.x>SIZE_X*2 && m.x<SIZE_X*3)
			{//第一行第三个
				ipos=0;jpos=2;
			}
			else if(m.x>SIZE_X*3 && m.x<SIZE_X*4)
			{//第一行第四个
				ipos=0;jpos=3;
			}
		}
		else if(m.y>SIZE_Y && m.y<SIZE_Y*2)
		{
			if(m.x>0 && m.x<SIZE_X)
			{//第二行第一个
				ipos=1;jpos=0;
			}
			else if(m.x>SIZE_X && m.x<SIZE_X*2)
			{//第二行第二个
				ipos=1;jpos=1;
			}
			else if(m.x>SIZE_X*2 && m.x<SIZE_X*3)
			{//第二行第三个
				ipos=1;jpos=2;
			}
			else if(m.x>SIZE_X*3 && m.x<SIZE_X*4)
			{//第二行第四个
				ipos=1;jpos=3;
			}
		}
		else if(m.y>SIZE_Y*2 && m.y<SIZE_Y*3)
		{
			if(m.x>0 && m.x<SIZE_X)
			{//第三行第一个
				ipos=2;jpos=0;
			}
			else if(m.x>SIZE_X && m.x<SIZE_X*2)
			{//第三行第二个
				ipos=2;jpos=1;
			}
			else if(m.x>SIZE_X*2 && m.x<SIZE_X*3)
			{//第三行第三个
				ipos=2;jpos=2;
			}
			else if(m.x>SIZE_X*3 && m.x<SIZE_X*4)
			{//第三行第四个
				ipos=2;jpos=3;
			}
		}
		else if(m.y>SIZE_Y*3 && m.y<SIZE_Y*4)
		{
			if(m.x>0 && m.x<SIZE_X)
			{//第四行第一个
				ipos=3;jpos=0;
			}
			else if(m.x>SIZE_X && m.x<SIZE_X*2)
			{//第四行第二个
				ipos=3;jpos=1;
			}
			else if(m.x>SIZE_X*2 && m.x<SIZE_X*3)
			{//第四行第三个
				ipos=3;jpos=2;
			}
			else if(m.x>SIZE_X*3 && m.x<SIZE_X*4)
			{//第四行第四个
				ipos=3;jpos=3;
			}
		}
	}
}

有了由鼠标点击确定的图片位置和空图的位置,我们就可以写交换图片的函数了,Exchangeimg()

void Exchangeimg()
{
	int x=0,y=0,bx=0,by=0;
	if(ipos==bipos)
	{//如果点击的图片和空图在一行
		if(jpos== bjpos-1 || jpos== bjpos+1)
		{//如果点击的图片在空图左边或右边		
			x+=jpos*SIZE_X;y+=ipos*SIZE_Y;//计算点击图片的坐标
			putimage(x,y,&nothing);//放空图

			bx+=bjpos*SIZE_X;by+=bipos*SIZE_Y;//计算空图坐标
			putimage(bx,by,&img[ map[ipos][jpos] ]);//放点击的图

			map[bipos][bjpos]=map[ipos][jpos];
			map[ipos][jpos]=-1;//交换地图上的数据

			bipos=ipos; //记录空图的新坐标
			bjpos=jpos;
		}
	}
	else if(jpos==bjpos)
	{//如果点击的图片和空图在一列
		if(ipos== bipos-1 || ipos== bipos+1)
		{//如果点击的图片在空图上边或下边
			x+=jpos*SIZE_X;y+=ipos*SIZE_Y;//计算点击图片的坐标
			putimage(x,y,&nothing);//放空图

			bx+=bjpos*SIZE_X;by+=bipos*SIZE_Y;//计算空图坐标
			putimage(bx,by,&img[ map[ipos][jpos] ]);//放点击的图

			map[bipos][bjpos]=map[ipos][jpos];
			map[ipos][jpos]=-1;//交换地图上的数据

			bipos=ipos; //记录空图的新坐标
			bjpos=jpos;
		}
	}
}

3.结束设计

上文提到

所有图移动到它本来的位置,游戏获胜

写一个Gameover()函数判断游戏是否结束

int  Gameover()
{
	if(map[0][1]==1)
		if(map[0][2]==2)
			if(map[0][3]==3)
				if(map[1][0]==10)
					if(map[1][1]==11)
						if(map[1][2]==12)
							if(map[1][3]==13)
								if(map[2][0]==20)
									if(map[2][1]==21)
										if(map[2][2]==22)
											if(map[2][3]==23)
												if(map[3][0]==30)
													if(map[3][1]==31)
														if(map[3][2]==32)
															if(map[3][3]==33)
																return 1;
	return 0;
}

4.整体设计

下面把上面的函数组合起来就是拼图游戏,再来点音乐

#include<stdio.h>
#include<graphics.h>//图形库
#include<mmsystem.h>//音乐
#pragma comment(lib,"winmm.lib")//库文件

int main()
{
	initgraph(980,500);//创建窗口
	Loadimg(); //加载图片资源
	mciSendString(L"open ./images/bg.mp3",0,0,0);//打开音乐
	mciSendString(_T("play ./images/bg.mp3 repeat"), 0, 0, 0);//循环播放
	BeginBatchDraw();//这个函数用于开始批量绘图。执行后,任何绘图操作都将暂时不输出到屏幕上,
	Drawmap();
	EndBatchDraw();//直到执行 EndBatchDraw 才将之前的绘图输出。
	while(true){
		Getimgxy();//获取鼠标点击的图片位置
		Exchangeimg();//交换图片位置
		if(Gameover())
		{//如果游戏结束
			mciSendString(L"close ./images/bg.mp3",0,0,0);//关闭背景音乐
			PlaySound(L"./images/success.wav", nullptr, SND_FILENAME | SND_ASYNC);//播放胜利音乐
			putimage(0,0,&img[0]);//把少的那一块图片贴上去
			break;
		}
	}
	setbkmode(0);//设置文字背景透明
	settextcolor(RED);//设置字体颜色  红色
	settextstyle(64, 0, _T("宋体"));//64是字体大小 0是自适应 双引号里可以填字体名字
	outtextxy(230, 150, _T("游戏结束,你真棒!"));
	system("pause");
	return 0;

}

把上面所有代码复制到一个cpp文件里,再把素材改好命名放到images文件夹里,images文件夹在cpp文件旁边,就可以编译运行了!

图片音乐素材及可执行程序需要的点击下载

  • 9
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
以下是使用easyx制作滑动拼图游戏的示例代码: ```python from easygraphics import * import random # 定义常量 WIDTH = 400 HEIGHT = 400 SIZE = 100 ROWS = 4 COLS = 4 BLANK_ROW = 3 BLANK_COL = 3 FONT_SIZE = 30 FONT_COLOR = "white" FONT_FAMILY = "Arial" IMAGE_PATH = "puzzle.jpg" # 加载图片 img = Image.open(IMAGE_PATH) img = img.resize((WIDTH, HEIGHT)) img.save("puzzle.jpg") # 初始化窗口 init_graph(WIDTH, HEIGHT, "Sliding Puzzle") # 定义方块类 class Block: def __init__(self, row, col, img): self.row = row self.col = col self.img = img self.x = col * SIZE self.y = row * SIZE self.selected = False def draw(self): if not self.selected: set_fill_color("white") draw_rectangle(self.x, self.y, self.x + SIZE, self.y + SIZE) set_color("black") draw_rectangle(self.x, self.y, self.x + SIZE, self.y + SIZE) draw_image(self.x, self.y, self.img.crop((self.col * SIZE, self.row * SIZE, (self.col + 1) * SIZE, (self.row + 1) * SIZE))) else: set_fill_color("red") draw_rectangle(self.x, self.y, self.x + SIZE, self.y + SIZE) set_color("black") draw_rectangle(self.x, self.y, self.x + SIZE, self.y + SIZE) draw_image(self.x, self.y, self.img.crop((self.col * SIZE, self.row * SIZE, (self.col + 1) * SIZE, (self.row + 1) * SIZE))) def is_clicked(self, x, y): if x >= self.x and x <= self.x + SIZE and y >= self.y and y <= self.y + SIZE: return True else: return False def move(self, row, col): self.row = row self.col = col self.x = col * SIZE self.y = row * SIZE # 初始化方块列表 blocks = [] for row in range(ROWS): for col in range(COLS): if row == BLANK_ROW and col == BLANK_COL: blocks.append(None) else: block_img = img.crop((col * SIZE, row * SIZE, (col + 1) * SIZE, (row + 1) * SIZE)) blocks.append(Block(row, col, block_img)) # 随机打乱方块 for i in range(100): blank_index = BLANK_ROW * COLS + BLANK_COL move_index = random.choice([blank_index - 1, blank_index + 1, blank_index - COLS, blank_index + COLS]) if move_index >= 0 and move_index < ROWS * COLS: blocks[move_index], blocks[blank_index] = blocks[blank_index], blocks[move_index] blocks[move_index].move(move_index // COLS, move_index % COLS) blocks[blank_index] = None BLANK_ROW = blank_index // COLS BLANK_COL = blank_index % COLS # 游戏循环 while is_run(): # 绘制方块 for block in blocks: if block is not None: block.draw() # 绘制文字 set_font_size(FONT_SIZE) set_font_color(FONT_COLOR) set_font_family(FONT_FAMILY) draw_text(WIDTH // 2, HEIGHT - FONT_SIZE, "Sliding Puzzle", Align.CENTER) # 处理鼠标事件 if has_mouse_msg(): msg = get_mouse_msg() if msg.type == MouseMessage.DOWN: for block in blocks: if block is not None and block.is_clicked(msg.x, msg.y): if block.row == BLANK_ROW and block.col == BLANK_COL - 1: block.move(BLANK_ROW, BLANK_COL) blocks[BLANK_ROW * COLS + BLANK_COL] = block blocks[BLANK_ROW * COLS + BLANK_COL - 1] = None BLANK_COL -= 1 elif block.row == BLANK_ROW and block.col == BLANK_COL + 1: block.move(BLANK_ROW, BLANK_COL) blocks[BLANK_ROW * COLS + BLANK_COL] = block blocks[BLANK_ROW * COLS + BLANK_COL + 1] = None BLANK_COL += 1 elif block.row == BLANK_ROW - 1 and block.col == BLANK_COL: block.move(BLANK_ROW, BLANK_COL) blocks[BLANK_ROW * COLS + BLANK_COL] = block blocks[(BLANK_ROW - 1) * COLS + BLANK_COL] = None BLANK_ROW -= 1 elif block.row == BLANK_ROW + 1 and block.col == BLANK_COL: block.move(BLANK_ROW, BLANK_COL) blocks[BLANK_ROW * COLS + BLANK_COL] = block blocks[(BLANK_ROW + 1) * COLS + BLANK_COL] = None BLANK_ROW += 1 break delay_fps(60) # 关闭窗口 close_graph() ``` 运行上述代码后,即可得到一个滑动拼图游戏窗口。玩家可以通过鼠标点击方块来移动它们,直到拼图完成。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值