158 lines
3.3 KiB
C++
158 lines
3.3 KiB
C++
#include "game.h"
|
|
#include <Log.h>
|
|
|
|
const std::string Game::SYM_NAMES[3] = {"NONE", "X", "O"};
|
|
|
|
std::string Game::UserInfo::getUsernameOrName() const {
|
|
return username.empty() ? name : ("@" + username);
|
|
}
|
|
|
|
bool Game::UserInfo::operator==(const UserInfo& other) const {
|
|
if(id != 0 && other.id != 0) {
|
|
return id == other.id;
|
|
}
|
|
return username == other.username;
|
|
}
|
|
|
|
bool Game::UserInfo::operator!=(const UserInfo& other) const {
|
|
if(id != 0 && other.id != 0) {
|
|
return id != other.id;
|
|
}
|
|
|
|
return other.username != username;
|
|
}
|
|
|
|
Game::Game() {
|
|
for(uint_fast8_t i = 0; i < SIZE * SIZE; ++i) {
|
|
field[i] = SYM::NONE;
|
|
}
|
|
}
|
|
|
|
void Game::setPlayerA(const UserInfo& player) {
|
|
playerA = player;
|
|
}
|
|
void Game::setPlayerB(const UserInfo& player) {
|
|
playerB = player;
|
|
}
|
|
|
|
bool Game::addPlayer(const UserInfo& player) {
|
|
if(!playerA) {
|
|
playerA = player;
|
|
return true;
|
|
}
|
|
|
|
if(!playerB && playerA != player) {
|
|
playerB = player;
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const Game::UserInfo& Game::getPlayerA() const {
|
|
return playerA;
|
|
}
|
|
|
|
const Game::UserInfo& Game::getPlayerB() const {
|
|
return playerB;
|
|
}
|
|
|
|
bool Game::ready() const {
|
|
return playerA && playerB && !done();
|
|
}
|
|
|
|
bool Game::done() const {
|
|
return (checkWinner() != SYM::NONE) || isFull();
|
|
}
|
|
|
|
bool Game::isFull() const {
|
|
for(uint_fast8_t i = 0; i < SIZE * SIZE; ++i) {
|
|
if(field[i] == SYM::NONE)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool Game::turn(uint_fast8_t x, uint_fast8_t y, const UserInfo& player) {
|
|
if(!isInField(x, y)) {
|
|
return false;
|
|
}
|
|
if(!ready()) {
|
|
return false;
|
|
}
|
|
|
|
// Log::info << "turn player: " << player.id << " n: " << player.name << " u: " << player.username;
|
|
// Log::info << "playerA: " << playerA.id << " n: " << playerA.name << " u: " << playerA.username << " e: " << (player == playerA);
|
|
// Log::info << "playerB: " << playerB.id << " n: " << playerB.name << " u: " << playerB.username << " e: " << (player == playerB);
|
|
|
|
|
|
// playerA
|
|
if(player == playerA && nextturna) {
|
|
SYM s = getField(x, y);
|
|
if(s != SYM::NONE) {
|
|
return false;
|
|
}
|
|
setField(x, y, SYM::A);
|
|
}
|
|
|
|
//playerB
|
|
else if(player == playerB && !nextturna) {
|
|
SYM s = getField(x, y);
|
|
if(s != SYM::NONE) {
|
|
return false;
|
|
}
|
|
setField(x, y, SYM::B);
|
|
}
|
|
|
|
// other user -> not allowed
|
|
else return false;
|
|
|
|
nextturna = !nextturna;
|
|
return true;
|
|
}
|
|
|
|
const std::string& Game::getWinner() const {
|
|
Game::SYM winner = checkWinner();
|
|
if(winner == SYM::NONE) {
|
|
static const std::string EMPTY = "";
|
|
return EMPTY;
|
|
}
|
|
return SYM_NAMES[(int) winner];
|
|
}
|
|
|
|
Game::SYM Game::getPos(uint_fast8_t x, uint_fast8_t y) const {
|
|
return getField(x, y);
|
|
}
|
|
|
|
void Game::setPos(uint_fast8_t x, uint_fast8_t y, Game::SYM s) {
|
|
setField(x, y, s);
|
|
}
|
|
|
|
static constexpr bool checkThree(Game::SYM s1, Game::SYM s2, Game::SYM s3) {
|
|
return s1 == s2 && s2 == s3;
|
|
}
|
|
|
|
Game::SYM Game::checkWinner() const {
|
|
// diagonal top-left -> bottom right
|
|
if(checkThree(getField(0, 0), getField(1, 1), getField(2, 2))) {
|
|
return getField(1, 1);
|
|
}
|
|
|
|
// diagonal top right -> bottom left
|
|
if(checkThree(getField(2, 0), getField(1, 1), getField(0, 2))) {
|
|
return getField(1, 1);
|
|
}
|
|
|
|
// check rows and cols
|
|
for(uint_fast8_t i = 0; i < SIZE; ++i) {
|
|
if(checkThree(getField(0, i), getField(1, i), getField(2, i))) {
|
|
// spalte gleich
|
|
return getField(0, i);
|
|
}
|
|
if(checkThree(getField(i, 0), getField(i, 1), getField(i, 2))) {
|
|
// zeile gleich
|
|
return getField(i, 0);
|
|
}
|
|
}
|
|
|
|
return SYM::NONE;
|
|
} |