自己摸索的点灯游戏(涂格子)

很简陋的1.0版本,算是我的入门作品。

 

使用了easyX图形库

//日志:

//2018/12/3/00点33分
//完成初始界面,地图绘制,鼠标点击方块填充功能

//2018/12/3/17点40分
//完成所有部分,进入调试阶段

//问题1:
/*定义maxn的时候二维数组的值想成了单元格的最大大小11,实际上应该是像素的边长640*/
//问题2:
/*进入第一关的时候发现点击一个单元格可以填涂,但是单元格四周的格子没有跟着涂,主要是因为
左键填涂函数在判断上下左右之后忘记改填涂的方位*/
//问题3:
/*游戏方框的外围是可以点击的,要改成不能点击的,暂定改成另一种颜色*/

//2018/12/3/20点11分
//完成调试,beta阶段,版本version 1.0

//2018/12/3/21点56分
//改进目标:
/*1.图形界面
  2.更有趣的关卡
  3.更正常的判定方式和游戏设置
  4.加入快捷键
  5.加入音乐
  6.加入作弊系统
  7.加入用户名、存档、成就系统
  8.更加优质的美工
*/

#include "pch.h"
#include 
#include 
#include 
#include 
#define SELECT_COLOR	RGB(111, 126, 138)	//开灯
#define GRIM_BK_COLOR	RGB(194, 205, 200)	//关灯
#define BOUND_COLOR		WHITE				//边界
#define LINE_COLOR		RGB(75,140,211)		//框线
#define	maxn			800 

//定义单元格属性
class BLOCK
{
public:
	int x;
	//左上角点横坐标
	int y;
	//左上角点纵坐标
	bool selectible;
	//是否可填充
};
//全局变量定义

	//游戏棋盘和关卡
	int cnt = 4;
	//棋盘左上角位置
	int  x, y;
	//定义单元格边长
	const int r = 50;
	//定义地图的二维数组
	BLOCK Grim[maxn][maxn];

//欢迎界面
void init(){
	//界面颜色
	initgraph(800, 600);
	setbkcolor(WHITE);
	cleardevice();
	//定义标题格式  // 黑色“点”
	{
		settextstyle(72, 0, "黑体");
		settextcolor(BLACK);
		//格式输出标题
		outtextxy(260, 60, "点");
	}
	//定义标题格式  // 棕色“灯”
	{
		settextstyle(88, 0, "汉仪铸字木头人W");
		settextcolor(BROWN);
		//格式输出标题
		outtextxy(332, 60, "灯");
	}
	//定义标题格式  // 红色“游戏”
	{
		settextcolor(BLACK);
		settextstyle(72, 0, "黑体");
		outtextxy(404, 60, "游戏");
	}
	//游戏规则部分输出
	{
		const int height_rule = 220;
		settextcolor(BROWN);
		settextstyle(14, 0, "宋体");
		outtextxy(180, height_rule, "这里是游戏规则:鼠标左键点击可以改变一盏灯周围的上下左右和");
		outtextxy(180, height_rule + 20, "中间五盏灯(边界除外)的开关状态。你的任务是通过点击不同的灯,");
		outtextxy(180, height_rule + 40, "让他们全部亮起来。鼠标右键可以清空格子,还原到初始的状态 !");
		outtextxy(180, height_rule + 60, "                                                      ");
		outtextxy(180, height_rule + 80, "                关卡一共有3关,祝你好运!");
		outtextxy(180, height_rule + 80, "                  请切换英文输入法!!!");
		settextcolor(BLACK);
		outtextxy(180, height_rule + 200, "               Made By : 取经中的稳健小锴");
		outtextxy(300, height_rule + 220, "				 	  version : 1.0");
	}
	int n = 255;
	while (!_kbhit()){
		settextcolor(RGB(n, n, n));
		outtextxy(320, 500, "请按任意键继续...");
		n = n - 8;
		Sleep(40);
		if (n < 0) {
			n = 255;
		}
	}
}

//结束界面
void end() {
	setbkcolor(WHITE);
	cleardevice();
	settextstyle(24, 0, "黑体");
	settextcolor(BLACK);
	outtextxy(300, 300, "恭喜你成功通关!");

	int n = 255;
	while (!_kbhit()) {
		settextcolor(RGB(n, n, n));
		outtextxy(260, 500, "按任意键退出...");
		n = n - 8;
		Sleep(40);
		if (n < 0) {
			n = 255;
		}
	}
}

//反转函数
void _Swap(int x, int y) {
	if (getpixel(x, y) == GRIM_BK_COLOR) {
		setfillcolor(SELECT_COLOR);
		floodfill(x, y, LINE_COLOR, 0);
	}
	else if (getpixel(x, y) == SELECT_COLOR) {
		setfillcolor(GRIM_BK_COLOR);
		floodfill(x, y, LINE_COLOR, 0);
	}
}

