编程语言
首页 > 编程语言> > 连连看(源码及图片素材)

连连看(源码及图片素材)

作者:互联网

@连连看(源码及图片素材)

连连看(源码及图片素材)

首先声明一下,我不是计算机专业的人,这是我大二上程设课的大作业,第一次做游戏,当时会的东西不多很焦虑,不知道该怎么开始第一步。开始前搜了很多东西,什么“图形界面编程”“面向对象编程”等等,结果其实根本用不上。easyx也是现学的(好在并不难)。在CSDN上找到了好些前辈的文章,非常感谢他们(对了,如果是和我一样非常小白的小白,完全不知道要干啥,可以先去知乎看看童晶老师的文章,感受一下一个小游戏是怎么写的,缓解一下焦虑)。

为了把这份帮助传递下去,决定把自己写的连连看上传上来。第一次写这么长的代码,很大的工作量,写的时候思路不够清晰,有些混乱,所以,我也知道我代码写的不好,仅仅是抱着贡献一点绵薄之力的心态,希望读者可以自行甄别(也不知道有没有bug哈哈哈)。再次感谢CSDN上分享知识的前辈们。

可以转载,请务必注明出处。禁止商用。

将源码、图片素材(freeillustrations.xyz)、删减版实验报告和用到的字体文件上传到了百度网盘上(虽然我真的很讨厌百度网盘。。。),方便大家下载,希望能帮到大家。永久有效。
链接: https://pan.baidu.com/s/1bqBNjDoM14ohiJzBc-VEiA 密码: fhoq

图形库用的是easyx,头文件graphics.h

对了,放上最终游戏界面的部分截图(很用心地做了界面设计,不喜勿喷)
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

头文件

#pragma once
#include<graphics.h>
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
#include<string>
#include<atlstr.h>	//CString头文件atlstr.h
#include<algorithm>
#include<time.h>
#include<process.h>
#include<algorithm>
using namespace std;

定义

#pragma once
#define column 16
#define row 12
#define grid_size 40
#define x0 5
#define y0 5
#define gap 0
const short windows_width = 2 * x0 + grid_size * column + gap * (row - 1) + 250;
const short windows_lenth = 2 * y0 + grid_size * row + gap * (row - 1);

//img[13] 开始菜单背景, img[14] 游戏界面背景, img[15] 排行榜、设置界面的“退出”按钮
IMAGE img[16];
LOGFONT textstyle;
//为真则进入菜单界面
bool flg = true;		
short nhint = 2;
short nshuffle = 1;
int combo = 2;
int score = 0;
long t_start;
short resttime = 360;
short t_limit = 360;
//t代表游戏开始到上一次消除成功多久了,t初始化为-5是为了防止第一次消除被误判为combo
short t = -5;
short n_img = (column - 2) * (row - 2);
short level = 1;
//在设置界面记录之前是否已经选择过一个关卡
short prechoice = 0;			
char fl_name[20] = "rank_list1.txt";

class labels
{
public:
	labels() : x(0), y(0), w(200), h(60), n(13) {}
	labels(short _x, short _y, short _w, short _h, short _n) : x(_x), y(_y), w(_w), h(_h), n(_n) {}
	//判断是否点击了该按钮
	bool init(MOUSEMSG m)
	{
		if (m.x >= x && m.x <= x + w && m.y >= y && m.y <= y + h)
			return true;
		else
			return false;
	}
private:
	short x, y, w, h, n;
};
labels lstart_game(250, 270, 400, 80, 13);
labels lrank_list(380, 5, 140, 40, 14);
labels lexit_game(760, 460, 120, 40, 15);
labels lsetting(855, 5, 40, 40, 16);
labels lshuffle(646, 287, 79, 46, 17);
labels lhint(646, 207, 79, 46, 18);
labels lbk_to_menu(720, 392, 79, 46, 19);
labels lclose_rank(410, 440, 79, 46, 20);

RECT rthint = { 631, 200, 870, 260 };
RECT rtshuffle = { 631, 280, 870, 340 };
RECT rlhint = { 646, 207, 725, 253 };
RECT rlshuffle = { 646, 287, 725, 333 };
RECT rbk_to_menu = { 720, 392, 799, 438 };
RECT rscores = { 650, 85, 870, 175 };
//输出“排行榜”三个字的矩形,“设置”两个字也是这个区域
RECT rrank_name = { 235, 25, 665, 120 };
RECT rrank1 = { 235, 25, 665, 120 };
RECT rrank2 = { 235, 125, 665, 425 };
RECT R = { 0, 5, windows_width, 45 };

