tictactoe/game/map.cpp

257 lines
7.3 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}