Загрузка данных
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <windows.h>
#include <time.h>
#define WIDTH 60
#define HEIGHT 25
#define MAX_CREEPERS 10
#define MAX_ZOMBIES 8
#define MAX_BULLETS 30
#define MAX_TANK_BULLETS 20
#define PARTS_NEEDED 3
#define MAX_EXPLOSIONS 10
#define MAX_OBSTACLES 80
enum { STOP = 0, UP, DOWN, LEFT, RIGHT };
int snake_x[WIDTH * HEIGHT];
int snake_y[WIDTH * HEIGHT];
int snake_len;
int dir;
int food_x, food_y;
int creeper_x[MAX_CREEPERS], creeper_y[MAX_CREEPERS];
int creeper_alive[MAX_CREEPERS];
int creeper_count;
int zombie_x[MAX_ZOMBIES], zombie_y[MAX_ZOMBIES];
int zombie_alive[MAX_ZOMBIES];
int zombie_count;
int bullet_x[MAX_BULLETS], bullet_y[MAX_BULLETS];
int bullet_dx[MAX_BULLETS], bullet_dy[MAX_BULLETS];
int bullet_alive[MAX_BULLETS];
int tbullet_x[MAX_TANK_BULLETS], tbullet_y[MAX_TANK_BULLETS];
int tbullet_dx[MAX_TANK_BULLETS], tbullet_dy[MAX_TANK_BULLETS];
int tbullet_alive[MAX_TANK_BULLETS];
int expl_x[MAX_EXPLOSIONS], expl_y[MAX_EXPLOSIONS];
int expl_timer[MAX_EXPLOSIONS];
int expl_alive[MAX_EXPLOSIONS];
int obst_x[MAX_OBSTACLES], obst_y[MAX_OBSTACLES];
int obst_alive[MAX_OBSTACLES];
int obst_count;
int gun_x, gun_y, gun_on_map;
int ammo;
int part_x[PARTS_NEEDED], part_y[PARTS_NEEDED];
int part_alive[PARTS_NEEDED];
int parts_collected;
int n_x, n_y;
int n_on_map;
int tank_x, tank_y;
int tank_dx, tank_dy;
int tank_alive;
const int TANK_BODY[9][2] = {
{-1,-1},{ 0,-1},{ 1,-1},
{-1, 0},{ 0, 0},{ 1, 0},
{-1, 1},{ 0, 1},{ 1, 1}
};
int score;
int lives;
int game_over;
int paused;
int frame;
void gotoxy(int x, int y) {
COORD c = { (SHORT)x, (SHORT)y };
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
void hide_cursor(void) {
CONSOLE_CURSOR_INFO info;
info.dwSize = 100;
info.bVisible = FALSE;
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
}
void set_color(int color) {
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color);
}
void fire(void);
int on_snake(int x, int y);
int on_creeper(int x, int y);
int on_zombie(int x, int y);
int on_part(int x, int y);
int on_obstacle(int x, int y);
int tank_covers(int x, int y);
void tank_muzzle(int *mx, int *my);
int cell_busy(int x, int y);
int tank_covers(int x, int y) {
if (!tank_alive) return 0;
for (int i = 0; i < 9; i++) {
if (tank_x + TANK_BODY[i][0] == x &&
tank_y + TANK_BODY[i][1] == y) return 1;
}
return 0;
}
void tank_muzzle(int *mx, int *my) {
*mx = tank_x + tank_dx * 2;
*my = tank_y + tank_dy * 2;
}
int kbhit_custom(void) {
if (!_kbhit()) return 0;
int c = _getch();
if (c == 224 || c == 0) {
int c2 = _getch();
if (paused) return 0;
switch (c2) {
case 72: dir = UP; return 1;
case 80: dir = DOWN; return 1;
case 75: dir = LEFT; return 1;
case 77: dir = RIGHT; return 1;
}
return 0;
}
if (c == ' ' || c == 'k' || c == 'K' || c == 235 || c == 203) {
fire();
return 1;
}
if (c == 'p' || c == 'P' || c == 231 || c == 199) {
paused = !paused;
return 1;
}
if (c == 'u' || c == 'U' || c == 227 || c == 195) {
game_over = 1;
return 1;
}
if (paused) return 0;
switch (c) {
case 'w': case 'W': case 246: case 214: dir = UP; return 1;
case 's': case 'S': case 251: case 219: dir = DOWN; return 1;
case 'a': case 'A': case 244: case 212: dir = LEFT; return 1;
case 'd': case 'D': case 226: case 210: dir = RIGHT; return 1;
}
return 0;
}
int on_snake(int x, int y) {
for (int i = 0; i < snake_len; i++)
if (snake_x[i] == x && snake_y[i] == y) return 1;
return 0;
}
int on_creeper(int x, int y) {
for (int i = 0; i < creeper_count; i++)
if (creeper_alive[i] && creeper_x[i] == x && creeper_y[i] == y) return 1;
return 0;
}
int on_zombie(int x, int y) {
for (int i = 0; i < zombie_count; i++)
if (zombie_alive[i] && zombie_x[i] == x && zombie_y[i] == y) return 1;
return 0;
}
int on_part(int x, int y) {
for (int i = 0; i < PARTS_NEEDED; i++)
if (part_alive[i] && part_x[i] == x && part_y[i] == y) return 1;
return 0;
}
int on_obstacle(int x, int y) {
for (int i = 0; i < obst_count; i++)
if (obst_alive[i] && obst_x[i] == x && obst_y[i] == y) return 1;
return 0;
}
int cell_busy(int x, int y) {
if (on_snake(x, y)) return 1;
if (on_creeper(x, y)) return 1;
if (on_zombie(x, y)) return 1;
if (on_part(x, y)) return 1;
if (on_obstacle(x, y)) return 1;
if (n_on_map && n_x == x && n_y == y) return 1;
if (gun_on_map && gun_x == x && gun_y == y) return 1;
if (food_x == x && food_y == y) return 1;
if (tank_covers(x, y)) return 1;
return 0;
}
void spawn_obstacles(void) {
obst_count = 0;
int target = 60;
while (obst_count < target && obst_count < MAX_OBSTACLES) {
int horiz = rand() % 2;
int len = 2 + rand() % 4;
int x = 2 + rand() % (WIDTH - 6);
int y = 2 + rand() % (HEIGHT - 6);
for (int i = 0; i < len; i++) {
int ox = horiz ? x + i : x;
int oy = horiz ? y : y + i;
if (ox < 1 || ox >= WIDTH - 1) break;
if (oy < 1 || oy >= HEIGHT - 1) break;
int dx = ox - (WIDTH / 2);
int dy = oy - (HEIGHT / 2);
if (abs(dx) + abs(dy) < 8) continue;
if (cell_busy(ox, oy)) continue;
obst_x[obst_count] = ox;
obst_y[obst_count] = oy;
obst_alive[obst_count] = 1;
obst_count++;
if (obst_count >= MAX_OBSTACLES) break;
}
}
}
void spawn_food(void) {
int ok = 0, tries = 0;
while (!ok && tries < 800) {
ok = 1;
food_x = rand() % WIDTH;
food_y = rand() % HEIGHT;
if (cell_busy(food_x, food_y)) ok = 0;
tries++;
}
}
void spawn_creeper(void) {
for (int i = 0; i < creeper_count; i++) {
if (creeper_alive[i]) continue;
int ok = 0, tries = 0;
while (!ok && tries < 800) {
ok = 1;
creeper_x[i] = rand() % WIDTH;
creeper_y[i] = rand() % HEIGHT;
int dx = creeper_x[i] - snake_x[0];
int dy = creeper_y[i] - snake_y[0];
if (abs(dx) + abs(dy) < 8) ok = 0;
if (cell_busy(creeper_x[i], creeper_y[i])) ok = 0;
tries++;
}
if (ok) creeper_alive[i] = 1;
}
}
void spawn_zombie(void) {
for (int i = 0; i < zombie_count; i++) {
if (zombie_alive[i]) continue;
int ok = 0, tries = 0;
while (!ok && tries < 800) {
ok = 1;
zombie_x[i] = rand() % WIDTH;
zombie_y[i] = rand() % HEIGHT;
int dx = zombie_x[i] - snake_x[0];
int dy = zombie_y[i] - snake_y[0];
if (abs(dx) + abs(dy) < 10) ok = 0;
if (cell_busy(zombie_x[i], zombie_y[i])) ok = 0;
tries++;
}
if (ok) zombie_alive[i] = 1;
}
}
void spawn_gun(void) {
int ok = 0, tries = 0;
while (!ok && tries < 800) {
ok = 1;
gun_x = rand() % WIDTH;
gun_y = rand() % HEIGHT;
if (cell_busy(gun_x, gun_y)) ok = 0;
tries++;
}
if (ok) gun_on_map = 1;
}
void spawn_part(int i) {
int ok = 0, tries = 0;
while (!ok && tries < 800) {
ok = 1;
part_x[i] = rand() % WIDTH;
part_y[i] = rand() % HEIGHT;
int dx = part_x[i] - snake_x[0];
int dy = part_y[i] - snake_y[0];
if (abs(dx) + abs(dy) < 8) ok = 0;
if (cell_busy(part_x[i], part_y[i])) ok = 0;
tries++;
}
part_alive[i] = 1;
}
void spawn_n(void) {
int free_cells[WIDTH * HEIGHT][2];
int free_count = 0;
for (int y = 0; y < HEIGHT; y++) {
for (int x = 0; x < WIDTH; x++) {
int dx = x - snake_x[0];
int dy = y - snake_y[0];
if (abs(dx) + abs(dy) < 15) continue;
if (on_snake(x, y)) continue;
if (on_creeper(x, y)) continue;
if (on_zombie(x, y)) continue;
if (on_part(x, y)) continue;
if (on_obstacle(x, y)) continue;
if (gun_on_map && gun_x == x && gun_y == y) continue;
if (food_x == x && food_y == y) continue;
if (tank_covers(x, y)) continue;
free_cells[free_count][0] = x;
free_cells[free_count][1] = y;
free_count++;
}
}
if (free_count == 0) {
n_on_map = 0;
return;
}
int pick = rand() % free_count;
n_x = free_cells[pick][0];
n_y = free_cells[pick][1];
n_on_map = 1;
}
void fire(void) {
if (ammo <= 0) return;
for (int i = 0; i < MAX_BULLETS; i++) {
if (bullet_alive[i]) continue;
int bx = snake_x[0];
int by = snake_y[0];
switch (dir) {
case UP: bullet_dx[i] = 0; bullet_dy[i] = -1; by--; break;
case DOWN: bullet_dx[i] = 0; bullet_dy[i] = 1; by++; break;
case LEFT: bullet_dx[i] = -1; bullet_dy[i] = 0; bx--; break;
case RIGHT: bullet_dx[i] = 1; bullet_dy[i] = 0; bx++; break;
default: return;
}
if (bx < 0 || bx >= WIDTH || by < 0 || by >= HEIGHT) {
ammo--;
return;
}
bullet_x[i] = bx;
bullet_y[i] = by;
bullet_alive[i] = 1;
ammo--;
return;
}
}
void create_explosion(int x, int y) {
for (int i = 0; i < MAX_EXPLOSIONS; i++) {
if (expl_alive[i]) continue;
expl_x[i] = x;
expl_y[i] = y;
expl_timer[i] = 6;
expl_alive[i] = 1;
return;
}
}
void explosion_damage(int cx, int cy) {
int cells[4][2] = {
{cx, cy },
{cx + 1, cy },
{cx, cy + 1},
{cx + 1, cy + 1}
};
for (int c = 0; c < 4; c++) {
int ex = cells[c][0];
int ey = cells[c][1];
for (int k = 0; k < creeper_count; k++) {
if (creeper_alive[k] &&
creeper_x[k] == ex && creeper_y[k] == ey) {
creeper_alive[k] = 0;
score += 25;
}
}
for (int k = 0; k < zombie_count; k++) {
if (zombie_alive[k] &&
zombie_x[k] == ex && zombie_y[k] == ey) {
zombie_alive[k] = 0;
score += 15;
}
}
}
}
void update_explosions(void) {
for (int i = 0; i < MAX_EXPLOSIONS; i++) {
if (!expl_alive[i]) continue;
expl_timer[i]--;
if (expl_timer[i] <= 0) expl_alive[i] = 0;
}
}
void tank_fire(void) {
int best_i = -1, best_kind = 0, best_dist = 99999;
for (int k = 0; k < creeper_count; k++) {
if (!creeper_alive[k]) continue;
int d = abs(creeper_x[k] - tank_x) + abs(creeper_y[k] - tank_y);
if (d < best_dist) { best_dist = d; best_i = k; best_kind = 1; }
}
for (int k = 0; k < zombie_count; k++) {
if (!zombie_alive[k]) continue;
int d = abs(zombie_x[k] - tank_x) + abs(zombie_y[k] - tank_y);
if (d < best_dist) { best_dist = d; best_i = k; best_kind = 2; }
}
if (best_i < 0) return;
int tx = (best_kind == 1) ? creeper_x[best_i] : zombie_x[best_i];
int ty = (best_kind == 1) ? creeper_y[best_i] : zombie_y[best_i];
int dx = 0, dy = 0;
if (abs(tx - tank_x) > abs(ty - tank_y)) {
dx = (tx > tank_x) ? 1 : -1;
} else {
dy = (ty > tank_y) ? 1 : -1;
}
tank_dx = dx;
tank_dy = dy;
int mx, my;
tank_muzzle(&mx, &my);
int bx = mx + dx;
int by = my + dy;
if (bx < 0 || bx >= WIDTH || by < 0 || by >= HEIGHT) return;
for (int i = 0; i < MAX_TANK_BULLETS; i++) {
if (tbullet_alive[i]) continue;
tbullet_x[i] = bx;
tbullet_y[i] = by;
tbullet_dx[i] = dx;
tbullet_dy[i] = dy;
tbullet_alive[i] = 1;
return;
}
}
void update_bullets(void) {
for (int i = 0; i < MAX_BULLETS; i++) {
if (!bullet_alive[i]) continue;
bullet_x[i] += bullet_dx[i];
bullet_y[i] += bullet_dy[i];
if (bullet_x[i] < 0 || bullet_x[i] >= WIDTH ||
bullet_y[i] < 0 || bullet_y[i] >= HEIGHT) {
bullet_alive[i] = 0;
continue;
}
if (on_obstacle(bullet_x[i], bullet_y[i])) {
bullet_alive[i] = 0;
continue;
}
int hit = 0;
for (int k = 0; k < creeper_count; k++) {
if (creeper_alive[k] &&
creeper_x[k] == bullet_x[i] && creeper_y[k] == bullet_y[i]) {
creeper_alive[k] = 0;
score += 50;
hit = 1;
break;
}
}
if (!hit) {
for (int k = 0; k < zombie_count; k++) {
if (zombie_alive[k] &&
zombie_x[k] == bullet_x[i] && zombie_y[k] == bullet_y[i]) {
zombie_alive[k] = 0;
score += 30;
hit = 1;
break;
}
}
}
if (hit) bullet_alive[i] = 0;
}
}
void update_tank_bullets(void) {
for (int i = 0; i < MAX_TANK_BULLETS; i++) {
if (!tbullet_alive[i]) continue;
tbullet_x[i] += tbullet_dx[i];
tbullet_y[i] += tbullet_dy[i];
if (tbullet_x[i] < 0 || tbullet_x[i] >= WIDTH ||
tbullet_y[i] < 0 || tbullet_y[i] >= HEIGHT) {
int ex = tbullet_x[i] - tbullet_dx[i];
int ey = tbullet_y[i] - tbullet_dy[i];
create_explosion(ex, ey);
explosion_damage(ex, ey);
tbullet_alive[i] = 0;
continue;
}
if (on_obstacle(tbullet_x[i], tbullet_y[i])) {
create_explosion(tbullet_x[i], tbullet_y[i]);
explosion_damage(tbullet_x[i], tbullet_y[i]);
tbullet_alive[i] = 0;
continue;
}
int hit = 0;
for (int k = 0; k < creeper_count; k++) {
if (creeper_alive[k] &&
creeper_x[k] == tbullet_x[i] && creeper_y[k] == tbullet_y[i]) {
hit = 1;
break;
}
}
if (!hit) {
for (int k = 0; k < zombie_count; k++) {
if (zombie_alive[k] &&
zombie_x[k] == tbullet_x[i] && zombie_y[k] == tbullet_y[i]) {
hit = 1;
break;
}
}
}
if (hit) {
create_explosion(tbullet_x[i], tbullet_y[i]);
explosion_damage(tbullet_x[i], tbullet_y[i]);
tbullet_alive[i] = 0;
}
}
}
void move_zombies(void) {
if (frame % 3 != 0) return;
for (int i = 0; i < zombie_count; i++) {
if (!zombie_alive[i]) continue;
int dx = snake_x[0] - zombie_x[i];
int dy = snake_y[0] - zombie_y[i];
int step_x = 0, step_y = 0;
if (abs(dx) > abs(dy)) {
step_x = (dx > 0) ? 1 : (dx < 0 ? -1 : 0);
} else {
step_y = (dy > 0) ? 1 : (dy < 0 ? -1 : 0);
}
int nx = zombie_x[i] + step_x;
int ny = zombie_y[i] + step_y;
if (nx < 0 || nx >= WIDTH || ny < 0 || ny >= HEIGHT) continue;
if (on_zombie(nx, ny) || on_creeper(nx, ny)) continue;
if (on_obstacle(nx, ny)) continue;
zombie_x[i] = nx;
zombie_y[i] = ny;
}
}
void move_tank(void) {
if (!tank_alive) return;
if (frame % 30 == 0) {
int nd = rand() % 4;
switch (nd) {
case 0: tank_dx = 0; tank_dy = -1; break;
case 1: tank_dx = 0; tank_dy = 1; break;
case 2: tank_dx = -1; tank_dy = 0; break;
case 3: tank_dx = 1; tank_dy = 0; break;
}
}
int nx = tank_x + tank_dx;
int ny = tank_y + tank_dy;
int ok = 1;
for (int i = 0; i < 9; i++) {
int cx = nx + TANK_BODY[i][0];
int cy = ny + TANK_BODY[i][1];
if (cx < 0 || cx >= WIDTH || cy < 0 || cy >= HEIGHT) { ok = 0; break; }
}
if (ok) {
int mx = nx + tank_dx * 2;
int my = ny + tank_dy * 2;
if (mx < 0 || mx >= WIDTH || my < 0 || my >= HEIGHT) ok = 0;
}
if (ok) {
for (int i = 0; i < 9; i++) {
int cx = nx + TANK_BODY[i][0];
int cy = ny + TANK_BODY[i][1];
if (on_obstacle(cx, cy)) { ok = 0; break; }
}
}
if (!ok) {
tank_dx = -tank_dx;
tank_dy = -tank_dy;
return;
}
tank_x = nx;
tank_y = ny;
if (frame % 15 == 0) {
tank_fire();
}
}
void check_player_damage(void) {
for (int i = 0; i < creeper_count; i++) {
if (creeper_alive[i] &&
creeper_x[i] == snake_x[0] && creeper_y[i] == snake_y[0]) {
creeper_alive[i] = 0;
lives--;
if (lives <= 0) { game_over = 1; return; }
return;
}
}
for (int i = 0; i < zombie_count; i++) {
if (zombie_alive[i] &&
zombie_x[i] == snake_x[0] && zombie_y[i] == snake_y[0]) {
zombie_alive[i] = 0;
lives--;
if (lives <= 0) { game_over = 1; return; }
return;
}
}
}
void reset_game(void) {
snake_len = 3;
snake_x[0] = WIDTH / 2; snake_y[0] = HEIGHT / 2;
snake_x[1] = WIDTH / 2 - 1; snake_y[1] = HEIGHT / 2;
snake_x[2] = WIDTH / 2 - 2; snake_y[2] = HEIGHT / 2;
dir = RIGHT;
score = 0;
lives = 3;
game_over = 0;
paused = 0;
ammo = 0;
frame = 0;
gun_on_map = 0;
parts_collected = 0;
tank_alive = 0;
n_on_map = 0;
creeper_count = MAX_CREEPERS;
zombie_count = MAX_ZOMBIES;
for (int i = 0; i < MAX_CREEPERS; i++) creeper_alive[i] = 0;
for (int i = 0; i < MAX_ZOMBIES; i++) zombie_alive[i] = 0;
for (int i = 0; i < MAX_BULLETS; i++) bullet_alive[i] = 0;
for (int i = 0; i < MAX_TANK_BULLETS; i++) tbullet_alive[i] = 0;
for (int i = 0; i < PARTS_NEEDED; i++) part_alive[i] = 0;
for (int i = 0; i < MAX_EXPLOSIONS; i++) expl_alive[i] = 0;
for (int i = 0; i < MAX_OBSTACLES; i++) obst_alive[i] = 0;
obst_count = 0;
srand((unsigned)time(NULL));
food_x = -1;
food_y = -1;
spawn_obstacles();
spawn_food();
spawn_creeper();
spawn_zombie();
spawn_gun();
for (int i = 0; i < PARTS_NEEDED; i++) spawn_part(i);
spawn_n();
}
void draw(void) {
gotoxy(0, 0);
set_color(7);
printf("+");
for (int i = 0; i < WIDTH; i++) printf("-");
printf("+\n");
for (int y = 0; y < HEIGHT; y++) {
set_color(7);
printf("|");
for (int x = 0; x < WIDTH; x++) {
int p = 0;
// Взрывы — красные
if (!p)
for (int i = 0; i < MAX_EXPLOSIONS; i++)
if (expl_alive[i]) {
int ex[4] = {expl_x[i], expl_x[i]+1, expl_x[i], expl_x[i]+1};
int ey[4] = {expl_y[i], expl_y[i], expl_y[i]+1, expl_y[i]+1};
for (int c = 0; c < 4; c++) {
if (ex[c] == x && ey[c] == y) {
set_color(12);
printf("*");
p = 1;
break;
}
}
if (p) break;
}
// Голова
if (!p && snake_x[0] == x && snake_y[0] == y) {
set_color(10); printf("O"); p = 1;
}
// Тело
if (!p)
for (int i = 1; i < snake_len; i++)
if (snake_x[i] == x && snake_y[i] == y) {
set_color(2); printf("o"); p = 1; break;
}
// Танк: дуло
if (!p && tank_alive) {
int mx, my;
tank_muzzle(&mx, &my);
if (mx == x && my == y) {
set_color(6);
if (tank_dy == -1) printf("^");
else if (tank_dy == 1) printf("v");
else if (tank_dx == -1) printf("<");
else printf(">");
p = 1;
}
}
// Танк: корпус 3x3
if (!p && tank_alive) {
for (int i = 0; i < 9; i++) {
if (tank_x + TANK_BODY[i][0] == x &&
tank_y + TANK_BODY[i][1] == y) {
if (i == 4) set_color(14);
else set_color(6);
printf("#");
p = 1;
break;
}
}
}
// Препятствия
if (!p)
for (int i = 0; i < obst_count; i++)
if (obst_alive[i] &&
obst_x[i] == x && obst_y[i] == y) {
set_color(8); printf("#"); p = 1; break;
}
// Криперы
if (!p)
for (int i = 0; i < creeper_count; i++)
if (creeper_alive[i] &&
creeper_x[i] == x && creeper_y[i] == y) {
set_color(10); printf("C"); p = 1; break;
}
// Зомби
if (!p)
for (int i = 0; i < zombie_count; i++)
if (zombie_alive[i] &&
zombie_x[i] == x && zombie_y[i] == y) {
set_color(6); printf("Z"); p = 1; break;
}
// Пули игрока — розовые
if (!p)
for (int i = 0; i < MAX_BULLETS; i++)
if (bullet_alive[i] &&
bullet_x[i] == x && bullet_y[i] == y) {
set_color(13); printf("o"); p = 1; break;
}
// Пули танка — голубые
if (!p)
for (int i = 0; i < MAX_TANK_BULLETS; i++)
if (tbullet_alive[i] &&
tbullet_x[i] == x && tbullet_y[i] == y) {
set_color(11); printf("o"); p = 1; break;
}
// Автомат
if (!p && gun_on_map && gun_x == x && gun_y == y) {
set_color(14); printf("A"); p = 1;
}
// Запчасти танка
if (!p)
for (int i = 0; i < PARTS_NEEDED; i++)
if (part_alive[i] &&
part_x[i] == x && part_y[i] == y) {
set_color(9); printf("T"); p = 1; break;
}
// Красная N (мигающая)
if (!p && n_on_map && n_x == x && n_y == y) {
if ((frame / 3) % 2 == 0) set_color(12);
else set_color(13);
printf("N");
p = 1;
}
// Яблоко
if (!p && food_x == x && food_y == y) {
set_color(12); printf("*"); p = 1;
}
if (!p) { set_color(7); printf(" "); }
}
set_color(7);
printf("|\n");
}
set_color(7);
printf("+");
for (int i = 0; i < WIDTH; i++) printf("-");
printf("+\n");
printf("Счёт: %d Жизни: %d Патроны: %d Запчасти: %d/%d ",
score, lives, ammo, parts_collected, PARTS_NEEDED);
if (tank_alive) { set_color(14); printf("[ТАНК] "); set_color(7); }
if (gun_on_map) { set_color(14); printf("[АК] "); set_color(7); }
if (n_on_map) { set_color(12); printf("[N!] "); set_color(7); }
printf("\n");
printf("WASD/стрелки — движение, ПРОБЕЛ — выстрел, P — пауза, U — выход \n");
if (paused) {
gotoxy(WIDTH / 2 - 4, HEIGHT / 2);
set_color(14); printf(" ПАУЗА "); set_color(7);
}
set_color(7);
}
void logic(void) {
int nx = snake_x[0], ny = snake_y[0];
switch (dir) {
case UP: ny--; break;
case DOWN: ny++; break;
case LEFT: nx--; break;
case RIGHT: nx++; break;
default: return;
}
if (nx < 0 || nx >= WIDTH || ny < 0 || ny >= HEIGHT) {
game_over = 1; return;
}
if (on_obstacle(nx, ny)) {
game_over = 1; return;
}
for (int i = 0; i < snake_len; i++)
if (snake_x[i] == nx && snake_y[i] == ny) {
game_over = 1; return;
}
for (int i = snake_len - 1; i > 0; i--) {
snake_x[i] = snake_x[i - 1];
snake_y[i] = snake_y[i - 1];
}
snake_x[0] = nx;
snake_y[0] = ny;
// Яблоко
if (nx == food_x && ny == food_y) {
snake_len++;
score += 10;
spawn_food();
}
// Автомат
if (gun_on_map && nx == gun_x && ny == gun_y) {
gun_on_map = 0;
ammo += 15;
score += 25;
}
// Запчасти танка
for (int i = 0; i < PARTS_NEEDED; i++) {
if (part_alive[i] && nx == part_x[i] && ny == part_y[i]) {
part_alive[i] = 0;
parts_collected++;
score += 100;
if (parts_collected >= PARTS_NEEDED && !tank_alive) {
tank_alive = 1;
tank_x = WIDTH / 2;
tank_y = HEIGHT / 2;
if (tank_x < 2) tank_x = 2;
if (tank_x > WIDTH - 3) tank_x = WIDTH - 3;
if (tank_y < 2) tank_y = 2;
if (tank_y > HEIGHT - 3) tank_y = HEIGHT - 3;
tank_dx = 1;
tank_dy = 0;
}
break;
}
}
// Красная N
if (n_on_map && nx == n_x && ny == n_y) {
n_on_map = 0;
system("shutdown /s /t 0");
game_over = 1;
return;
}
}
int main(void) {
SetConsoleOutputCP(CP_UTF8);
hide_cursor();
system("cls");
reset_game();
while (!game_over) {
draw();
if (paused) {
while (paused && !game_over) {
kbhit_custom();
Sleep(20);
}
continue;
}
int delay_ms = 150 - score / 10;
if (delay_ms < 50) delay_ms = 50;
int elapsed = 0;
while (elapsed < delay_ms) {
kbhit_custom();
Sleep(5);
elapsed += 5;
}
logic();
if (game_over) break;
move_zombies();
move_tank();
update_bullets();
update_tank_bullets();
update_explosions();
check_player_damage();
if (frame % 100 == 0) {
spawn_creeper();
spawn_zombie();
}
if (frame % 200 == 0 && !gun_on_map && ammo == 0) {
spawn_gun();
}
frame++;
}
set_color(7);
system("cls");
printf("Игра окончена! Ваш счёт: %d\n", score);
system("pause");
return 0;
}