Добавил:
jetu
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Snake
.cpp#include <iostream>
#include <conio.h>
#include <fcntl.h>
#include <io.h>
#include <ctime>
#include <Windows.h>
#define W_MAX 50
#define H_MAX 20
#define KEY_UP 72
#define KEY_LEFT 75
#define KEY_RIGHT 77
#define KEY_DOWN 80
#define CONTROL_KEYS 224
#define FUNC_KEYS 0
#define KEY_ENTER 13
#define KEY_ESCAPE 27
#define EMPTY 0
#define FOOD -1
#define UP 1
#define RIGHT 2
#define DOWN 3
#define LEFT 4
#define EASY 600
#define NORMAL 400
#define HARD 200
HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
void goto_xy(int x, int y) {
COORD coord;
coord.X = x;
coord.Y = y;
SetConsoleCursorPosition(consoleHandle, coord);
}
void set_text_color(int color) {
SetConsoleTextAttribute(consoleHandle, (WORD)color);
}
struct Point {
short x, y;
};
struct Snake {
Point head = { 0, 0 }, tail = { 0, 0 };
short direction = UP, length = 1;
};
class Field {
private:
short field[H_MAX][W_MAX];
public:
short height, width;
short get_value(Point point) {
return field[point.y][point.x];
}
void set_value(Point point, short value) {
field[point.y][point.x] = value;
}
};
Snake snake;
Field field;
void print_cell(Point point, wchar_t symbol, int color) {
set_text_color(color);
goto_xy(point.x * 2 + 2, point.y + 1);
wprintf(L"%c", symbol);
}
void print_head(short snake_direction) {
if (snake_direction == UP) print_cell(snake.head, L'▲', 14);
else if (snake_direction == RIGHT) print_cell(snake.head, L'►', 14);
else if (snake_direction == DOWN) print_cell(snake.head, L'▼', 14);
else if (snake_direction == LEFT) print_cell(snake.head, L'◄', 14);
}
void print_tail(short tail_direction) {
if (tail_direction == UP) print_cell(snake.tail, L'▼', 10);
else if (tail_direction == RIGHT) print_cell(snake.tail, L'◄', 10);
else if (tail_direction == DOWN) print_cell(snake.tail, L'▲', 10);
else if (tail_direction == LEFT) print_cell(snake.tail, L'►', 10);
}
void move_point(Point* point, short direction) {
if (direction == UP) {
--(*point).y;
if ((*point).y == -1)
(*point).y = field.height - 1;
}
else if (direction == RIGHT) {
++(*point).x;
if ((*point).x == field.width)
(*point).x = 0;
}
else if (direction == DOWN) {
++(*point).y;
if ((*point).y == field.height)
(*point).y = 0;
}
else if (direction == LEFT) {
--(*point).x;
if ((*point).x == -1)
(*point).x = field.width - 1;
}
}
void move_snake(Point next, short snake_direction) {
short tail_direction = field.get_value(snake.tail);
field.set_value(snake.tail, EMPTY);
print_cell(snake.tail, L'·', 8);
move_point(&snake.tail, tail_direction);
if (snake.length > 1) {
print_tail(field.get_value(snake.tail));
if (snake.length != 2)
print_cell(snake.head, L'■', 10);
}
else
print_cell(snake.head, L'·', 8);
snake.head = next;
field.set_value(snake.head, snake_direction);
print_head(snake_direction);
}
int main() {
(void)_setmode(_fileno(stdout), _O_U16TEXT);
// Скрыть курсор
CONSOLE_CURSOR_INFO info;
info.dwSize = 100;
info.bVisible = FALSE;
SetConsoleCursorInfo(consoleHandle, &info);
int default_frequency = NORMAL;
field.width = 7;
field.height = 7;
bool working = true;
while (working) {
// МЕНЮ
short cursor = 1;
bool menu = true;
system("cls");
set_text_color(15);
wprintf(L" ——= ЗМЕЙКА =—— ");
set_text_color(7);
wprintf(L"\n Ширина поля: %2d \n Высота поля: %2d \n Сложность: %-7s \n",
field.width,
field.height,
(default_frequency == EASY) ? L"Низкая" : ((default_frequency == NORMAL) ? L"Средняя" : L"Высокая")
);
set_text_color(14);
wprintf(L"\n [Enter]");
set_text_color(15);
wprintf(L" — начать игру");
while (menu) {
set_text_color(14);
goto_xy(1, cursor);
wprintf(L"—>");
if (cursor == 1) {
goto_xy(17, cursor);
wprintf(L"< %2d >", field.width);
}
else if (cursor == 2) {
goto_xy(17, cursor);
wprintf(L"< %2d >", field.height);
}
else if (cursor == 3) {
goto_xy(15, cursor);
wprintf(L"< %-7s >", (default_frequency == EASY)? L"Низкая" : ((default_frequency == NORMAL)? L"Средняя" : L"Высокая"));
}
// Управление меню
wchar_t input = _getwch();
if (input == FUNC_KEYS)
(void)_getwch();
else if (input == CONTROL_KEYS) {
input = _getwch();
if (input == KEY_UP or input == KEY_DOWN) {
goto_xy(1, cursor);
wprintf(L" ");
if (cursor == 1) {
set_text_color(7);
goto_xy(17, cursor);
wprintf(L" %2d ", field.width);
}
else if (cursor == 2) {
set_text_color(7);
goto_xy(17, cursor);
wprintf(L" %2d ", field.height);
}
else if (cursor == 3) {
set_text_color(7);
goto_xy(15, cursor);
wprintf(L" %-7s ", (default_frequency == EASY) ? L"Низкая" : ((default_frequency == NORMAL) ? L"Средняя" : L"Высокая"));
}
}
if (input == KEY_UP and --cursor == 0) cursor = 3;
else if (input == KEY_DOWN and ++cursor == 4) cursor = 1;
else if (input == KEY_RIGHT) {
if (cursor == 1 and ++field.width > W_MAX) field.width = 3;
if (cursor == 2 and ++field.height > H_MAX) field.height = 3;
if (cursor == 3) {
if (default_frequency == EASY)
default_frequency = NORMAL;
else if (default_frequency == NORMAL)
default_frequency = HARD;
else if (default_frequency == HARD)
default_frequency = EASY;
}
}
else if (input == KEY_LEFT) {
if (cursor == 1 and --field.width < 3) field.width = W_MAX;
if (cursor == 2 and --field.height < 3) field.height = H_MAX;
if (cursor == 3) {
if (default_frequency == HARD)
default_frequency = NORMAL;
else if (default_frequency == NORMAL)
default_frequency = EASY;
else if (default_frequency == EASY)
default_frequency = HARD;
}
}
}
else if (input == KEY_ENTER)
menu = false;
}
int frequency = default_frequency;
// Генерация пищи и змейки
Point random_point = {
rand() % field.width,
rand() % field.height
};
for (short i = 0; i < 5; i++) {
while (field.get_value(random_point) != EMPTY)
random_point = {
rand() % field.width,
rand() % field.height
};
field.set_value(random_point, FOOD);
}
while (field.get_value(random_point) != EMPTY)
random_point = {
rand() % field.width,
rand() % field.height
};
field.set_value(random_point, UP);
snake.head = random_point;
snake.tail = random_point;
// отображение начального поля
system("cls");
set_text_color(15);
wprintf(L" ——= ЗМЕЙКА =——\n");
for (short i = 0; i < field.height; i++) {
wprintf(L" ");
for (short j = 0; j < field.width; j++) {
Point current = { j, i };
short value = field.get_value(current);
if (value == EMPTY) {
set_text_color(8);
wprintf(L"· ");
}
else if (value == FOOD) {
set_text_color(12);
wprintf(L"● ");
}
else if (snake.head.x == current.x and snake.head.y == current.y) {
set_text_color(14);
wprintf(L"▲ ");
}
}
wprintf(L"\n");
}
bool playing = true;
clock_t started_time = clock();
clock_t prev_time = clock();
// ИГРА
while (playing) {
// Управление
if (_kbhit()) {
wchar_t input = _getwch();
if (input == FUNC_KEYS)
(void)_getwch();
else if (input == CONTROL_KEYS) {
input = _getwch();
if (input == KEY_UP and (snake.length == 1 or snake.direction != DOWN))
field.set_value(snake.head, UP);
else if (input == KEY_RIGHT and (snake.length == 1 or snake.direction != LEFT))
field.set_value(snake.head, RIGHT);
else if (input == KEY_DOWN and (snake.length == 1 or snake.direction != UP))
field.set_value(snake.head, DOWN);
else if (input == KEY_LEFT and (snake.length == 1 or snake.direction != RIGHT))
field.set_value(snake.head, LEFT);
}
}
if (clock() - prev_time > frequency) {
prev_time = clock();
//system("cls");
// Движение
Point next = snake.head;
short snake_direction = field.get_value(snake.head);
move_point(&next, snake_direction);
short next_value = field.get_value(next);
// пусто
if (next_value == EMPTY) {
move_snake(next, snake_direction);
}
//еда
else if (next_value == FOOD) {
frequency = (frequency * 99) / 100; // Увеличение скорости
++snake.length;
if (snake.length == 2)
print_tail(snake_direction);
else
print_cell(snake.head, L'■', 10);
snake.head = next;
field.set_value(snake.head, snake_direction);
print_head(snake_direction);
if (snake.length == field.height * field.width)
playing = false;
else if (field.height * field.width - snake.length >= 5) {
while (field.get_value(random_point) != EMPTY)
random_point = {
rand() % field.width,
rand() % field.height
};
field.set_value(random_point, FOOD);
print_cell(random_point, L'●', 12);
}
}
// змейка
else {
if (next.x == snake.tail.x and next.y == snake.tail.y) {
move_snake(next, snake_direction);
}
else
playing = false;
}
snake.direction = field.get_value(snake.head);
}
}
// КОНЕЦ ИГРЫ
int time_elapsed = (clock() - started_time) / CLOCKS_PER_SEC;
goto_xy(0, field.height + 1);
set_text_color(14);
wprintf(L"\n Игра окончена!");
set_text_color(7);
wprintf(L"\n Длина змейки: %d ед.\n Скорость змейки: %.1f ед./с\n Времени затрачено: %d:%s%d",
snake.length,
CLOCKS_PER_SEC/(double)frequency,
time_elapsed / 60,
((time_elapsed % 60) < 10) ? L"0" : L"",
time_elapsed % 60
);
set_text_color(15);
wprintf(L"\n\n Сыграть ещё раз? ");
set_text_color(3);
wprintf(L"[y/n]");
// Ожидание [y/n]
while (true) {
wchar_t input = _getwch();
if (input == FUNC_KEYS or input == CONTROL_KEYS)
(void)_getwch();
else if (input == 'y' or input == L'н') {
for (short i = 0; i < field.height; i++)
for (short j = 0; j < field.width; j++) {
field.set_value({ j, i }, EMPTY);
}
snake.length = 1;
snake.direction = UP;
break;
}
else if (input == 'n' or input == L'т') {
working = false;
break;
}
}
}
}
Соседние файлы в предмете Программирование