关灯游戏

#include<windows.h>
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<conio.h>
#include<wincon.h>
#include<winbase.h>
#include<time.h>
#include<ctype.h>
#include<string.h>
#include<math.h>
using namespace std;
int flag[30][30];//标记是绿色还是红色
int h, w, map[30][30], temp[30][30], m[30][30],ii[30][30],jj[30][30];
int judge(int x, int y) {
	int next[5][2] = { {0,0},{0,1},{0,-1},{1,0},{-1,0} };
	int c = map[x][y];
	for (int k = 0; k < 5; k++) {
		int tx = x + next[k][0];
		int ty = y + next[k][1];
		if (tx >= 1 && tx <= h && ty >= 1 && ty <= w)
			c += temp[tx][ty];
	}
	return c % 2;
}
int dfs() {
	//从第二行开始,根据上一行的状态做出相应反转 
	for (int i = 2; i <= h; i++) {
		for (int j = 1; j <= w; j++) {
			if (judge(i - 1, j)) {
				temp[i][j] = 1;//如果此点上一行对应的点是黑棋,则此点反转一次 
			}
		}
	}
	for (int j = 1; j <= w; j++) {
		if (judge(h,j))//如果最后一行还有黑棋,返回-1; 
			return -1;
	}
	int count = 0;
	//计算总的反转数; 
	for (int i = 1; i <= h; i++) {
		for (int j = 1; j <= w; j++)
			count += temp[i][j];
	}
	return count;
}
void fangan() {
	int min = -1;
	//从第一行开始遍历,第一行棋子的反转情况为2的W次方,用二进制状态压缩; 
	for (int i = 0; i < (1 << w); i++) {  //1<<w为2的w次方 
		memset(temp, 0, sizeof(temp));
		for (int j = 1; j <= w; j++) {
			temp[1][j] = (i >> (j-1)) & 1;//在此i值下第一行的反转情况 
		}
		int num = dfs();//num记录当下方案的总反转数 
		if (num > 0 && (min<0 || min>num)) {
			min = num;
			memcpy(m, temp, sizeof(temp));//用memcpy函数将temp数组赋给m数组; 
		}
	}
	if (min == -1) {
		printf("IMPOSSIBLE\n");
	}
	else {
		//cout << min << endl;
		printf("最佳方案:\n");
		for (int i = 1; i <= h; i++) {
			for (int j = 1; j <= w-1; j++)
				printf("%d ", m[i][j]);
			printf("%d\n", m[i][w]);
		}
	}
	return;
}
HANDLE hout;//光标自由移动必需
//指定光标移动函数,移动到(x,y);
void gotoxy(int x, int y) {
	CONSOLE_SCREEN_BUFFER_INFO csbi;
	HANDLE hConOut;
	hConOut= GetStdHandle(STD_OUTPUT_HANDLE);
	GetConsoleScreenBufferInfo(hConOut, &csbi);
	csbi.dwCursorPosition.X = x;
	csbi.dwCursorPosition.Y = y;
	SetConsoleCursorPosition(hConOut, csbi.dwCursorPosition);
}
char getInput()
{
	int next[4][2] = { {1,0},{0,1},{-1,0},{0,-1} };
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	int ch; //输入字符串

	COORD coord; //屏幕上的坐标
	CONSOLE_SCREEN_BUFFER_INFO csbi; //控制台屏幕缓冲区信息

	coord.X = 10;
	coord.Y = 10;

	ch = _getch();

	//0x0d表示回车,0XE0表示上下左右等键的键码
	while (ch == 0xE0 || ch == 0x20)
	{
		GetConsoleScreenBufferInfo(hout, &csbi);
		coord.X = csbi.dwCursorPosition.X; //得到坐标X的值
		coord.Y = csbi.dwCursorPosition.Y; //得到坐标Y的值
		gotoxy(coord.X, coord.Y);
		//如果是回车
		if (ch == 0x20)
		{
			gotoxy(coord.X, coord.Y);
			if (flag[coord.X][coord.Y] == 1) {
				SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
				flag[coord.X][coord.Y] = 0;
				printf("*");
			}
			else {
				SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
				flag[coord.X][coord.Y] = 1;
				printf("*");
			}
			for (int k = 0; k < 4; k++) {
				gotoxy(coord.X, coord.Y);
				int tx = coord.X + next[k][0];
				int ty = coord.Y + next[k][1];
				if (tx >= 1 && tx <= w && ty >= 1 && ty <= h) {
					if (flag[tx][ty] == 1) {
						gotoxy(tx, ty);
						SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
						flag[tx][ty] = 0;
						printf("*");
						gotoxy(coord.X, coord.Y);
					}
					else {
						gotoxy(tx, ty);
						SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
						flag[tx][ty] = 1;
						printf("*");
						gotoxy(coord.X, coord.Y);
					}
				}
			}
			break;
		}
		ch = _getch();
		//上
		if (ch == 0x48)
		{
			if (coord.Y != 0)coord.Y--;
		}
		//下
		else if (ch == 0x50)
		{
			coord.Y++;
		}
		//左
		else if (ch == 0x4b)
		{
			if (coord.X != 0) { coord.X--; }
		}
		//右
		else if (ch == 0x4d)
		{
			if (coord.X != 79)coord.X++;
			else
			{
				coord.X = 0;
				coord.Y++;
			}
		}
		SetConsoleCursorPosition(hout, coord);
		ch = _getch();
	}
	return ch;
}
int main() {
	h = 5;
	w = 6;
	srand((unsigned)time(NULL));
	hout = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE handle_out = GetStdHandle(STD_OUTPUT_HANDLE);
	HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
	for (int i = 0; i <= w; i++) {
		SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
		cout << i;
	}
	cout << endl;
	for (int i = 1; i <=h; i++) {
		SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_BLUE);
		printf("%d", h + 1 - i);
		for (int j = 1; j <=w;j++) {
			int kk = abs(rand() % 2);
			if (kk) {
			   {SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_GREEN);
			   printf("*"); 
				}
				map[i][j] = flag[j][i] = 0;
			}
			else {
				{SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | FOREGROUND_RED);
				printf("*"); }
				map[i][j] = flag[j][i] = 1;
			}
		}
		printf("\n");
	}
	fangan();
	char ch;
	while (1)
	{
		ch = getInput();
	}
	system("pause");
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值