瀏覽代碼

refactoring

Kajetan Johannes Hammerle 3 年之前
父節點
當前提交
9739ad0bec
共有 5 個文件被更改,包括 123 次插入88 次删除
  1. 1 1
      Makefile
  2. 69 76
      source/Game.cpp
  3. 11 10
      source/Game.h
  4. 41 0
      source/List.h
  5. 1 1
      source/Main.cpp

+ 1 - 1
Makefile

@@ -5,7 +5,7 @@ all: fanorona
 test: fanorona
 	socat TCP4-CONNECT:alpaga.hammerle.me:4455 EXEC:"./fanorona"
 	
-fanorona: source/Main.cpp source/Game.cpp source/Game.h source/String.cpp source/String.h source/Vector.cpp source/Vector.h
+fanorona: source/Main.cpp source/Game.cpp source/Game.h source/String.cpp source/String.h source/Vector.cpp source/Vector.h source/List.h
 	g++ source/Main.cpp source/Game.cpp source/String.cpp source/Vector.cpp ${ARGS}
 	
 clean:

+ 69 - 76
source/Game.cpp

@@ -6,7 +6,7 @@
 std::array<Vector, 8> Game::neighbours;
 std::array<Vector, 9 * 5> Game::fieldVectors;
 
-Game::Game() : active(-1, -1), direction(0, 0), mustTake(false), lastLocation(0) {
+Game::Game() : active(-1, -1), mustTake(false) {
     std::cout << "0\n1\n0\n";
 
     neighbours[0].set(1, 0);
@@ -26,72 +26,75 @@ Game::Game() : active(-1, -1), direction(0, 0), mustTake(false), lastLocation(0)
     }
 }
 
