|
|
|
@ -1,4 +1,5 @@
|
|
|
|
|
// Design an algorithm to figure out if someone has won in a game of tic-tac-toe.
|
|
|
|
|
// Design an algorithm to figure out if someone has won in a game of
|
|
|
|
|
// tic-tac-toe.
|
|
|
|
|
|
|
|
|
|
#define CATCH_CONFIG_MAIN
|
|
|
|
|
#include <catch.hpp>
|
|
|
|
@ -8,61 +9,51 @@
|
|
|
|
|
enum class Owner {
|
|
|
|
|
Invalid = 0,
|
|
|
|
|
None = 1,
|
|
|
|
|
X = 2,
|
|
|
|
|
O = 4,
|
|
|
|
|
X = 2,
|
|
|
|
|
O = 4,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
using Row = std::array<Owner, 3>;
|
|
|
|
|
using Board = std::array<Row, 3>;
|
|
|
|
|
static const int Dim = 3;
|
|
|
|
|
|
|
|
|
|
static Owner merge(std::initializer_list<Owner> items) {
|
|
|
|
|
using Row = std::array<Owner, Dim>;
|
|
|
|
|
using Board = std::array<Row, Dim>;
|
|
|
|
|
|
|
|
|
|
static bool is_winner(const Board& board, int x, int y, int dx, int dy) {
|
|
|
|
|
int merged = 0;
|
|
|
|
|
|
|
|
|
|
for (auto item: items) {
|
|
|
|
|
merged |= int(item);
|
|
|
|
|
for (auto i = 0; i < Dim; i++) {
|
|
|
|
|
merged |= int(board[y+i*dy][x+i*dx]);
|
|
|
|
|
}
|
|
|
|
|
return Owner(merged);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool is_winner(Owner owner) {
|
|
|
|
|
auto owner = Owner(merged);
|
|
|
|
|
return owner == Owner::X || owner == Owner::O;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool has_winner(const Board& board) {
|
|
|
|
|
Owner winner = Owner::Invalid;
|
|
|
|
|
|
|
|
|
|
for (const auto& row: board) {
|
|
|
|
|
if (is_winner(merge({row[0], row[1], row[2]}))) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for (size_t x = 0; x < board[0].size(); x++) {
|
|
|
|
|
if (is_winner(merge({board[0][x], board[1][x], board[2][x]}))) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (is_winner(merge({board[0][0], board[1][1], board[2][2]}))) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
if (is_winner(merge({board[2][0], board[1][1], board[0][2]}))) {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
return false
|
|
|
|
|
// Columns
|
|
|
|
|
|| is_winner(board, 0, 0, 1, 0)
|
|
|
|
|
|| is_winner(board, 0, 1, 1, 0)
|
|
|
|
|
|| is_winner(board, 0, 2, 1, 0)
|
|
|
|
|
// Rows
|
|
|
|
|
|| is_winner(board, 0, 0, 0, 1)
|
|
|
|
|
|| is_winner(board, 1, 0, 0, 1)
|
|
|
|
|
|| is_winner(board, 2, 0, 0, 1)
|
|
|
|
|
// Diagonals
|
|
|
|
|
|| is_winner(board, 0, 0, 1, 1)
|
|
|
|
|
|| is_winner(board, 2, 0, -1, 1)
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Board make_board(std::string defn) {
|
|
|
|
|
static Board make_board(const std::string& defn) {
|
|
|
|
|
Board board;
|
|
|
|
|
int x = 0;
|
|
|
|
|
int y = 0;
|
|
|
|
|
|
|
|
|
|
for (auto& row : board) {
|
|
|
|
|
for (auto& cell: row) {
|
|
|
|
|
cell = Owner::None;
|
|
|
|
|
}
|
|
|
|
|
row.fill(Owner::None);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto ch: defn) {
|
|
|
|
|
for (auto ch : defn) {
|
|
|
|
|
switch (ch) {
|
|
|
|
|
case 'x':
|
|
|
|
|
board[y][x] = Owner::X;
|
|
|
|
@ -73,7 +64,7 @@ Board make_board(std::string defn) {
|
|
|
|
|
default:
|
|
|
|
|
board[y][x] = Owner::None;
|
|
|
|
|
}
|
|
|
|
|
if (++x == 3) {
|
|
|
|
|
if (++x == Dim) {
|
|
|
|
|
x = 0;
|
|
|
|
|
y++;
|
|
|
|
|
}
|
|
|
|
|