257 lines
7.3 KiB
C++
257 lines
7.3 KiB
C++
|
#include "map.hpp"
|
|||
|
#include <cstdlib>
|
|||
|
#include <allegro5/allegro_primitives.h>
|
|||
|
#include <allegro5/allegro_native_dialog.h>
|
|||
|
#include "ai.hpp"
|
|||
|
|
|||
|
map *init_map(const int size, const int window_wh, const int margin_map)
|
|||
|
{
|
|||
|
map *m = (map *)malloc(sizeof(map));
|
|||
|
|
|||
|
float map_wh = 0; // размер карты с учётом отступов
|
|||
|
float cell_width = 0; // ширина ячейки
|
|||
|
float cell_margin = 0; // отступ внутри ячейки
|
|||
|
float line_count = 0; // количество линий на одно направление
|
|||
|
float line_width = 0; // ширина линии
|
|||
|
float cell_sym_width = 0; // ширина сивола внутри ячейки
|
|||
|
|
|||
|
m->size = size;
|
|||
|
m->window_wh = window_wh;
|
|||
|
m->margin_map = margin_map;
|
|||
|
m->toWin = size;
|
|||
|
|
|||
|
line_count = size - 1;
|
|||
|
map_wh = window_wh - margin_map * 2;
|
|||
|
line_width = map_wh * 0.0036;
|
|||
|
cell_width = map_wh / size;
|
|||
|
cell_margin = cell_width * 0.0538;
|
|||
|
cell_sym_width = cell_width - (line_width * 2) - (cell_margin * 2);
|
|||
|
|
|||
|
m->sym_width = cell_sym_width;
|
|||
|
|
|||
|
m->cells = (cell ***)malloc(sizeof(cell **) * (size * size));
|
|||
|
|
|||
|
for (int i = 0; i < size; ++i)
|
|||
|
{
|
|||
|
m->cells[i] = (cell **)malloc(sizeof(cell *) * size);
|
|||
|
|
|||
|
for (int j = 0; j < size; ++j)
|
|||
|
{
|
|||
|
m->cells[i][j] = create_cell(j, i, cell_width, cell_margin, line_width, margin_map);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
m->grid = (line ***)malloc(sizeof(line **) * (line_count * line_count));
|
|||
|
|
|||
|
for (int i = 0; i < 2; ++i)
|
|||
|
{
|
|||
|
m->grid[i] = (line **)malloc(sizeof(line *) * line_count);
|
|||
|
|
|||
|
DIRECTION d = (i == 0 ? HORIZONTAL : VERTICAL);
|
|||
|
|
|||
|
for (int j = 0; j < line_count; ++j)
|
|||
|
{
|
|||
|
m->grid[i][j] = create_line(d, j, line_width, map_wh, cell_width, margin_map);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return m;
|
|||
|
}
|
|||
|
|
|||
|
cell *create_cell(const float row, const float col, const float cell_width, const float cell_margin, const float line_width, const float margin_map)
|
|||
|
{
|
|||
|
cell *c = (cell *)malloc(sizeof(cell));
|
|||
|
c->select = false;
|
|||
|
c->is_draw = false;
|
|||
|
c->pos_x = row * cell_width + margin_map;
|
|||
|
c->pos_y = col * cell_width + margin_map;
|
|||
|
c->width = cell_width;
|
|||
|
c->sym_pos_x = c->pos_x + line_width + cell_margin;
|
|||
|
c->sym_pos_y = c->pos_y + line_width + cell_margin;
|
|||
|
c->p = EMPTY;
|
|||
|
return c;
|
|||
|
}
|
|||
|
|
|||
|
line *create_line(DIRECTION d, const float row, const float line_width, const float map_wh, const float cell_width, const float margin_map)
|
|||
|
{
|
|||
|
line *l = (line *)malloc(sizeof(line));
|
|||
|
l->d = d;
|
|||
|
l->height = map_wh;
|
|||
|
l->width = line_width;
|
|||
|
if (d == HORIZONTAL)
|
|||
|
{
|
|||
|
l->pos_x = margin_map;
|
|||
|
l->pos_y = (row + 1) * cell_width + margin_map - line_width;
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
l->pos_x = (row + 1) * cell_width + margin_map - line_width;
|
|||
|
l->pos_y = margin_map;
|
|||
|
}
|
|||
|
|
|||
|
return l;
|
|||
|
}
|
|||
|
|
|||
|
void draw_map(const map *m, ALLEGRO_BITMAP *bx, ALLEGRO_BITMAP *bo)
|
|||
|
{
|
|||
|
int size = m->size;
|
|||
|
|
|||
|
int swh = al_get_bitmap_width(bx);
|
|||
|
|
|||
|
for (int i = 0; i < size; ++i)
|
|||
|
{
|
|||
|
for (int j = 0; j < size; ++j)
|
|||
|
{
|
|||
|
cell *c = m->cells[i][j];
|
|||
|
|
|||
|
if (c->is_draw)
|
|||
|
{
|
|||
|
if (c->p == HUMAN)
|
|||
|
al_draw_scaled_bitmap(bx, 0, 0, swh, swh, c->sym_pos_x, c->sym_pos_y, m->sym_width, m->sym_width, 0);
|
|||
|
else
|
|||
|
al_draw_scaled_bitmap(bo, 0, 0, swh, swh, c->sym_pos_x, c->sym_pos_y, m->sym_width, m->sym_width, 0);
|
|||
|
}
|
|||
|
|
|||
|
if (c->select)
|
|||
|
{
|
|||
|
if (c->is_draw)
|
|||
|
al_draw_tinted_scaled_bitmap(bx, al_map_rgba_f(255, 0, 0, 0.3), 0, 0, swh, swh, c->sym_pos_x, c->sym_pos_y, m->sym_width, m->sym_width, 0);
|
|||
|
else
|
|||
|
al_draw_tinted_scaled_bitmap(bx, al_map_rgba_f(0, 255, 0, 0.3), 0, 0, swh, swh, c->sym_pos_x, c->sym_pos_y, m->sym_width, m->sym_width, 0);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
for (int i = 0; i < 2; ++i)
|
|||
|
{
|
|||
|
for (int j = 0; j < size - 1; ++j)
|
|||
|
{
|
|||
|
line *l = m->grid[i][j];
|
|||
|
|
|||
|
if (l->d == HORIZONTAL)
|
|||
|
al_draw_filled_rectangle(l->pos_x, l->pos_y, l->pos_x + l->height, l->pos_y + l->width, al_map_rgb(0, 0, 0));
|
|||
|
else
|
|||
|
al_draw_filled_rectangle(l->pos_x, l->pos_y, l->pos_x + l->width, l->pos_y + l->height, al_map_rgb(0, 0, 0));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void select_cell(map *m, const int mouse_x, const int mouse_y)
|
|||
|
{
|
|||
|
int size = m->size;
|
|||
|
|
|||
|
for (int i = 0; i < size; ++i)
|
|||
|
{
|
|||
|
for (int j = 0; j < size; ++j)
|
|||
|
{
|
|||
|
cell *c = m->cells[i][j];
|
|||
|
|
|||
|
if ((mouse_x >= c->pos_x && mouse_y >= c->pos_y) &&
|
|||
|
(mouse_x <= (c->pos_x + c->width) && mouse_y <= (c->pos_y + c->width)) && c->p != HUMAN)
|
|||
|
c->select = true;
|
|||
|
else
|
|||
|
c->select = false;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool enter_cell(map *m, const int mouse_x, const int mouse_y, PLAYER p)
|
|||
|
{
|
|||
|
int size = m->size;
|
|||
|
|
|||
|
for (int i = 0; i < size; ++i)
|
|||
|
{
|
|||
|
for (int j = 0; j < size; ++j)
|
|||
|
{
|
|||
|
cell *c = m->cells[i][j];
|
|||
|
|
|||
|
if (!c->is_draw && (mouse_x >= c->pos_x && mouse_y >= c->pos_y) &&
|
|||
|
(mouse_x <= (c->pos_x + c->width) && mouse_y <= (c->pos_y + c->width)))
|
|||
|
{
|
|||
|
c->is_draw = true;
|
|||
|
c->p = p;
|
|||
|
return true;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
void clear_map(map *m)
|
|||
|
{
|
|||
|
int size = m->size;
|
|||
|
|
|||
|
for (int i = 0; i < size; ++i)
|
|||
|
{
|
|||
|
for (int j = 0; j < size; ++j)
|
|||
|
{
|
|||
|
cell *c = m->cells[i][j];
|
|||
|
|
|||
|
c->is_draw = false;
|
|||
|
c->select = false;
|
|||
|
c->p = EMPTY;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
bool game_check(map *m, ALLEGRO_DISPLAY *d)
|
|||
|
{
|
|||
|
int answer = -1;
|
|||
|
|
|||
|
if (checkWin(m, HUMAN))
|
|||
|
answer = al_show_native_message_box(d, "Игра окончена!", "Вы победили!",
|
|||
|
"Начать игру сначала?", NULL, ALLEGRO_MESSAGEBOX_YES_NO);
|
|||
|
|
|||
|
if (checkWin(m, AI))
|
|||
|
answer = al_show_native_message_box(d, "Игра окончена!", "Вы проиграли!",
|
|||
|
"Начать игру сначала?", NULL, ALLEGRO_MESSAGEBOX_YES_NO);
|
|||
|
|
|||
|
if (isDraw(m))
|
|||
|
answer = al_show_native_message_box(d, "Игра окончена!", "Ничья!",
|
|||
|
"Начать игру сначала?", NULL, ALLEGRO_MESSAGEBOX_YES_NO);
|
|||
|
|
|||
|
if (answer == 1)
|
|||
|
clear_map(m);
|
|||
|
else if (answer == 0 || answer == 2)
|
|||
|
return true;
|
|||
|
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
void free_map(map *m)
|
|||
|
{
|
|||
|
for (int i = 0; i < m->size; ++i)
|
|||
|
{
|
|||
|
for (int j = 0; j < m->size; ++j)
|
|||
|
{
|
|||
|
free(m->cells[i][j]);
|
|||
|
}
|
|||
|
free(m->cells[i]);
|
|||
|
}
|
|||
|
free(m->cells);
|
|||
|
|
|||
|
for (int i = 0; i < 2; ++i)
|
|||
|
{
|
|||
|
for (int j = 0; j < m->size - 1; ++j)
|
|||
|
{
|
|||
|
free(m->grid[i][j]);
|
|||
|
}
|
|||
|
free(m->grid[i]);
|
|||
|
}
|
|||
|
free(m->grid);
|
|||
|
|
|||
|
free(m);
|
|||
|
}
|
|||
|
|
|||
|
bool exit_game(ALLEGRO_DISPLAY *d)
|
|||
|
{
|
|||
|
int answer = al_show_native_message_box(d, NULL, "Выход из игры",
|
|||
|
"Вы хотите закончить игру?", NULL, ALLEGRO_MESSAGEBOX_YES_NO);
|
|||
|
|
|||
|
if (answer == 1)
|
|||
|
return true;
|
|||
|
else
|
|||
|
return false;
|
|||
|
}
|