很简陋的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列的灯,开始时全部是灭的,当你点击其中一盏灯时他的上下左右(若存在的话)
状态全部改变,现在要求你在限定的时间内以最少地步数,将全部的灯点亮。*/