struct grids
{
	short x = 0;
	short y = 0;
	//编号 -1 表示没有图片
	short img_num = -1;				
}grid[row][column];

struct levels
{
	char fl_name[20];
	short n_img;
	short t_limit;
};
struct levels level1 = { "rank_list1.txt", 140, 360 };
struct levels level2 = { "rank_list2.txt", 140, 150 };
struct levels level3 = { "rank_list3.txt",  80, 150 };
struct levels level4 = { "rank_list4.txt", 110, 200 };
struct levels level5 = { "rank_list5.txt", 110, 150 };

int Rand(int i)
{
	return rand() % i;
}

void initgridxy();
void initimg();
void initmap1();
void initmap2();
void initmap3();
void draw_start_menu();
void draw_game_window();

void rank_list();
void setting();
void hint();
void shuffle();
bool ten_solutions();

bool start_menu();
void start_game();
void game_window();
void game_over();
bool judge();
void save_memory();

void draw_map();
void drawline(short x1, short y1, short x2, short y2);
void drawrectangle(short x, short y);
void drawsolidrectangle(short x, short y);
void print_score(int scores);

bool is_solution(short &solution_x1, short &solution_y1, short &solution_x2, short &solution_y2);
bool x_no_dots_between(short x1, short x2, short y);
bool y_no_dots_between(short y1, short y2, short x);
bool is_connected(short x1, short y1, short x2, short y2, short &x3, short &y3, short &x4, short &y4);
bool no_turn(short x1, short y1, short x2, short y2);
bool one_turn(short x1, short y1, short x2, short y2, short &x3, short &y3);
bool two_turns(short x1, short y1, short x2, short y2, short &x3, short &y3, short &x4, short &y4);

bool cmp(short a, short b)
{
	return a > b;
}

/*返回label序号,label序号即为对应的img[]序号;
	false代表在开始菜单界面,true代表在游戏界面 */
short clk_labels(MOUSEMSG m, bool flg);
//选择哪个关卡
void clk_levels(MOUSEMSG m);

函数们

#include"headers.h"
#include"definitions.h"
//#include<iostream>
int main()
{
	initgraph(windows_width, windows_lenth + 30);
	setbkcolor(WHITE);				//背景色
	setfillcolor(WHITE);
	setbkmode(OPAQUE);

	gettextstyle(&textstyle);
	textstyle.lfHeight = 50;
	textstyle.lfWidth = 30;
	textstyle.lfQuality = ANTIALIASED_QUALITY;
	textstyle.lfWeight = 700;
	_tcscpy(textstyle.lfFaceName, _T("Aa方萌 (非商业使用)"));
	settextstyle(&textstyle);

	LINESTYLE linestyle;
	linestyle.thickness = 2;
	setlinestyle(&linestyle);
	initimg();
	initgridxy();

	while (1)
	{
		//返回false代表用户点击了“退出游戏”
		if (!start_menu())			
		{
			closegraph();
			return 0;
		}
		start_game();
		while (!flg);
	}

	_getch();
	closegraph();
}

//开始菜单界面
bool start_menu()
{
	level = 1;
	prechoice = 0;
	flg = true;
	cleardevice();
	draw_start_menu();
	FlushMouseMsgBuffer();
	while (1)
	{
		MOUSEMSG m;
		m = GetMouseMsg();
		if (m.mkLButton)
		{
			if (clk_labels(m, false) == 13)		//开始游戏
			{
				flg = false;
				return true;
			}
			else if (clk_labels(m, false) == 14)
			{
				rank_list();
				draw_start_menu();
			}

			else if (clk_labels(m, false) == 15)
			{
				return false;		//用户点击了“退出游戏”
			}
			else if (clk_labels(m, false) == 16)
			{
				setting();
				draw_start_menu();
			}
		}
	}
}

//进入哪一关
void start_game()
{
	while (!flg)
	{
		switch (level)
		{
		case 1:
			strcpy(fl_name, level1.fl_name);
			resttime = level1.t_limit;
			t_limit = resttime;
			n_img = level1.n_img;

			draw_game_window();
			initmap1();
			game_window();

			break;
		case 2:
			strcpy(fl_name, level2.fl_name);
			resttime = level2.t_limit;
			t_limit = resttime;
			n_img = level2.n_img;

			draw_game_window();
			initmap1();
			game_window();
			break;
		case 3:
			strcpy(fl_name, level3.fl_name);
			resttime = level3.t_limit;
			t_limit = resttime;
			n_img = level3.n_img;

			draw_game_window();
			initmap2();
			game_window();
			break;
		case 4:
			strcpy(fl_name, level4.fl_name);
			resttime = level4.t_limit;
			t_limit = resttime;
			n_img = level4.n_img;

			draw_game_window();
			initmap3();
			game_window();
			break;
		case 5:
			strcpy(fl_name, level5.fl_name);
			resttime = level5.t_limit;
			t_limit = resttime;
			n_img = level5.n_img;

			draw_game_window();
			initmap3();
			game_window();
			flg = true;//无论如何都要返回主菜单了
			return;
		}
	}
	//循环结束,说明flg为true了,返回菜单界面
	return;
}

