Skip to content

Commit

Permalink
Upload project files
Browse files Browse the repository at this point in the history
  • Loading branch information
kubatk committed Jun 20, 2022
1 parent b970118 commit 47c0d2e
Show file tree
Hide file tree
Showing 23 changed files with 1,195 additions and 0 deletions.
94 changes: 94 additions & 0 deletions Board.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
#include "classes/Board.h"
#include <SFML/Graphics.hpp>

Board::Board(const int n) :size(n) {
field = new Field * [n];
for (int i = 0; i < n; ++i)
field[i] = new Field[n];
int x, y;
for (x = 0; x < n; x++) {
for (y = 0; y < n; y++) {
field[x][y].setpos(x, y);
}
}
sign_x.loadFromFile("images/x.png");
sign_o.loadFromFile("images/o.png");
win_x.loadFromFile("images/win_x.png");
win_o.loadFromFile("images/win_o.png");
}

Board::~Board() {
delete[] field;
}

Field* Board::get_field(const int x, const int y) {
return &(field[x][y]);
}

void Board::unmark_all() {
int x, y;
for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
field[x][y].unmark();
}
}
}

bool Board::is_full() {
int x, y;
for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
if (field[x][y].get_owner() == nullptr) return false;
}
}
return true;
}

void Board::draw_grid(sf::RenderWindow& window) {
int x, y;
float posX, posY;

float lr_margin = 50;

float btn_size = (float)((window.getSize().x - (2 * lr_margin)) / size) - 2 * 1;

float top_margin = window.getSize().y - lr_margin - (btn_size + 2) * size;

posX = lr_margin;
posY = top_margin;

for (x = 0; x < size; x++) {
for (y = 0; y < size; y++) {
field[x][y].button.setSize({ btn_size, btn_size });
field[x][y].button.setPosition(posX, posY);

if (field[x][y].get_owner() != nullptr) {
if (field[x][y].get_owner()->get_symbol() == 'o') {
if (field[x][y].is_marked()) field[x][y].button.setTexture(&win_o);
else field[x][y].button.setTexture(&sign_o);
}
else {
if (field[x][y].is_marked()) field[x][y].button.setTexture(&win_x);
else field[x][y].button.setTexture(&sign_x);
}
}

field[x][y].draw(window);
posY += btn_size + 2;
}
posX += btn_size + 2;
posY = top_margin;
}
}

Field* Board::get_clicked_field(sf::RenderWindow& window) {
int x, y;
for (y = 0; y < size; y++) {
for (x = 0; x < size; x++) {
if (field[x][y].isMouseOver(window)) {
return &(field[x][y]);
}
}
}
return nullptr;
}
63 changes: 63 additions & 0 deletions Button.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include "classes/Button.h"
#include <SFML/Graphics.hpp>

Button::Button() {
button.setFillColor(sf::Color::White);
}

Button::Button(sf::Vector2f pos, sf::Vector2f size) {
button.setPosition(pos.x, pos.y);
button.setSize({ size.x, size.y });
}

bool Button::isMouseOver(sf::RenderWindow& window) {
int mouseX = sf::Mouse::getPosition(window).x;
int mouseY = sf::Mouse::getPosition(window).y;

float btnPosX = button.getPosition().x;
float btnPosY = button.getPosition().y;

float btnWidth = btnPosX + button.getLocalBounds().width;
float btnHeight = btnPosY + button.getLocalBounds().height;

return (mouseX > btnPosX && mouseX < btnWidth&& mouseY < btnHeight&& mouseY > btnPosY);
}

void Button::draw_button(sf::RenderWindow& window) {
window.draw(button);
text.draw_text(window);
}

void Button::set_position(sf::Vector2f pos) {
button.setPosition(pos.x, pos.y);
}

void Button::set_size(sf::Vector2f btn_size) {
button.setSize({ btn_size.x, btn_size.y });
}

void Button::set_texture(const char* filename) {
texture.loadFromFile(filename);
button.setTexture(&texture);
}

void Button::set_border(int width, sf::Color color) {
button.setOutlineThickness(width);
button.setOutlineColor(color);
}

void Button::set_display_text(std::string new_text, int size) {

text.set_display_text(new_text);
text.set_size(size);

float posX = button.getPosition().x + ((button.getLocalBounds().width - 2 * button.getOutlineThickness()) - text.getLocalBounds().width) / 2;
float posY = -3 + button.getPosition().y + ((button.getLocalBounds().height - 2 * button.getOutlineThickness()) - text.getLocalBounds().height) / 2;

text.set_position(posX, posY);

}

void Button::set_color(int r, int g, int b) {
button.setFillColor(sf::Color(r, g, b, 255));
}
66 changes: 66 additions & 0 deletions Field.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include "classes/Field.h"
#include <SFML/Graphics.hpp>

