#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;
}