//游戏界面
void game_window()
{
	flg = false;
	t = -5;
	nhint = 2;
	nshuffle = 1;
	score = 0;
	combo = 2;
	t_start = time(0);
	long t_now = t_start;
	//	_beginthread(&draw_timer, 0, NULL);
	BeginBatchDraw();
	textstyle.lfHeight = 50;
	textstyle.lfWidth = 30;
	settextstyle(&textstyle);
	char level_name[10];
	sprintf(level_name, "第%d关得分", level);
	RECT rr = { 650, 35, 870, 120 };
	drawtext(CString(level_name), &rr, DT_VCENTER | DT_CENTER | DT_SINGLELINE);

	setfillcolor(BGR(0xF7E085));
	solidroundrect(17, windows_lenth - 3, windows_width - 17, windows_lenth + 23, 6, 6);
	setfillcolor(BGR(0xAD4560));
	solidroundrect(20, windows_lenth, windows_width - 20, windows_lenth + 20, 6, 6);
	setfillcolor(WHITE);
	EndBatchDraw();
	setlinecolor(BGR(0xF7E085));

	FlushMouseMsgBuffer();
	settextcolor(BLACK);

	bool clked = false;						//记录是否已经选中了一张图片
	short x1 = 0, y1 = 0, x2 = 0, y2 = 0;
	short lenth;
	while (1)
	{
		if (t_now != time(0))
		{
			BeginBatchDraw();
			setfillcolor(BGR(0xF7E085));
			solidroundrect(17, windows_lenth - 3, windows_width - 17, windows_lenth + 23, 6, 6);
			setfillcolor(BGR(0xAD4560));
			lenth = resttime * (windows_width - 40) / t_limit;
			solidroundrect(20, windows_lenth, 20 + lenth, windows_lenth + 20, 6, 6);
			setfillcolor(WHITE);
			EndBatchDraw();
			resttime--;
			t_now = time(0);
		}
		//时间到
		if (!resttime)
		{

			game_over();
			flg = true;
			Sleep(2 * 1000);
			return;
		}
		short tmpx1 = 0, tmpy1 = 0, tmpx2 = 0, tmpy2 = 0;
		if (MouseHit())
		{
			MOUSEMSG m;
			m = GetMouseMsg();
			if (m.mkLButton)
			{
				if (clk_labels(m, true) == 17 && nshuffle)
				{
					nshuffle--;
					char s[10];
					sprintf(s, "%c / 1 次", nshuffle + '0');
					settextcolor(BLACK);
					drawtext(CString(s), &rtshuffle, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
					srand((unsigned)time(0));
					shuffle();
					draw_map();
					continue;
				}
				else if (clk_labels(m, true) == 18 && nhint)
				{
					nhint--;
					char s[10];
					sprintf(s, "%c / 2 次", nhint + '0');
					settextcolor(BLACK);
					drawtext(CString(s), &rthint, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
					hint();
					continue;
				}
				else if (clk_labels(m, true) == 19)
				{
					flg = true;
					return;					//bk_to_menu
				}
				else if (clk_labels(m, true) == 0)		//点击格子区域
				{
					if (clked)
					{
						x2 = (m.x - x0) / grid_size;
						y2 = (m.y - y0) / grid_size;

						short x3 = x1;
						short y3 = y1;
						short x4 = x2;
						short y4 = y2;
						if (x1 == x2 && y1 == y2)
						{
							clked = false;
							combo = 2;
							putimage(grid[y1][x1].x, grid[y1][x1].y, &img[grid[y1][x1].img_num]);

						}
						//能够消除
						else if (is_connected(x1, y1, x2, y2, x3, y3, x4, y4))
						{
							n_img -= 2;
							short tmpt = (short)(time(0) - t_start);
							if (tmpt - t < 2)
								combo = combo * 2;
							else
								combo = 2;
							t = tmpt;
							score += combo;
							print_score(score);
							setlinecolor(BGR(0xF7E085));

							drawrectangle(x1, y1);
							drawrectangle(x2, y2);
							drawline(x1, y1, x3, y3);
							drawline(x3, y3, x4, y4);
							drawline(x4, y4, x2, y2);

							Sleep(300);

							BeginBatchDraw();

							setlinecolor(WHITE);
							drawrectangle(x1, y1);
							drawrectangle(x2, y2);
							drawsolidrectangle(x1, y1);
							drawsolidrectangle(x2, y2);
							drawline(x1, y1, x3, y3);
							drawline(x3, y3, x4, y4);
							drawline(x4, y4, x2, y2);

							EndBatchDraw();

							setlinecolor(BGR(0xF7E085));

							grid[y1][x1].img_num = -1;
							grid[y2][x2].img_num = -1;
							if (judge())
							{
								return;
							}
							clked = false;
						}
						//不能消除
						else
						{
							putimage(grid[y1][x1].x, grid[y1][x1].y, &img[grid[y1][x1].img_num]);
							x1 = x2;
							y1 = y2;
							combo = 2;
							drawrectangle(x1, y1);
						}
					}
					else
					{
						x1 = (m.x - x0) / grid_size;
						y1 = (m.y - y0) / grid_size;
						drawrectangle(x1, y1);
						clked = true;
					}
				}
				else if (clk_labels(m, true) == -1)		//既没有点击labels也没有点击格子区域,包括已被消除的区域!!!					
				{
					continue;
				}
			}
		}
	}
}

//游戏界面的“判断”模块
//返回true就是游戏成功,false就是残局
bool judge()			
{

	//判断是否在规定时间内全部消除(即是否成功过关)
	if (!n_img && resttime)
	{
		save_memory();
		
		setbkmode(TRANSPARENT);

		BeginBatchDraw();
		if (level != 5)
			drawtext(_T("游戏成功!2s后进入下一关..."), &R, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
		else
			drawtext(_T("恭喜您已经通关!2s后返回菜单界面..."), &R, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
		EndBatchDraw();

		setbkmode(OPAQUE);

		flg = false;
		Sleep(2 * 1000);
		level++;
		return true;
	}

	//残局
	short tmpx1, tmpy1, tmpx2, tmpy2;
	if (!is_solution(tmpx1, tmpy1, tmpx2, tmpy2))
	{

		shuffle();
		flg = false;
		return false;
	}
	return false;
}

//游戏失败,输出提示文字
void game_over()
{

	setfillcolor(WHITE);
	settextcolor(BGR(0xAD4560));

	setbkmode(TRANSPARENT);

	BeginBatchDraw();
	drawtext(_T("时间到,游戏失败!2s后返回菜单界面..."), &R, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
	EndBatchDraw();

	setbkmode(OPAQUE);
}

//游戏界面
//绘制游戏界面基本形状及文字
void draw_game_window()
{
	setbkcolor(WHITE);				//背景色
	setfillcolor(WHITE);
	textstyle.lfHeight = 50;
	textstyle.lfWidth = 30;
	settextstyle(&textstyle);

	BeginBatchDraw();

	putimage(0, 0, &img[14]);
	setfillcolor(WHITE);
	solidroundrect(22, 22, 628, 468, 15, 15);
	print_score(0);
	settextcolor(BLACK);
	drawtext(_T("2 / 2 次"), &rthint, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);
	drawtext(_T("1 / 1 次"), &rtshuffle, DT_RIGHT | DT_VCENTER | DT_SINGLELINE);

	EndBatchDraw();
}

//显示得分
void print_score(int score)
{
	char sscore[10];
	itoa(score, sscore, 10);
	settextcolor(BGR(0xAD4560));
	drawtext(CString(sscore), &rscores, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
}

//游戏界面,提示
void hint()
{
	short s_x1 = 1, s_y1 = 1, s_x2 = 1, s_y2 = 1;
	setlinecolor(BGR(0x41BFDA));

	if (is_solution(s_x1, s_y1, s_x2, s_y2))
	{
		BeginBatchDraw();

		drawrectangle(s_x1, s_y1);
		drawrectangle(s_x2, s_y2);

		EndBatchDraw();

		Sleep(5 * 100);

		BeginBatchDraw();

		putimage(grid[s_y1][s_x1].x, grid[s_y1][s_x1].y, &img[grid[s_y1][s_x1].img_num]);
		putimage(grid[s_y2][s_x2].x, grid[s_y2][s_x2].y, &img[grid[s_y2][s_x2].img_num]);

		EndBatchDraw();

		setlinecolor(BGR(0xF7E085));
		return;
	}
	//其实一定会有解的,这条语句可以删除
	else
		return;
}

//设置界面
void setting()
{
	BeginBatchDraw();

	setfillcolor(WHITE);
	solidroundrect(225, 20, 675, 500, 20, 20);

	textstyle.lfHeight = 70;
	textstyle.lfWidth = 50;
	settextstyle(&textstyle);
	settextcolor(BGR(0xfed9db));
	setbkcolor(WHITE);
	drawtext(_T("设置"), &rrank1, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
	putimage(410, 440, &img[15]);

	settextcolor(BGR(0x94b7bd));
	textstyle.lfHeight = 45;
	textstyle.lfWidth = 28;
	settextstyle(&textstyle);
	for (short i = 0; i < 5; i++)
	{
		setfillcolor(BGR(0xf9f0e8));
		setbkcolor(BGR(0xf9f0e8));

		solidroundrect(330, 180 + (i - 1) * 60, 570, 180 + (i - 1) * 60 + 50, 10, 10);

		RECT tmpr = { 330, 180 + (i - 1) * 60, 570, 180 + (i - 1) * 60 + 50 };

		char sscr[10], clevel[10];

		sprintf(clevel, "第%d关", i + 1);
		drawtext(CString(clevel), &tmpr, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
	}
	setlinecolor(BGR(0xF7E085));
	roundrect(330 + 1, 180 + (prechoice - 1) * 60 - 1, 570 + 1, 180 + (prechoice - 1) * 60 + 50 - 1, 10, 10);
	
	EndBatchDraw();

	MOUSEMSG m;
	while (1)
	{
		m = GetMouseMsg();
		if (m.mkLButton)
		{
			if (m.mkLButton && lclose_rank.init(m))
				return;
			else
				clk_levels(m);
		}
	}
}

//设置界面,判断选择的是哪一关
void clk_levels(MOUSEMSG m)
{
	for (short i = 0; i < 5; i++)
	{
		if (m.x > 330 && m.x < 570
			&& m.y < 180 + (i - 1) * 60 + 50 && m.y > 180 + (i - 1) * 60)
		{
			setlinecolor(BGR(0xf9f0e8));
			roundrect(330 + 1, 180 + (prechoice - 1) * 60 - 1, 570 + 1, 180 + (prechoice - 1) * 60 + 50 - 1, 10, 10);
			prechoice = i;
			level = i + 1;
			setlinecolor(BGR(0xF7E085));
			roundrect(330 + 1, 180 + (i - 1) * 60 - 1, 570 + 1, 180 + (i - 1) * 60 + 50 - 1, 10, 10);
		}
	}
	return;
}

//排行榜界面
void rank_list()
{
	FILE *fp;
	short scr;

	setfillcolor(WHITE);
	solidroundrect(225, 20, 675, 500, 20, 20);

	textstyle.lfHeight = 70;
	textstyle.lfWidth = 50;
	settextstyle(&textstyle);
	settextcolor(BGR(0xfed9db));
	setbkcolor(WHITE);
	drawtext(_T("排行榜"), &rrank1, DT_VCENTER | DT_CENTER | DT_SINGLELINE);
	putimage(410, 440, &img[15]);

	settextcolor(BGR(0x94b7bd));
	textstyle.lfHeight = 50;
	textstyle.lfWidth = 30;
	settextstyle(&textstyle);

	BeginBatchDraw();

	for (short i = 0; i < 5; i++)
	{
		sprintf(fl_name, "rank_list%d.txt", i + 1);
		setfillcolor(WHITE);
		setbkcolor(WHITE);
		if (!(i % 2))
		{
			setfillcolor(BGR(0xf9f0e8));
			setbkcolor(BGR(0xf9f0e8));
		}

		solidroundrect(240, 180 + (i - 1) * 60, 360, 180 + i * 60, 10, 10);
		solidroundrect(380, 180 + (i - 1) * 60, 665, 180 + i * 60, 10, 10);

		RECT tmpr1 = { 240, 180 + (i - 1) * 60, 360, 180 + i * 60 };
		RECT tmpr2 = { 380, 180 + (i - 1) * 60, 665, 180 + i * 60 };

		char sscr[10], clevel[10];

		sprintf(clevel, "第%d关", i + 1);
		drawtext(CString(clevel), &tmpr1, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		if (!(fp = fopen(fl_name, "r")))
			drawtext(_T("无人上榜"), &tmpr2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
		else
		{
			fread(&scr, sizeof(scr), 1, fp);
			itoa(scr, sscr, 10);
			drawtext(CString(sscr), &tmpr2, DT_CENTER | DT_VCENTER | DT_SINGLELINE);
			fclose(fp);
		}
	}
	EndBatchDraw();

	MOUSEMSG m;

	while (1)
	{
		m = GetMouseMsg();
		if (m.mkLButton && lclose_rank.init(m))
			return;
	}
}

//过关后存档
void save_memory()
{
	FILE *fp;
	short i = 0;
	short scr;
	sprintf(fl_name, "rank_list%d.txt", level);
	if (fp = fopen(fl_name, "r"))
	{
		fread(&scr, sizeof(scr), 1, fp);
		if (scr < score)
			scr = score;
		fclose(fp);
		remove(fl_name);
	}
	else
	{
		scr = score;
	}
	fp = fopen(fl_name, "w+");
	fwrite(&scr, sizeof(scr), 1, fp);
	fclose(fp);
}

//绘制形状
void drawsolidrectangle(short  x, short y)
{
	setfillcolor(WHITE);
	solidrectangle(grid[y][x].x, grid[y][x].y, grid[y][x].x + grid_size, grid[y][x].y + grid_size);
}

void drawrectangle(short x, short y)
{
	rectangle(grid[y][x].x + 1, grid[y][x].y + 1, grid[y][x].x + grid_size - 2, grid[y][x].y + grid_size - 2);
}

void drawline(short x1, short y1, short x2, short y2)
{

	LINESTYLE linestyle;
	linestyle.thickness = 3;
	setlinestyle(&linestyle);

	line(grid[y1][x1].x + grid_size / 2, grid[y1][x1].y + grid_size / 2, grid[y2][x2].x + grid_size / 2, grid[y2][x2].y + grid_size / 2);
}

//画开始菜单
void draw_start_menu()
{
	putimage(0, 0, &img[13]);
}

short clk_labels(MOUSEMSG m, bool _flg)
{
	short x = (m.x - x0) / grid_size;
	short y = (m.y - y0) / grid_size;

	if (!_flg)
	{
		if (lstart_game.init(m))
			return 13;
		else if (lrank_list.init(m))
			return 14;
		else if (lexit_game.init(m))
			return 15;
		else if (lsetting.init(m))
			return 16;
	}
	else if (_flg)
	{
		if (lshuffle.init(m))
			return 17;
		else if (lhint.init(m))
			return 18;
		else if (lbk_to_menu.init(m))
			return 19;
		else if (x > -1 && y > -1 && x < column && y < row && grid[y][x].img_num != -1)
			return 0;
		else
			return -1;
	}
}

//初始化grid[][].img_num
//第一、二关地图
void initmap1()
{
	for (int i = 0; i < column; i++)
	{
		grid[0][i].img_num = -1;
		grid[row - 1][i].img_num = -1;
	}
	for (int j = 0; j < row; j++)
	{
		grid[j][0].img_num = -1;
		grid[j][column - 1].img_num = -1;
	}
	srand(unsigned(time(0)));
	for (int j = 1; j < row / 2; j++)
		for (int i = 1; i < column - 1; i++)
		{
			grid[j][i].img_num = rand() % 13;
			grid[j + row / 2 - 1][i].img_num = grid[j][i].img_num;
		}

	do
	{
		srand((unsigned)time(0));
		for (int i = 1; i < level1.n_img + 1; i++)
		{
			shuffle();
		}
	} while (!ten_solutions());

	draw_map();
}

//第三关地图,呈十字形
void initmap2()
{
	for (int i = 0; i < column; i++)
	{
		grid[0][i].img_num = -1;
		grid[row - 1][i].img_num = -1;
	}
	for (int j = 0; j < row; j++)
	{
		grid[j][0].img_num = -1;
		grid[j][column - 1].img_num = -1;
	}
	for (short j = 1; j < 4; j++)
		for (short i = 1; i < 6; i++)
		{
			grid[j][i].img_num = -1;

		}
	for (short j = 1; j < 4; j++)
		for (short i = 10; i < 15; i++)
		{
			grid[j][i].img_num = -1;

		}
	for (short j = 8; j < 11; j++)
		for (short i = 10; i < 15; i++)
		{
			grid[j][i].img_num = -1;

		}
	for (short j = 8; j < 11; j++)
		for (short i = 1; i < 6; i++)
		{
			grid[j][i].img_num = -1;

		}

	srand(unsigned(time(0)));
	for (int j = 4; j < 6; j++)
		for (int i = 1; i < column - 1; i++)
		{
			grid[j][i].img_num = rand() % 13;
			grid[j + 2][i].img_num = grid[j][i].img_num;
		}
	for (int j = 1; j < 4; j++)
		for (int i = 6; i < 10; i++)
		{
			grid[j][i].img_num = rand() % 13;
			grid[j + 7][i].img_num = grid[j][i].img_num;

		}

	do
	{
		srand((unsigned)time(0));
		for (int i = 1; i < level2.n_img + 1; i++)
		{
			shuffle();
		}
	} while (!ten_solutions());

	draw_map();
}

//第四、五关地图,主对角线附近为空
void initmap3()
{
	for (short k = 12; k < 15; k++)
		for (short j = 1; j < row - 1; j++)
		{
			short i = k - j;
			grid[j][i].img_num = -1;
		}
	for (int i = 0; i < column; i++)
	{
		grid[0][i].img_num = -1;
		grid[row - 1][i].img_num = -1;
	}
	for (int j = 0; j < row; j++)
	{
		grid[j][0].img_num = -1;
		grid[j][column - 1].img_num = -1;
	}

	srand(unsigned(time(0)));
	for (short k = 2; k < 12; k++)
		for (short j = 1; j < k; j++)
		{
			grid[j][k - j].img_num = rand() % 13;
			grid[11 - j][15 - k + j].img_num = grid[j][k - j].img_num;

		}

	do
	{
		srand((unsigned)time(0));
		for (int i = 1; i < level3.n_img + 1; i++)
		{
			shuffle();
		}
	} while (!ten_solutions());

	draw_map();
}

//把图片输出
void draw_map()
{
	BeginBatchDraw();

	setfillcolor(WHITE);
	for (short j = 1; j < row - 1; j++)
		for (short i = 1; i < column - 1; i++)
		{
			if (grid[j][i].img_num != -1)
				putimage(grid[j][i].x, grid[j][i].y, &img[grid[j][i].img_num]);
			else
				drawsolidrectangle(i, j);
		}

	EndBatchDraw();
}

//初始化保证至少有十对图案可以消除
bool ten_solutions()
{
	short tmpx1, tmpy1, tmpx2, tmpy2, nsolution = 0, tmpx3, tmpy3, tmpx4, tmpy4;
	for (tmpy1 = 1; tmpy1 < row - 1; tmpy1++)
		for (tmpx1 = 1; tmpx1 < column - 1; tmpx1++)
			for (tmpy2 = tmpy1; tmpy2 < row - 1; tmpy2++)
				for (tmpx2 = 1; tmpx2 < column - 1; tmpx2++)
				{
					if (grid[tmpy1][tmpx1].img_num != -1 && grid[tmpy2][tmpx2].img_num != -1
						&& is_connected(tmpx1, tmpy1, tmpx2, tmpy2, tmpx3, tmpy3, tmpx4, tmpy4))
					{
						nsolution++;
						if (nsolution >= 10)
							return true;
					}
				}
	return false;
}

//洗牌,直到有解
void shuffle()
{
	short tmpx1 = 0, tmpy1 = 0, tmpx2 = 0, tmpy2 = 0, tmp_imgn = -1;

	do
	{
		do
		{
			tmpx1 = rand() % column;
			tmpy1 = rand() % row;
		} while (grid[tmpy1][tmpx1].img_num == -1);
		do
		{
			tmpx2 = rand() % column;
			tmpy2 = rand() % row;
		} while (grid[tmpy2][tmpx2].img_num == -1);
		tmp_imgn = grid[tmpy1][tmpx1].img_num;
		grid[tmpy1][tmpx1].img_num = grid[tmpy2][tmpx2].img_num;
		grid[tmpy2][tmpx2].img_num = tmp_imgn;
	} while (grid[tmpy1][tmpx1].img_num == grid[tmpy2][tmpx2].img_num
		|| !is_solution(tmpx1, tmpy1, tmpx2, tmpy2));
}

//初始化grid[][].x, grid[][].y
void initgridxy()
{
	for (int j = 0; j < row; j++)
		for (int i = 0; i < column; i++)
		{
			grid[j][i].x = x0 + i*(grid_size + gap);
			grid[j][i].y = y0 + j*(grid_size + gap);
		}
}

//载入图像
void initimg()
{
	char img_name[16];
	for (int i = 0; i < 10; i++)
	{
		sprintf(img_name, "imag\\%c.png", i + '0');
		loadimage(&img[i], CString(img_name), grid_size, grid_size);
	}
	for (int i = 0; i < 3; i++)
	{
		sprintf(img_name, "imag\\1%c.png", i + '0');
		loadimage(&img[i + 10], CString(img_name), grid_size, grid_size);
	}
	loadimage(&img[13], _T("imag\\13.png"));
	loadimage(&img[14], _T("imag\\14.png"));
	loadimage(&img[15], _T("imag\\15.jpg"), 79, 46);
}

//中间是否有其他点,保证l < r
bool x_no_dots_between(short x1, short x2, short y)
{
	short l = x1 < x2 ? x1 : x2, r = x1 > x2 ? x1 : x2;
	for (int i = l + 1; i < r; i++)
	{
		if (grid[y][i].img_num != -1)
			return false;
	}
	return true;
}

//中间是否有其他点,保证t < b
bool y_no_dots_between(short y1, short y2, short x)
{
	short t = y1 < y2 ? y1 : y2, b = y1 > y2 ? y1 : y2;
	for (int i = t + 1; i < b; i++)
	{
		if (grid[i][x].img_num != -1)
			return false;
	}
	return true;
}

//判断连通情况
bool is_connected(short x1, short y1, short x2, short y2, short &x3, short &y3, short &x4, short &y4)
{
	if (grid[y1][x1].img_num == grid[y2][x2].img_num && grid[y1][x1].img_num != -1)
	{
		if (x1 == x2 && y1 == y2)
			return false;
		if (x1 == x2 || y1 == y2)
		{
			if (no_turn(x1, y1, x2, y2))
			{
				return true;
			}
			if (two_turns(x1, y1, x2, y2, x3, y3, x4, y4))
			{
				return true;
			}
		}
		else
		{
			if (one_turn(x1, y1, x2, y2, x3, y3))
			{
				return true;
			}
			if (two_turns(x1, y1, x2, y2, x3, y3, x4, y4))
			{
				return true;
			}
		}
	}
	return false;
}

//不经过拐点直接连通
bool no_turn(short x1, short y1, short x2, short y2)
{
	if (y1 == y2)
	{
		if (x_no_dots_between(x1, x2, y1))
			return true;
	}
	else
	{
		if (y_no_dots_between(y1, y2, x1))
			return true;
	}
	return false;
}

//经过一个拐点
bool one_turn(short x1, short y1, short x2, short y2, short &x3, short &y3)
{
	if (grid[y1][x2].img_num == -1 && no_turn(x1, y1, x2, y1) && no_turn(x2, y1, x2, y2))
	{
		x3 = x2;
		y3 = y1;
		return true;
	}
	if (grid[y2][x1].img_num == -1 && no_turn(x1, y1, x1, y2) && no_turn(x1, y2, x2, y2))
	{
		x3 = x1;
		y3 = y2;
		return true;
	}
	return false;
}

//经过两个拐点
bool two_turns(short x1, short y1, short x2, short y2, short &x3, short &y3, short &x4, short &y4)
{
	for (int i = 0; i < column; i++)
		if (i != x1 && i != x2 && grid[y1][i].img_num == -1 && grid[y2][i].img_num == -1)
			//不写成no_turn && one_turn是为了避免与ont_turn 两种情况之一重复
			if (no_turn(x1, y1, i, y1) && no_turn(i, y1, i, y2) && no_turn(i, y2, x2, y2))
			{
				x3 = i;
				y3 = y1;
				x4 = i;
				y4 = y2;
				return true;
			}

	for (int i = 0; i < row; i++)
		if (i != y1 && i != y2 && grid[i][x1].img_num == -1 && grid[i][x2].img_num == -1)
			if (no_turn(x1, y1, x1, i) && no_turn(x1, i, x2, i) && no_turn(x2, i, x2, y2))
			{
				x3 = x1;
				y3 = i;
				x4 = x2;
				y4 = i;
				return true;
			}
	return false;
}

//有无解
bool is_solution(short &x1, short &y1, short &x2, short &y2)
{
	short tmpx3, tmpy3, tmpx4, tmpy4;
	for (y1 = 1; y1 < row - 1; y1++)
		for (x1 = 1; x1 < column - 1; x1++)
			for (y2 = y1; y2 < row - 1; y2++)
				for (x2 = 1; x2 < column - 1; x2++)
				{
					if (grid[y1][x1].img_num != -1)
						if (grid[y2][x2].img_num != -1)
							if (grid[y1][x1].img_num == grid[y2][x2].img_num)
								if (is_connected(x1, y1, x2, y2, tmpx3, tmpy3, tmpx4, tmpy4))
									return true;
				}
	return false;
}

标签:y2,short,连连看,img,图片素材,源码,grid,y1,x1
来源: https://blog.csdn.net/qq_40930634/article/details/111923895