Field::Field() {
mark_as_winner = false;
x_pos = y_pos = -1;
owner = nullptr;

button.setFillColor(sf::Color::White);
button.setOutlineThickness(1.f);
button.setOutlineColor(sf::Color::Black);
}

Field::~Field() {
delete owner;
}

int Field::get_x() const {
return x_pos;
}

int Field::get_y() const {
return y_pos;
}

Player* Field::get_owner() {
return owner;
}

void Field::mark() {
mark_as_winner = true;
}

void Field::unmark() {
mark_as_winner = false;
}

bool Field::is_marked() {
return mark_as_winner;
}

void Field::setpos(int x, int y) {
x_pos = x;
y_pos = y;
}

void Field::set_owner(Player* new_owner) {
owner = new_owner;
}

void Field::draw(sf::RenderWindow& window) {
window.draw(button);
}

bool Field::isMouseOver(sf::RenderWindow& window) {
int mouseX = sf::Mouse::getPosition(window).x;
int mouseY = sf::Mouse::getPosition(window).y;

float btnPosX = button.getPosition().x;
float btnPosY = button.getPosition().y;

float btnWidth = btnPosX + button.getLocalBounds().width;
float btnHeight = btnPosY + button.getLocalBounds().height;

return (mouseX > btnPosX && mouseX < btnWidth&& mouseY < btnHeight&& mouseY > btnPosY);
}
46 changes: 46 additions & 0 deletions Game.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#include "classes/Game.h"
#include <SFML/Graphics.hpp>

Game::Game(const int field_size, const int req_length, bool is_ai) : size(field_size), length(req_length) {
finished = false;
board = new Board(field_size);
winner = nullptr;
players[0] = new Player('o', false);
players[1] = new Player('x', is_ai);
}

Game::~Game() {
delete winner;
delete board;
}

Board* Game::get_board() {
return board;
}

Player* Game::get_winner() {
return winner;
}

void Game::set_field_owner(int x, int y, char sign) {
Player* new_owner;

if (players[0]->get_symbol() == sign) new_owner = players[0];
else if (players[1]->get_symbol() == sign) new_owner = players[1];
else return;

board->get_field(x, y)->set_owner(new_owner);
}

void Game::remove_field_owner(int x, int y) {
board->get_field(x, y)->set_owner(nullptr);
}

Player* Game::get_player_by_sign(char sign) {
if (players[0]->get_symbol() == sign) return players[0];
else if (players[1]->get_symbol() == sign) return players[1];
else return nullptr;
}
bool Game::is_finished() {
return finished;
}
110 changes: 110 additions & 0 deletions Game_AI.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
#include "classes/Game.h"
#include <SFML/Graphics.hpp>
#include <iostream>

Field* Game::random_empty_field() {
if (finished) return nullptr;
int x, y;
Field* field;
srand(time(NULL));
while (true) {
x = rand() % size;
y = rand() % size;
field = board->get_field(x, y);
if (field->get_owner() == nullptr) return field;
}
}

Field* Game::get_ai_move(int difficulty) {

int x, y, rate = 0, i, j, win, win_points, block_points, win_diff, block_diff;
int minimal = 100000;

win = length;

win_points = difficulty == 2 ? 0 : 1005;
win_diff = difficulty == 2 ? 0 : 15;
block_points = 1000;
block_diff = 5;



//allocate rating table
int** rating = new int* [size];
for (i = 0; i < size; ++i) {
rating[i] = new int[size];
}
//fill array with zeros
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
rating[i][j] = 0;
}
}

//give points value to the field
for (win = length; win > 1; win--) {

for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {


if (board->get_field(i, j)->get_owner() == nullptr) {

//Try to put AI's symbol
set_field_owner(i, j, 'x');
if (look_for_win(win)) {
rating[i][j] += win_points;
}
finished = false;
board->unmark_all();
remove_field_owner(i, j);

//Try to put user's symbol
set_field_owner(i, j, 'o');
if (look_for_win(win)) {
rating[i][j] += block_points;
}
finished = false;
board->unmark_all();
remove_field_owner(i, j);
}

}
}

win_points -= win_diff;
block_points -= block_diff;

}

//Look for most profitable field
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
if (rating[i][j] > rate) {
rate = rating[i][j];
x = i;
y = j;
}
}
}

//Find lowest value
for (i = 0; i < size; i++) {
for (j = 0; j < size; j++) {
if (rating[i][j] < minimal && board->get_field(i, j)->get_owner() == nullptr) {
minimal = rating[i][j];
}
}
}

//cleanup
for (i = 0; i < size; ++i) {
delete[] rating[i];
}
delete[] rating;
rating = NULL;

//return result
if (rate == minimal) return random_empty_field();
else return board->get_field(x, y);
}
Loading

0 comments on commit 47c0d2e

Please sign in to comment.