Game.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. #include <iostream>
  2. #include "Game.h"
  3. #include "Types.h"
  4. Game::Game() : activeX(-1), activeY(-1), directionX(0), directionY(0), lastLocation(0) {
  5. }
  6. void Game::print(String& s) const {
  7. s.append("\n\r 0 1 2 3 4 5 6 7 8\n\r");
  8. printLine(s, 0);
  9. s.append(" |\\|/|\\|/|\\|/|\\|/|\n\r");
  10. printLine(s, 1);
  11. s.append(" |/|\\|/|\\|/|\\|/|\\|\n\r");
  12. printLine(s, 2);
  13. s.append(" |\\|/|\\|/|\\|/|\\|/|\n\r");
  14. printLine(s, 3);
  15. s.append(" |/|\\|/|\\|/|\\|/|\\|\n\r");
  16. printLine(s, 4);
  17. s.append("\n\r");
  18. }
  19. void Game::printLine(String& s, int index) const {
  20. static const char map[] = {
  21. '#', 'O', '.'
  22. };
  23. s.append(index + '0').append(' ');
  24. for(int x = 0; x < 8; x++) {
  25. if(x == activeX && index == activeY) {
  26. s.append("*-");
  27. continue;
  28. }
  29. s.append(map[fields[x][index]]).append('-');
  30. }
  31. if(8 == activeX && index == activeY) {
  32. s.append('*');
  33. } else {
  34. s.append(map[fields[8][index]]);
  35. }
  36. s.append("\n\r");
  37. }
  38. void Game::parse() {
  39. String s;
  40. while(true) {
  41. char c = std::cin.get();
  42. if(c == '0') {
  43. parseFields();
  44. continue;
  45. }
  46. if(c == '\n' || c == '\r') {
  47. std::cerr << s << "\n";
  48. s.clear();
  49. continue;
  50. }
  51. s.append(c);
  52. if(s == "select stone:") {
  53. std::cerr << s;
  54. s.clear();
  55. selectStone();
  56. } else if(s == "select location to move:") {
  57. std::cerr << s;
  58. s.clear();
  59. selectLocationToMove();
  60. } else if(s == "select stone to take:") {
  61. std::cerr << s;
  62. s.clear();
  63. selectStoneToTake();
  64. }
  65. }
  66. }
  67. void Game::consumeLine() const {
  68. while(std::cin.get() != '\n');
  69. while(true) {
  70. char c = std::cin.peek();
  71. if(c != '\r') {
  72. break;
  73. }
  74. std::cin.get();
  75. }
  76. }
  77. void Game::consumeLine(uint index) {
  78. std::cin.get();
  79. std::cin.get();
  80. for(uint i = 0; i < 9; i++) {
  81. char c = std::cin.get();
  82. if(c == '#') {
  83. fields[i][index] = BLACK;
  84. } else if(c == '.') {
  85. fields[i][index] = EMPTY;
  86. } else if(c == 'O') {
  87. fields[i][index] = WHITE;
  88. } else if(c == '*') {
  89. activeX = i;
  90. activeY = index;
  91. fields[i][index] = WHITE;
  92. } else {
  93. std::cerr << "game field parsing error\n";
  94. }
  95. std::cin.get();
  96. }
  97. }
  98. void Game::parseFields() {
  99. for(uint i = 0; i < 5; i++) {
  100. consumeLine();
  101. consumeLine(i);
  102. }
  103. String s;
  104. print(s);
  105. std::cerr << s;
  106. }
  107. void Game::selectStone() {
  108. lastLocation = 0;
  109. directionX = 0;
  110. directionY = 0;
  111. Location from;
  112. int rank = -1;
  113. for(int bx = 0; bx < 9; bx++) {
  114. for(int by = 0; by < 5; by++) {
  115. if(fields[bx][by] != EMPTY) {
  116. continue;
  117. }
  118. for(int mx = -1; mx <= 1; mx++) {
  119. for(int my = -1; my <= 1; my++) {
  120. int x = bx + mx;
  121. int y = by + my;
  122. if((mx == 0 && my == 0) || !isInRange(x, y) || !areNeighbours(bx, by, x, y) || fields[x][y] != WHITE) {
  123. continue;
  124. }
  125. int rankA = getRank(bx, by, x, y);
  126. int rankB = getRank(x, y, bx, by);
  127. if(rankA > rank) {
  128. rank = rankA;
  129. from = {x, y};
  130. }
  131. if(rankB > rank) {
  132. rank = rankB;
  133. from = {x, y};
  134. }
  135. }
  136. }
  137. }
  138. }
  139. std::cout << from.x << " " << from.y << "\n";
  140. }
  141. void Game::selectLocationToMove() {
  142. Location to;
  143. int rank = -1;
  144. for(int mx = -1; mx <= 1; mx++) {
  145. for(int my = -1; my <= 1; my++) {
  146. int x = activeX + mx;
  147. int y = activeY + my;
  148. if((mx == 0 && my == 0) || (mx == directionX && my == directionY) || !isInRange(x, y) ||
  149. !areNeighbours(activeX, activeY, x, y) || fields[x][y] != EMPTY || isInQueue(x, y)) {
  150. continue;
  151. }
  152. int rankA = getRank(x, y, activeX, activeY);
  153. int rankB = getRank(activeX, activeY, x, y);
  154. if(rankA > rank) {
  155. rank = rankA;
  156. to = {x, y};
  157. }
  158. if(rankB > rank) {
  159. rank = rankB;
  160. to = {x, y};
  161. }
  162. }
  163. }
  164. addLocation(activeX, activeY);
  165. directionX = to.x - activeX;
  166. directionY = to.y - activeY;
  167. std::cout << to.x << " " << to.y << "\n";
  168. }
  169. void Game::selectStoneToTake() {
  170. int rankA = getRank(activeX, activeY, activeX + directionX, activeY + directionY);
  171. int rankB = getRank(activeX + directionX, activeY + directionY, activeX, activeY);
  172. if(rankA > rankB) {
  173. std::cout << (activeX + directionX * 2) << " " << (activeY + directionY * 2) << "\n";
  174. } else {
  175. std::cout << (activeX - directionX) << " " << (activeY - directionY) << "\n";
  176. }
  177. }
  178. bool Game::isInRange(int x, int y) const {
  179. return x >= 0 && x <= 8 && y >= 0 && y <= 4;
  180. }
  181. bool Game::areNeighbours(int x, int y, int x2, int y2) const {
  182. if(x == x2 && y == y2) {
  183. return false;
  184. }
  185. int diffX = x - x2;
  186. int diffY = y - y2;
  187. if(diffX < -1 || diffX > 1 || diffY < -1 || diffY > 1) {
  188. return false;
  189. }
  190. if(diffX == 0 || diffY == 0) {
  191. return true;
  192. }
  193. return !((x & 1) ^ (y & 1));
  194. }
  195. int Game::getRank(int x, int y, int x2, int y2) const {
  196. int diffX = x2 - x;
  197. int diffY = y2 - y;
  198. int rank = 0;
  199. while(true) {
  200. x2 += diffX;
  201. y2 += diffY;
  202. if(!isInRange(x2, y2) || fields[x2][y2] != BLACK) {
  203. return rank;
  204. }
  205. rank++;
  206. }
  207. }
  208. void Game::addLocation(int x, int y) {
  209. if(lastLocation >= lastLocations.size()) {
  210. // safely to ignore, such long turns will never happen
  211. return;
  212. }
  213. lastLocations[lastLocation].x = x;
  214. lastLocations[lastLocation].y = y;
  215. lastLocation++;
  216. }
  217. bool Game::isInQueue(int x, int y) const {
  218. for(uint i = 0; i < lastLocation; i++) {
  219. if(lastLocations[i].x == x && lastLocations[i].y == y) {
  220. return true;
  221. }
  222. }
  223. return false;
  224. }