//加载地图
void BuildGrim(int cnt) {
	//重载地图之前清除屏幕;棋盘底色
	setbkcolor(GRIM_BK_COLOR);
	cleardevice();
	//根据关卡的不同绘制棋盘
	setlinecolor(LINE_COLOR);
	double l = cnt / 2.0;
	x = 400-l*50, y = 300-l*50;
	//画横线
	for (int i = 0; i <= cnt; i++) {
		line(x, y + i * r, x + cnt * r, y + i * r);
	}
	//画竖线
	for (int i = 0; i <= cnt; i++) {
		line(x + i * r, y, x + i * r, y + cnt * r);
	}
	//外围底色
	setfillcolor(BOUND_COLOR);
	floodfill(1, 1, LINE_COLOR);
	//初始化每个单元格,并且设定所有单元格"关灯"
	int i, j;
	for (i = (x + r / 2); i < (x + cnt * r); i = i + r) {
		for (j = (y + r / 2); j < (y + cnt * r); j = j + r) {
			Grim[i][j].x = i;
			Grim[i][j].y = j;
			Grim[i][j].selectible = false;
		}
	}
}

//刷新地图状态
void _Refresh() {
	for (int i = (x + r / 2); i < (x + cnt * r); i = i + r) {
		for (int j = (y + r / 2); j < (y + cnt * r); j = j + r) {
			//如果这一点所在的单元格开灯,更正为true,反之更正为false
			if (getpixel(Grim[i][j].x, Grim[i][j].y) == SELECT_COLOR) {
				Grim[i][j].selectible = true;
			}
			else if(getpixel(Grim[i][j].x, Grim[i][j].y) == GRIM_BK_COLOR) {
				Grim[i][j].selectible = false;
			}
		}
	}
}

//右键重置函数
void _ReStart() {
	BuildGrim(cnt);
}

//判断输赢
bool _Judge() {
	//通过遍历"地图状态中的selectible"来判断输赢
	bool ans = true;
	//flag 是循环中跳出的标志,如果flag为0,说明还有格子没有填涂
	int flag = 1;
	for (int i = (x + r / 2); i < (x + cnt * r); i = i + r) {
		for (int j = (y + r / 2); j < (y + cnt * r); j = j + r) {
			if (getpixel(Grim[i][j].x, Grim[i][j].y) != SELECT_COLOR) {
				ans = false; flag = 0;
			}
			if (flag == 0) {
				break;
			}
		}
		if (flag == 0) {
			break;
		}
	}
	return ans;
}

//左键的填充函数
void _Fill(MOUSEMSG m) {
	//填充光标所选择的方块
	if (getpixel(m.x, m.y) != BOUND_COLOR && getpixel(m.x, m.y) != LINE_COLOR) {
		_Swap(m.x, m.y);
	}
	else {
		return;
	}
	//此颜色为边界颜色
	//判断边界,填充鼠标周围方块
	//上
	if (m.y - r >= y) {
		_Swap(m.x, m.y - r);
	}
	//下
	if (m.y + r <= y + cnt * r) {
		_Swap(m.x, m.y + r);
	}
	//左
	if (m.x - r >= x) {
		_Swap(m.x - r, m.y);
	}
	//右
	if (m.x + r <= x + cnt * r) {
		_Swap(m.x + r, m.y);
	}
}

//游戏主框架
void Game() {

	BuildGrim(cnt);
	MOUSEMSG m;

	while (1) {
		//每次的循环开始前要刷新单元格的状态
		_Refresh();

		//获取鼠标信息
		m = GetMouseMsg();

		switch (m.uMsg)
		{
			//如果按下左键
		case WM_LBUTTONDOWN:
			//进入左键填充函数
			_Fill(m);
			break;

			//如果按下右键
		case WM_RBUTTONDOWN:

			//重新绘制棋盘
			_ReStart();	
			break;
		}
		//判断胜利条件,如果返回胜利,游戏结束,回到主函数
		if (_Judge()) {
			break;
		}
	}
}
int main()
{
	//欢迎界面
	init();
	//主体部分
	while (cnt <= 6) {
		Game();
		cnt++;
	}
	//游戏结束界面
	end();
	getchar();
	return 0;
}

/*点灯游戏的规则:
有一行N行N列的灯,开始时全部是灭的,当你点击其中一盏灯时他的上下左右(若存在的话)
状态全部改变,现在要求你在限定的时间内以最少地步数,将全部的灯点亮。*/

 

 

 

你可能感兴趣的:(个人demo)