tictactoebot/src/game.cpp

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