Game.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. #include <iostream>
  2. #include "Game.h"
  3. #include "Types.h"
  4. Game::Game() : activeX(-1), activeY(-1) {
  5. reset();
  6. }
  7. void Game::reset() {
  8. activeX = -1;
  9. activeY = -1;
  10. for(uint x = 0; x < 9; x++) {
  11. for(uint y = 0; y < 5; y++) {
  12. fields[x][y] = (y > 2 ? FieldState::WHITE : FieldState::BLACK);
  13. }
  14. }
  15. fields[0][2] = FieldState::WHITE;
  16. fields[2][2] = FieldState::WHITE;
  17. fields[4][2] = FieldState::EMPTY;
  18. fields[5][2] = FieldState::WHITE;
  19. fields[7][2] = FieldState::WHITE;
  20. }
  21. void Game::reset(String& output) {
  22. reset();
  23. output.append("Fanorona Game\n");
  24. print(output);
  25. output.append("Human Color: White(O)\nAIColor: Black(#)\nHuman turn\nselect stone: ");
  26. }
  27. void Game::print(String& s) const {
  28. s.append("\n 0 1 2 3 4 5 6 7 8\n");
  29. printLine(s, 0);
  30. s.append(" |\\|/|\\|/|\\|/|\\|/|\n");
  31. printLine(s, 1);
  32. s.append(" |/|\\|/|\\|/|\\|/|\\|\n");
  33. printLine(s, 2);
  34. s.append(" |\\|/|\\|/|\\|/|\\|/|\n");
  35. printLine(s, 3);
  36. s.append(" |/|\\|/|\\|/|\\|/|\\|\n");
  37. printLine(s, 4);
  38. s.append('\n');
  39. }
  40. void Game::printLine(String& s, int index) const {
  41. static const char map[] = {
  42. '#', 'O', '.'
  43. };
  44. s.append(index + '0').append(' ');
  45. for(int x = 0; x < 8; x++) {
  46. if(x == activeX && index == activeY) {
  47. s.append("*-");
  48. continue;
  49. }
  50. s.append(map[fields[x][index]]).append('-');
  51. }
  52. if(8 == activeX && index == activeY) {
  53. s.append('*');
  54. } else {
  55. s.append(map[fields[8][index]]);
  56. }
  57. s.append('\n');
  58. }
  59. void Game::parse(const String& input, String& output) {
  60. if(input.getLength() <= 2 || !isDigit(input[0]) || input[1] != ' ' || !isDigit(input[2])) {
  61. revertToSelection(output);
  62. return;
  63. }
  64. uint x = input[0] - '0';
  65. uint y = input[2] - '0';
  66. if(x >= 9 || y >= 6) {
  67. revertToSelection(output);
  68. return;
  69. }
  70. if(activeX == -1 || activeY == -1) {
  71. markActive(x, y, output);
  72. } else {
  73. move(x, y, output);
  74. }
  75. }
  76. bool Game::isDigit(char c) const {
  77. return c >= '0' && c <= '9';
  78. }
  79. void Game::markActive(int x, int y, String& output) {
  80. if(fields[x][y] != FieldState::WHITE) {
  81. revertToSelection(output);
  82. return;
  83. }
  84. activeX = x;
  85. activeY = y;
  86. print(output);
  87. output.append("Human Color: White(O)\nAIColor: Black(#)\nselect location to move: ");
  88. }
  89. void Game::move(int x, int y, String& output) {
  90. if(fields[x][y] != FieldState::EMPTY || !areNeighbours(activeX, activeY, x, y)) {
  91. revertToSelection(output);
  92. return;
  93. }
  94. fields[activeX][activeY] = FieldState::EMPTY;
  95. fields[x][y] = FieldState::WHITE;
  96. removeLine(x, y, activeX, activeY, FieldState::BLACK);
  97. removeLine(activeX, activeY, x, y, FieldState::BLACK);
  98. activeX = x;
  99. activeY = y;
  100. print(output);
  101. output.append("Human Color: White(O)\nAIColor: Black(#)\n");
  102. print(output);
  103. output.append("Human Color: White(O)\nAIColor: Black(#)\nAI turn\n");
  104. activeX = -1;
  105. activeY = -1;
  106. botMove(output);
  107. }
  108. bool Game::areNeighbours(int x, int y, int x2, int y2) const {
  109. if(x == x2 && y == y2) {
  110. return false;
  111. }
  112. int diffX = x - x2;
  113. int diffY = y - y2;
  114. if(diffX < -1 || diffX > 1 || diffY < -1 || diffY > 1) {
  115. return false;
  116. }
  117. if(diffX == 0 || diffY == 0) {
  118. return true;
  119. }
  120. return !((x & 1) ^ (y & 1));
  121. }
  122. void Game::revertToSelection(String& output) {
  123. activeX = -1;
  124. activeY = -1;
  125. print(output);
  126. output.append("Human Color: White(O)\nAIColor: Black(#)\nHuman turn\nselect stone: ");
  127. }
  128. void Game::removeLine(int x, int y, int x2, int y2, FieldState remove) {
  129. int diffX = x2 - x;
  130. int diffY = y2 - y;
  131. while(true) {
  132. x2 += diffX;
  133. y2 += diffY;
  134. if(x2 < 0 || x2 >= 9 || y2 < 0 || y2 >= 5 || fields[x2][y2] != remove) {
  135. return;
  136. }
  137. fields[x2][y2] = FieldState::EMPTY;
  138. }
  139. }
  140. void Game::botMove(String& output) {
  141. while(true) {
  142. int x = 0;
  143. int y = 0;
  144. while(true) {
  145. x = rand() % 9;
  146. y = rand() % 5;
  147. if(fields[x][y] == FieldState::EMPTY) {
  148. break;
  149. }
  150. }
  151. for(uint i = 0; i < 10; i++) {
  152. int mx = x + (rand() % 3) - 1;
  153. int my = y + (rand() % 3) - 1;
  154. if((mx == x && my == y) || mx < 0 || mx >= 9 || my < 0 || my >= 5 || fields[mx][my] != FieldState::BLACK) {
  155. continue;
  156. }
  157. fields[mx][my] = FieldState::EMPTY;
  158. fields[x][y] = FieldState::BLACK;
  159. removeLine(mx, my, x, y, FieldState::WHITE);
  160. removeLine(x, y, mx, my, FieldState::WHITE);
  161. activeX = x;
  162. activeY = y;
  163. print(output);
  164. activeX = -1;
  165. activeY = -1;
  166. print(output);
  167. revertToSelection(output);
  168. return;
  169. }
  170. }
  171. }