Created
April 17, 2025 13:41
-
-
Save Ruthenus/326c881d0ec8a9a133ca01c027934429 to your computer and use it in GitHub Desktop.
Week 17 Homework in IT STEP Academy (maze6.txt refactoring)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <windows.h> | |
#include <conio.h> // _getch | |
#include <ctime> | |
#include <cstdlib> | |
using namespace std; | |
// Розміри ігрового поля (глобальні константи як виняток) | |
const int HEIGHT = 25; | |
const int WIDTH = 65; | |
// Перелік ігрових об'єктів: коридор, стіна, монета, ворог | |
enum GameObject : short { HALL, WALL, COIN, ENEMY }; | |
// Визначення кольорів для консолі (enum не можна перенести в main()) | |
enum Color : short { | |
BLACK, DARKBLUE, DARKGREEN, TURQUOISE, DARKRED, | |
PURPLE, DARKYELLOW, GREY, DARKGREY, BLUE, GREEN, | |
CYAN, RED, PINK, YELLOW, WHITE | |
}; | |
// Коди клавіш керування | |
enum Key : short { | |
LEFT = 75, RIGHT = 77, UP = 72, DOWN = 80, | |
// ENTER = 13, SPACE = 32, ESCAPE = 27, BACKSPACE = 8 | |
}; | |
// https://kbdlayout.info/kbdusx/scancodes | |
// https://kbd-project.org/docs/scancodes/scancodes-5.html#focus | |
// Функція для приховування курсора | |
void hideCursor(HANDLE& h) | |
{ | |
CONSOLE_CURSOR_INFO cursor; | |
cursor.bVisible = false; | |
cursor.dwSize = 100; | |
SetConsoleCursorInfo(h, &cursor); | |
} | |
// Функція для моделювання ігрового поля | |
void modelMap(int map[][WIDTH]) | |
{ | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
map[y][x] = rand() % 4; | |
// HALL = 0, WALL = 1, COIN = 2, ENEMY = 3 | |
// рамка по краях (зовнішні стіни) | |
if (x == 0 || y == 0 || x == WIDTH - 1 || y == HEIGHT - 1) { | |
map[y][x] = GameObject::WALL; | |
} | |
// отвори для входу і виходу | |
if (x == 0 && y == 2 || | |
x == 1 && y == 2 || | |
x == 2 && y == 2 || | |
x == WIDTH - 1 && y == HEIGHT - 3 || | |
x == WIDTH - 2 && y == HEIGHT - 3 || | |
x == WIDTH - 3 && y == HEIGHT - 3) { | |
map[y][x] = GameObject::HALL; | |
} | |
// Щоб уникнути частих зустрічей з ворогом: | |
if (map[y][x] == GameObject::ENEMY) { | |
int r = rand() % 10; | |
if (r != 0) { | |
map[y][x] = GameObject::HALL; | |
} | |
} | |
} | |
} | |
} | |
// Функція для відображення ігрового поля у консолі | |
void viewMap(int map[][WIDTH], HANDLE h) | |
{ | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
switch (map[y][x]) { | |
case GameObject::HALL: // 0 | |
SetConsoleTextAttribute(h, Color::BLACK); | |
cout << " "; | |
break; | |
case GameObject::WALL: // 1 | |
SetConsoleTextAttribute(h, Color::DARKGREEN); | |
cout << (char)178; // https://www.ascii-code.com/CP437/178 | |
break; | |
case GameObject::COIN: // 2 | |
SetConsoleTextAttribute(h, Color::YELLOW); | |
cout << "."; | |
break; | |
case GameObject::ENEMY: // 3 | |
SetConsoleTextAttribute(h, Color::RED); | |
cout << "O"; | |
break; | |
} | |
} | |
cout << "\n"; | |
} | |
} | |
// Функція для розміщення героя у висхідній позиції | |
void deployHero(COORD& hero, HANDLE h) | |
{ | |
hero.X = 0; | |
hero.Y = 2; | |
SetConsoleCursorPosition(h, hero); | |
SetConsoleTextAttribute(h, Color::BLUE); | |
cout << "O"; | |
hideCursor(h); | |
} | |
// Функція для відображення статистики гравця | |
void userStatistics(int coins_collected, HANDLE h) | |
{ | |
COORD coins_info; | |
coins_info.X = WIDTH + 1; | |
coins_info.Y = 0; | |
SetConsoleCursorPosition(h, coins_info); | |
SetConsoleTextAttribute(h, Color::DARKYELLOW); | |
cout << "COINS: "; | |
SetConsoleTextAttribute(h, Color::YELLOW); | |
cout << coins_collected; | |
hideCursor(h); | |
} | |
// Функція для переміщення героя, збирання монет, обробки зіткнень | |
void playHero(int map[][WIDTH], COORD& hero, int& coins_collected, HANDLE h) | |
{ | |
int code = _getch(); // get character | |
if (code == 224) { // зчитування другого коду клавіші | |
code = _getch(); | |
} | |
// https://learn.microsoft.com/ru-ru/cpp/c-runtime-library/reference/getch-getwch?view=msvc-170 | |
COORD old_position = hero; | |
bool has_been_moved = false; // false - пересування не було | |
switch (code) { | |
case Key::LEFT: | |
if (hero.X > 0 && map[hero.Y][hero.X - 1] != GameObject::WALL) { | |
has_been_moved = true; | |
hero.X--; | |
} | |
break; | |
case Key::RIGHT: | |
if (map[hero.Y][hero.X + 1] != GameObject::WALL) { | |
has_been_moved = true; | |
hero.X++; | |
} | |
break; | |
case Key::UP: | |
if (map[hero.Y - 1][hero.X] != GameObject::WALL) { | |
has_been_moved = true; | |
hero.Y--; | |
} | |
break; | |
case Key::DOWN: | |
if (map[hero.Y + 1][hero.X] != GameObject::WALL) { | |
has_been_moved = true; | |
hero.Y++; | |
} | |
break; | |
} | |
if (has_been_moved) { | |
// стирання героя в старих координатах | |
SetConsoleCursorPosition(h, old_position); | |
SetConsoleTextAttribute(h, Color::BLACK); | |
cout << " "; | |
// перемальовка героя в нових координатах | |
SetConsoleCursorPosition(h, hero); | |
SetConsoleTextAttribute(h, Color::BLUE); | |
cout << "O"; | |
} | |
// перевірка на перетинання з якимось об'єктом в лабірінті | |
if (map[hero.Y][hero.X] == GameObject::COIN) { | |
coins_collected++; | |
map[hero.Y][hero.X] = GameObject::HALL; | |
userStatistics(coins_collected, h); | |
} | |
if (map[hero.Y][hero.X] == GameObject::ENEMY) { | |
cout << "ENEMY"; | |
} | |
hideCursor(h); | |
} | |
// Функція для ігрового двигунчика | |
void bomberPerpetuumMobile(int map[][WIDTH], COORD& hero, | |
int& coins_collected, HANDLE h) | |
{ | |
while (true) { | |
playHero(map, hero, coins_collected, h); | |
} | |
} | |
int main() | |
{ | |
system("title Bomberman"); // встановлення назви вікна | |
srand(time(0)); | |
// rand(); // попередження C6031 та C4244 | |
HANDLE h = GetStdHandle(STD_OUTPUT_HANDLE); | |
hideCursor(h); | |
int map[HEIGHT][WIDTH] = {}; | |
modelMap(map); | |
viewMap(map, h); | |
COORD hero; | |
deployHero(hero, h); | |
int coins_collected = 0; | |
userStatistics(coins_collected, h); | |
playHero(map, hero, coins_collected, h); | |
bomberPerpetuumMobile(map, hero, coins_collected, h); | |
Sleep(INFINITE); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment