#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <conio.h>
#include <Windows.h>
#include <stdbool.h>
#pragma region _CONSTANT_VALUE
#define MAP_MIN_SIZE 5
#define MAP_MAX_SIZE 20
#pragma endregion
#pragma region _ENUMERATION
typedef enum STATE {
Disable = 0,
Active = 1,
cDisable = -1,
cActive = 2
}STATE;
typedef enum KEYS {
KEYS_UP = 72,
KEYS_DOWN = 80,
KEYS_LEFT = 75,
KEYS_RIGHT = 77,
KEYS_SPACE = 32,
KEYS_ESC = 27
}KEYS;
typedef enum COLOR {
BLACK = 0,
BLUE = 1,
GREEN = 2,
JADE = 3,
RED = 4,
PURPLE = 5,
YELLOW = 6,
WHITE = 7,
GRAY = 8,
LIGHTBLUE = 9,
LIGHTGREEN = 10,
LIGHTJADE = 11,
LIGHTRED = 12,
LIGHTPURPLE = 13,
LIGHTYELLOW = 14,
DARKGRAY = 15
}COLOR;
#pragma endregion
#pragma region _STRUCTURE
typedef struct Pos {
int x;
int y;
}Pos;
typedef struct Hint {
//Pos *pos;
int value;
struct Hint *next;
}Hint;
typedef struct Ground {
int size;
int **BG;
Hint **rHint;
Hint **cHint;
}Ground;
#pragma endregion
#pragma region _FUNCTION
int getDepth(Hint *);
Hint *getHint(Hint *, int);
Hint *setHint(int);
void addHint(Hint *, int);
void setParent(Hint *, Hint *);
Pos *setPos(int, int);
Ground *setGround(int);
bool printGround(Ground *, Pos *);
void printHorizontalLine(int);
void Click(Ground *g, Pos *focus);
void DeleteHint(Hint *);
void DeletePos(Pos *);
void DeleteGround(Ground *);
#pragma endregion
int main(void) {
system("mode con:cols=150 lines=60");
bool state = false; //게임 종료 여부
int size;
do {
system("cls");
printf("map size : ");
scanf("%d", &size);
} while (!(size >= MAP_MIN_SIZE && size <= MAP_MAX_SIZE));
Pos *focus = setPos(0, 0);
//user cursor location
Ground *g = setGround(size);
printGround(g, focus);
int key;
while (1) {
state = false;
if (_kbhit()) {
key = _getch();
switch (key) {
case 0:
case 224:
key = _getch();
switch (key) {
case KEYS_LEFT:
if (focus->x - 1 >= 0) {
focus->x--;
}
else {
focus->x = g->size - 1;
}
break;
case KEYS_RIGHT:
if (focus->x + 1 < g->size) {
focus->x++;
}
else {
focus->x = 0;
}
break;
case KEYS_UP:
if (focus->y - 1 >= 0) {
focus->y--;
}
else {
focus->y = g->size - 1;
}
break;
case KEYS_DOWN:
if (focus->y + 1 < g->size) {
focus->y++;
}
else {
focus->y = 0;
}
break;
default:
//not special key
break;
}
break;
case KEYS_ESC:
state = true;
break;
case KEYS_SPACE: //space
Click(g, focus);
key = _getch();
break;
default:
//not special key
break;
}
if (state) {
//ESC 누르면 게임 종료
break;
}
if (printGround(g, focus)) {
//모든 구역 선택 완료시 게임 종료
break;
}
}
}
DeleteGround(g);
DeletePos(focus);
return 0;
}
int getDepth(Hint *root) {
int depth = 1;
if (root->value == 0) {
depth = 0;
}
if (root->next != NULL) {
depth += getDepth(root->next);
}
return depth;
}
Hint *getHint(Hint *root, int depth) {
if (depth <= 1) {
return root;
}
else {
return getHint(root->next, depth - 1);
}
}
Hint *setHint(int value) {
Hint *p = (Hint *)malloc(sizeof(Hint));
p->value = value;
p->next = NULL;
//p->pos = NULL;
return p;
}
void addHint(Hint *target, int value) {
target->value += value;
return;
}
void setParent(Hint *parent, Hint *son) {
if (parent->next != NULL) {
setParent(parent->next, son);
}
else {
parent->next = son;
}
return;
}
Pos *setPos(int x, int y) {
Pos *p = (Pos *)malloc(sizeof(Pos));
p->x = x;
p->y = y;
return p;
}
Ground *setGround(int size) {
Ground *g = (Ground *)malloc(sizeof(Ground));
g->size = size;
g->BG = (int **)malloc(sizeof(int *) * g->size);
srand((unsigned int)time(NULL));
for (int i = 0; i < g->size; i++) {
g->BG[i] = (int *)malloc(sizeof(int) * g->size);
for (int y = 0; y < g->size; y++) {
g->BG[i][y] = rand() % 2;
//랜덤 값 생성
}
//alloc memory and Initialization
}
g->cHint = (Hint **)malloc(sizeof(Hint *) * g->size);
g->rHint = (Hint **)malloc(sizeof(Hint *) * g->size);
int depth;
for (int y = 0; y < g->size; y++) {
//Get row hint
g->rHint[y] = setHint(0);
//alloc memory
depth = 1;
//depth
for (int x = 0; x < g->size; x++) {
if (g->BG[x][y]) {
addHint(getHint(g->rHint[y], depth), 1);
//Add 1 into last Hint;
}
else {
if (getHint(g->rHint[y], depth)->value) {
//If value of select hint is not 0
setParent(g->rHint[y], setHint(0));
depth++;
}
}
}
}
for (int x = 0; x < g->size; x++) {
g->cHint[x] = setHint(0);
depth = 1;
for (int y = 0; y < g->size; y++) {
if (g->BG[x][y]) {
addHint(getHint(g->cHint[x], depth), 1);
}
else {
if (getHint(g->cHint[x], depth)->value) {
setParent(g->cHint[x], setHint(0));
depth++;
}
}
}
}
//same function :: column
return g;
}
bool printGround(Ground *g, Pos *focus) {
bool state = true;
//게임 종료 여부
int rMax, cMax;
rMax = cMax = 0;
int depth;
for (int i = 0; i < g->size; i++) {
depth = getDepth(g->rHint[i]);
if (rMax < depth) {
rMax = depth;
}
depth = getDepth(g->cHint[i]);
if (cMax < depth) {
cMax = depth;
}
} //get Max depth
system("cls");
//clear screen
printf("\n");
for (int c = 1; c < cMax + 1; c++) {
//column Hints
for (int r = 0; r < rMax; r++) {
//sort text
printf(" ");
}
printf("|");
Hint *temps;
for (int r = 0; r < g->size; r++) {
depth = getDepth(g->cHint[r]) - cMax + c;
if (depth >= 1) {
temps = getHint(g->cHint[r], depth);
printf(" %2d ", getHint(g->cHint[r], depth)->value);
}
else {
if (cMax - 1 == depth) {
printf(" 0 ");
}
else {
printf(" ");
}
}
}
printf("\n\n");
}
//print column Hint
printHorizontalLine(rMax + g->size);
for (int i = 0; i < g->size; i++) {
for (int r = 0; r < rMax - getDepth(g->rHint[i]); r++) {
if (rMax - 1 == r) {
printf(" 0 ");
}
else {
printf(" ");
}
}
depth = getDepth(g->rHint[i]);
for (int d = 1; d < depth + 1; d++) {
printf(" %2d ", getHint(g->rHint[i], d)->value);
}
printf("|");
for (int x = 0; x < g->size; x++) {
if (x == focus->x && i == focus->y) {
if (g->BG[focus->x][focus->y] == Disable) {
//선택한 위치가 아직 확인되지 않은 경우
state = false;
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), LIGHTYELLOW);
printf(" YOU");
}
else {
switch (g->BG[x][i]) {
case Active:
case Disable:
state = false;
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), WHITE);
printf(" __ ");
break;
case cActive:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), LIGHTGREEN);
printf("OKEY");
break;
case cDisable:
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), LIGHTRED);
printf("DONT");
break;
default:
break;
}
}
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), WHITE);
}
printf("\n\n");
}
return state;
}
void printHorizontalLine(int length) {
for (int i = 0; i < length; i++) {
printf("----");
}
printf("\n");
return;
}
void Click(Ground *g, Pos *focus) {
switch (g->BG[focus->x][focus->y]) {
case Active:
g->BG[focus->x][focus->y] = cActive;
break;
case Disable:
g->BG[focus->x][focus->y] = cDisable;
break;
default:
break;
}
return;
}
#pragma region Delete
// http://pang2h.tistory.com
void DeleteHint(Hint *target) {
if (target->next != NULL) {
DeleteHint(target->next);
}
else {
//DeletePos(target->pos);
target->value = 0;
//Initialization
free(target);
}
return;
}
void DeletePos(Pos *target) {
if (target != NULL) {
target->x = target->y = 0;
//Initialization
free(target);
}
return;
}
void DeleteGround(Ground *target) {
if (target->BG != NULL) {
for (int i = 0; i < target->size; i++) {
memset(target->BG[i], 0, sizeof(int) * target->size);
//Initialization
free(target->BG[i]);
}
free(target->BG);
}
free(target);
return;
}
#pragma endregion