-void Game::print(String& s) const {
+char Game::getChar(int x, int y) const {
+    if(active.compare(x, y)) {
+        return '*';
+    }
+    static const char map[] = {'#', 'O', '.'};
+    return map[fields[x][y]];
+}
+
+void Game::toString(String& s) const {
     s.append("  0 1 2 3 4 5 6 7 8\n");
-    printLine(s, 0);
+    lineToString(s, 0);
     s.append("  |\\|/|\\|/|\\|/|\\|/|\n");
-    printLine(s, 1);
+    lineToString(s, 1);
     s.append("  |/|\\|/|\\|/|\\|/|\\|\n");
-    printLine(s, 2);
+    lineToString(s, 2);
     s.append("  |\\|/|\\|/|\\|/|\\|/|\n");
-    printLine(s, 3);
+    lineToString(s, 3);
     s.append("  |/|\\|/|\\|/|\\|/|\\|\n");
-    printLine(s, 4);
+    lineToString(s, 4);
     s.append("\n");
 }
 
-void Game::printLine(String& s, int y) const {
-    static const char map[] = {
-        '#', 'O', '.'
-    };
+void Game::lineToString(String& s, int y) const {
     s.append(y + '0').append(' ');
     for(int x = 0; x < 8; x++) {
-        if(active.compare(x, y)) {
-            s.append("*-");
-            continue;
-        }
-        s.append(map[fields[x][y]]).append('-');
-    }
-    if(active.compare(8, y)) {
-        s.append('*');
-    } else {
-        s.append(map[fields[8][y]]);
+        s.append(getChar(x, y)).append('-');
     }
-    s.append("\n\r");
+    s.append(getChar(8, y)).append("\n\r");
 }
 
-void Game::parse() {
-    String s;
+void Game::readLine() {
+    String line;
     while(true) {
         char c = std::cin.get();
-        if(c == '\r') {
-            continue;
-        }
-        if(c != '\n') {
-            s.append(c);
-            continue;
-        }
-        if(s == "   0   1   2   3   4   5   6   7   8") {
-            parseFields();
-        } else if(s == "Please enter origin x-axis") {
-            makeSelection();
-        } else if(s == "Please enter destination x-axis") {
-            makeMove();
-        } else if(s == "Please enter wether you want to Withdraw or Approach [W/A]") {
-            takeStone();
-        } else if(s == "Do you want to continue with your turn [Y/N]?") {
-            std::cout << "Y\n";
-        } else if(s == "************************Player 1 won!**********************" ||
-                s == "************************Player 2 won!**********************") {
-            std::cerr << s << "\n";
-            return;
+        if(c == '\n') {
+            if(parseLine(line)) {
+                return;
+            }
+            line.clear();
+        } else if(c != '\r') {
+            line.append(c);
         }
-        s.clear();
     }
 }
 
+bool Game::parseLine(const String& line) {
+    if(line == "   0   1   2   3   4   5   6   7   8") {
+        readFields();
+        printFields();
+    } else if(line == "Please enter origin x-axis") {
+        makeSelection();
+    } else if(line == "Please enter destination x-axis") {
+        makeMove();
+    } else if(line == "Please enter wether you want to Withdraw or Approach [W/A]") {
+        takeStone();
+    } else if(line == "Do you want to continue with your turn [Y/N]?") {
+        std::cout << "Y\n";
+    } else if(line == "************************Player 1 won!**********************" ||
+            line == "************************Player 2 won!**********************") {
+        std::cerr << line << "\n";
+        return true;
+    }
+    return false;
+}
+
 void Game::consumeLine() const {
+    // skip until newline
     while(std::cin.get() != '\n');
+    // skip any trailing line carriage
     while(true) {
         char c = std::cin.peek();
         if(c != '\r') {
@@ -101,11 +104,13 @@ void Game::consumeLine() const {
     }
 }
 
-void Game::consumeLine(uint y) {
+void Game::readLine(uint y) {
+    // skip line heading
     std::cin.get();
     std::cin.get();
     std::cin.get();
     for(uint x = 0; x < 9; x++) {
+        // read field state
         char c = std::cin.get();
         if(c == '2') {
             fields[x][y] = BLACK;
@@ -116,19 +121,23 @@ void Game::consumeLine(uint y) {
         } else {
             std::cerr << "game field parsing error\n";
         }
+        // skip " - " until the next field (or the next line for x = 8)
         std::cin.get();
         std::cin.get();
         std::cin.get();
     }
 }
 
-void Game::parseFields() {
+void Game::readFields() {
     for(uint i = 0; i < 5; i++) {
         consumeLine();
-        consumeLine(i);
+        readLine(i);
     }
+}
+
+void Game::printFields() const {
     String s;
-    print(s);
+    toString(s);
     std::cerr << s;
 }
 
@@ -175,24 +184,8 @@ uint Game::getRank(const Vector& from, const Vector& to, FieldState state) const
     }
 }
 
-void Game::addLocation(const Vector& v) {
-    if(lastLocation < lastLocations.size()) {
-        lastLocations[lastLocation] = v;
-        lastLocation++;
-    }
-}
-
-bool Game::isInQueue(const Vector& v) const {
-    for(uint i = 0; i < lastLocation; i++) {
-        if(lastLocations[i] == v) {
-            return true;
-        }
-    }
-    return false;
-}
-
 uint Game::getStoneTakes(const Vector& from, const Vector& to) const {
-    if(!isInRange(to) || !hasState(to, EMPTY) || !areNeighbours(from, to) || isInQueue(to) || (to - from) == direction) {
+    if(!isInRange(to) || !hasState(to, EMPTY) || !areNeighbours(from, to) || lastLocations.contains(to) || (to - from) == direction) {
         return 0;
     }
     FieldState enemy = (hasState(from, BLACK) ? WHITE : BLACK);
@@ -211,7 +204,7 @@ uint Game::getStoneTakes(const Vector& from, const Vector& to) const {
         copy.removeLine(to, from, enemy);
         rank = rankB;
     }
-    copy.addLocation(from);
+    copy.lastLocations.add(from);
     copy.move(from, to);
 
     uint maxRank = 0;
@@ -269,7 +262,7 @@ void Game::move(const Vector& from, const Vector& to) {
 }
 
 void Game::makeSelection() {
-    lastLocation = 0;
+    lastLocations.clear();
     direction.set(0, 0);
 
     mustTake = isTakingPossible();
@@ -296,12 +289,12 @@ void Game::makeSelection() {
         }
     }
     active = selection;
-    
+
     std::cerr << "Selecting (" << selection.x << ", " << selection.y << ")\n";
     String s;
-    print(s);
+    toString(s);
     std::cerr << s;
-    
+
     std::cout << selection.x << "\n" << selection.y << "\n";
 }
 
@@ -310,10 +303,10 @@ void Game::makeMove() {
     int maxRank = -100000;
     for(Vector& m : neighbours) {
         Vector to = active + m;
-        if(!isInRange(to) || !hasState(to, EMPTY) || isInQueue(to) || !areNeighbours(active, to) || m == direction) {
+        if(!isInRange(to) || !hasState(to, EMPTY) || lastLocations.contains(to) || !areNeighbours(active, to) || m == direction) {
             continue;
         }
-        if(lastLocation > 0 || mustTake) {
+        if(!lastLocations.isEmpty() || mustTake) {
             int rank = getRank(active, to, BLACK) + getRank(to, active, BLACK);
             if(rank == 0) {
                 continue;
@@ -325,7 +318,7 @@ void Game::makeMove() {
             maxTo = to;
         }
     }
-    addLocation(active);
+    lastLocations.add(active);
     direction = maxTo - active;
     active = maxTo;
     std::cerr << "Move to (" << maxTo.x << ", " << maxTo.y << ")\n";
@@ -354,7 +347,7 @@ int Game::getQuality(const Vector& from, const Vector& to) const {
     } else {
         copy.removeLine(to, from, BLACK);
     }
-    copy.lastLocation = 0;
+    copy.lastLocations.clear();
     copy.direction.set(0, 0);
 
     int whiteFreedom = copy.getFreedom(WHITE);

+ 11 - 10
source/Game.h

@@ -6,6 +6,7 @@
 #include "String.h"
 #include "Types.h"
 #include "Vector.h"
+#include "List.h"
 
 class Game final {
 public:
@@ -15,21 +16,22 @@ public:
     };
 
     Game();
-    void parse();
+    void readLine();
 
 private:
+    bool parseLine(const String& command);
+    
     void consumeLine() const;
-    void consumeLine(uint y);
-    void parseFields();
+    void readLine(uint y);
+    void readFields();
+    void printFields() const;
 
     bool isInRange(const Vector& v) const;
-    void print(String& s) const;
-    void printLine(String& s, int y) const;
+    char getChar(int x, int y) const;
+    void toString(String& s) const;
+    void lineToString(String& s, int y) const;
     
     bool areNeighbours(const Vector& from, const Vector& to) const;
-
-    void addLocation(const Vector& v);
-    bool isInQueue(const Vector& v) const;
     
     void removeLine(const Vector& from, const Vector& to, FieldState state);
     uint getRank(const Vector& from, const Vector& to, FieldState state) const;
@@ -60,8 +62,7 @@ private:
     Vector direction;
     bool mustTake;
     
-    std::array<Vector, 20> lastLocations;
-    uint lastLocation;
+    List<Vector, 20> lastLocations;
 
     static std::array<Vector, 8> neighbours;
     static std::array<Vector, 9 * 5> fieldVectors;

+ 41 - 0
source/List.h

@@ -0,0 +1,41 @@
+#ifndef LIST_H
+#define LIST_H
+
+#include <array>
+
+#include "Types.h"
+
+template<typename T, uint N>
+class List final {
+public:
+
+    void add(const T& t) {
+        if(index >= N) {
+            return;
+        }
+        array[index++] = t;
+    }
+
+    void clear() {
+        index = 0;
+    }
+
+    bool contains(const T& t) const {
+        for(uint i = 0; i < index; i++) {
+            if(t == array[i]) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    bool isEmpty() const {
+        return index == 0;
+    }
+
+private:
+    uint index = 0;
+    std::array<T, N> array;
+};
+
+#endif

+ 1 - 1
source/Main.cpp

@@ -2,6 +2,6 @@
 
 int main() {
     Game game;
-    game.parse();
+    game.readLine();
     return 0;
 }