Advertisement
_TruELecter_

Untitled

Dec 11th, 2016
114
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.58 KB | None | 0 0
  1. package truelecter.checkers.board;
  2.  
  3. import java.util.LinkedList;
  4. import java.util.List;
  5.  
  6. /**
  7. * Board class for checkers. We are always playing as a bottom player.
  8. *
  9. * @author TrueLecter
  10. *
  11. */
  12. // □ ■ □ ■ □ ■ □ ■
  13. // ■ □ ■ □ ■ □ ■ □
  14. // □ ■ □ ■ □ ■ □ ■
  15. // ■ □ ■ □ ■ □ ■ □
  16. // □ ■ □ ■ □ ■ □ ■
  17. // ■ □ ■ □ ■ □ ■ □
  18. // □ ■ □ ■ □ ■ □ ■
  19. // ■ □ ■ □ ■ □ ■ □
  20.  
  21. public class Board {
  22. // 10 - enemy king
  23. // 1 - enemy
  24. // 0 - free cell
  25. // -1 - we
  26. // -10 - our king
  27. public static final byte ENEMY_KING = 10;
  28. public static final byte ENEMY_NORMAL = 1;
  29. public static final byte OUR_KING = -10;
  30. public static final byte OUR_NORMAL = -1;
  31.  
  32. private byte[][] board = new byte[8][8];
  33. private MoveChain fromMove = null;
  34.  
  35. public int ourChecker;
  36. public int ourKings;
  37. public int theirChecker;
  38. public int theirKings;
  39.  
  40. public Board(byte[][] board) {
  41. for (byte t = 0; t < 8; t += 2) {
  42. for (byte x = 0; x < 8; x++) {
  43. byte y = (byte) (x % 2 + t);
  44. byte c = board[x][y];
  45. if (c != 0) {
  46. byte sign = sign(board[x][y]);
  47. if (board[x][y] * sign > 1) {
  48. this.board[x][y] = (byte) (10 * sign);
  49. if (sign > 0) {
  50. theirKings++;
  51. } else {
  52. ourKings++;
  53. }
  54. } else {
  55. this.board[x][y] = (byte) (1 * sign);
  56. if (sign > 0) {
  57. theirChecker++;
  58. } else {
  59. ourChecker++;
  60. }
  61. }
  62. }
  63. }
  64. }
  65. }
  66.  
  67. public Board(Board previous, MoveChain multiMove) {
  68. for (byte y = 0; y < 8; y++) {
  69. for (byte x = 0; x < 8; x++) {
  70. board[x][y] = previous.board[x][y];
  71. switch (board[x][y]) {
  72. case Board.ENEMY_KING:
  73. theirKings++;
  74. break;
  75. case Board.ENEMY_NORMAL:
  76. theirChecker++;
  77. break;
  78. case Board.OUR_KING:
  79. ourKings++;
  80. break;
  81. case Board.OUR_NORMAL:
  82. ourChecker++;
  83. break;
  84. }
  85. }
  86. }
  87. fromMove = multiMove;
  88. for (int i = 0; i < multiMove.size(); i++) {
  89. Move m = multiMove.get(i);
  90. board[m.to.x][m.to.y] = board[m.from.x][m.from.y];
  91. board[m.from.x][m.from.y] = 0;
  92. if (m.captured != null) {
  93. board[m.captured.x][m.captured.y] = 0;
  94. }
  95. }
  96. }
  97.  
  98. public Board(Board previous, Move move) {
  99. this(previous, new MoveChain(move));
  100. }
  101.  
  102. public MoveChain getFromMove() {
  103. return fromMove;
  104. }
  105.  
  106. public List<MoveChain> movesFor(byte who) {
  107. if (who == 0) {
  108. throw new IllegalArgumentException("Idk who is it");
  109. }
  110. List<MoveChain> moves = new LinkedList<>();
  111. boolean onlyBite = false;
  112. byte sign = sign(who);
  113. for (byte t = 0; t < 8; t += 2) {
  114. for (byte x = 0; x < 8; x++) {
  115. byte y = (byte) (x % 2 + t); // (0,0) (1,1) (2,0) (3,1)
  116. // Move only our checkers
  117. if (board[x][y] != 0 && sign(board[x][y]) == sign) {
  118. MoveType mt = loopAction(false, x, y);
  119. if (mt.isBite && !onlyBite) {
  120. onlyBite = true;
  121. moves.clear();
  122. }
  123. if (onlyBite) {
  124. if (mt.isBite) {
  125. for (MoveChain m : mt.moves) {
  126. moves.add(m);
  127. }
  128. }
  129. } else {
  130. for (MoveChain m : mt.moves) {
  131. moves.add(m);
  132. }
  133. }
  134. }
  135. }
  136. }
  137. return moves;
  138. }
  139.  
  140. private MoveType loopAction(boolean onlyBite, byte x, byte y) {
  141. List<MoveChain> moves = new LinkedList<>();
  142. List<Cell>[] res = movesFor(x, y);
  143. List<Cell> biteable = res[0];
  144. Cell self = biteable.remove(0);
  145. if (biteable.isEmpty() && !onlyBite) {
  146. // Noone to bite
  147. for (Cell dest : res[1]) {
  148. moves.add(new MoveChain(new Move(self, dest)));
  149. }
  150. return new MoveType(moves, false);
  151. } else {
  152. for (Cell dest : biteable) {
  153. // moves.add(new MoveChain(new Move(self, dest)));
  154. List<Move> movez = new LinkedList<>();
  155. boolean isMan = self.value() == 1 || self.value() == -1;
  156. Cell t = new Cell(dest);
  157. switch (t.from) {
  158. case LEFT_UP:
  159. while (t.isLegal()) {
  160. movez.add(new Move(self, (t = t.rd()), dest));
  161. if (isMan || t.isChecker()) {
  162. break;
  163. }
  164. }
  165. break;
  166. case RIGHT_UP:
  167. while (t.isLegal()) {
  168. movez.add(new Move(self, (t = t.ld()), dest));
  169. if (isMan || t.isChecker()) {
  170. break;
  171. }
  172. }
  173. break;
  174. case LEFT_DOWN:
  175. while (t.isLegal()) {
  176. movez.add(new Move(self, (t = t.ru()), dest));
  177. if (isMan || t.isChecker()) {
  178. break;
  179. }
  180. }
  181. break;
  182. case RIGHT_DOWN:
  183. while (t.isLegal()) {
  184. movez.add(new Move(self, (t = t.lu()), dest));
  185. if (isMan || t.isChecker()) {
  186. break;
  187. }
  188. }
  189. break;
  190. default:
  191. throw new IllegalArgumentException("Unknown direction");
  192. }
  193.  
  194. // if (!isMan)
  195. // movez.remove(movez.size() - 1);
  196. for (Move m : movez) {
  197. if (m.to.isLegal() && m.to.value() == 0) {
  198. Board helpBoard = new Board(this, m);
  199. List<MoveChain> movezz = helpBoard.loopAction(true, m.to.x, m.to.y).moves;
  200. if (movezz.isEmpty()){
  201. moves.add(new MoveChain(m));
  202. } else {
  203. for (MoveChain mc : movezz) {
  204. moves.add(new MoveChain(m).append(mc));
  205. }
  206. }
  207. }
  208. }
  209.  
  210. }
  211. return new MoveType(moves, true);
  212. }
  213. }
  214.  
  215. /**
  216. * Test all possible move cells if there is any we can bite
  217. *
  218. * @return List of cell containing enemies we can bite
  219. */
  220. @SuppressWarnings("unchecked")
  221. private List<Cell>[] movesFor(byte x, byte y) {
  222. Cell c = new Cell(x, y);
  223. List<Cell> biteable = new LinkedList<>();
  224. List<Cell> moves = new LinkedList<>();
  225. // Add self not to create new one in future
  226. biteable.add(c);
  227. byte sign = sign(c.value());
  228. if (sign * c.value() == 10) {
  229. Cell t = c.lu();
  230. while (t.isLegal()) {
  231. if (t.isChecker()) {
  232. if (sign(t.value()) != sign) {
  233. if ((t = t.lu()).isLegal() && t.value() == 0)
  234. biteable.add(t.rd());
  235. break;
  236. }
  237. } else {
  238. moves.add(t);
  239. }
  240. t = t.lu();
  241. }
  242. t = c.ld();
  243. while (t.isLegal()) {
  244. if (t.isChecker()) {
  245. if (sign(t.value()) != sign) {
  246. if ((t = t.ld()).isLegal() && t.value() == 0)
  247. biteable.add(t.ru());
  248. break;
  249. }
  250. } else {
  251. moves.add(t);
  252. }
  253. t = t.ld();
  254. }
  255. t = c.ru();
  256. while (t.isLegal()) {
  257. if (t.isChecker()) {
  258. if (sign(t.value()) != sign) {
  259. if ((t = t.ru()).isLegal() && t.value() == 0)
  260. biteable.add(t.ld());
  261. break;
  262. }
  263. } else {
  264. moves.add(t);
  265. }
  266. t = t.ru();
  267. }
  268. t = c.rd();
  269. while (t.isLegal()) {
  270. if (t.isChecker()) {
  271. if (sign(t.value()) != sign) {
  272. if ((t = t.rd()).isLegal() && t.value() == 0)
  273. biteable.add(t.lu());
  274. break;
  275. }
  276. } else {
  277. moves.add(t);
  278. }
  279. t = t.rd();
  280. }
  281. } else {
  282. Cell t = c.lu();
  283. // Test if cell is in board bounds, checker in this cell is enemy
  284. // and next cell is free
  285. if (t.isLegal())
  286. if (t.isChecker()) {
  287. if (sign(t.value()) != sign && (t = t.lu()).isLegal() && t.value() == 0) {
  288. biteable.add(t.rd());
  289. }
  290. } else {
  291. if (sign == -1) {
  292. moves.add(t);
  293. }
  294. }
  295. t = c.ld();
  296. if (t.isLegal())
  297. if (t.isChecker()) {
  298. if (sign(t.value()) != sign && (t = t.ld()).isLegal() && t.value() == 0)
  299. biteable.add(t.ru());
  300. } else {
  301. if (sign == 1) {
  302. moves.add(t);
  303. }
  304. }
  305. t = c.ru();
  306. if (t.isLegal())
  307. if (t.isChecker()) {
  308. if (sign(t.value()) != sign && (t = t.ru()).isLegal() && t.value() == 0)
  309. biteable.add(t.ld());
  310. } else {
  311. if (sign == -1) {
  312. moves.add(t);
  313. }
  314. }
  315. t = c.rd();
  316. if (t.isLegal())
  317. if (t.isChecker()) {
  318. if (sign(t.value()) != sign && (t = t.rd()).isLegal() && t.value() == 0)
  319. biteable.add(t.lu());
  320. } else {
  321. if (sign == 1) {
  322. moves.add(t);
  323. }
  324. }
  325. }
  326. return new List[] { biteable, moves };
  327. }
  328.  
  329. /**
  330. * Returns current board state
  331. *
  332. * @return 0 - if still playing</br>
  333. * -1 - if we won</br>
  334. * 1 - if enemy won</br>
  335. * -128 - if draw
  336. */
  337. public byte state(byte turn) {
  338. int our;
  339. if ((our = (ourKings + ourChecker)) == 0) {
  340. return 1;
  341. }
  342. int their;
  343. if ((their = (theirKings + theirChecker)) == 0) {
  344. return -1;
  345. }
  346. if ((our == their && their == 1 && ourKings == theirKings) || movesFor(turn).isEmpty()) {
  347. return -128;
  348. }
  349. return 0;
  350. }
  351.  
  352. public class Cell {
  353. public byte x;
  354. public byte y;
  355. public Direction from;
  356.  
  357. public Cell(byte x, byte y) {
  358. this.x = x;
  359. this.y = y;
  360. }
  361.  
  362. public Cell(Cell c) {
  363. this(c.x, c.y);
  364. setDirection(c.from);
  365. }
  366.  
  367. public Cell add(byte x, byte y) {
  368. this.x += x;
  369. this.y += y;
  370. return this;
  371. }
  372.  
  373. public Cell substract(byte x, byte y) {
  374. this.x -= x;
  375. this.y -= y;
  376. return this;
  377. }
  378.  
  379. public Cell lu() {
  380. return lu((byte) 1);
  381. }
  382.  
  383. public Cell lu(byte b) {
  384. return new Cell(this).substract(b, b).setDirection(Direction.LEFT_UP);
  385. }
  386.  
  387. public Cell ld() {
  388. return ld((byte) 1);
  389. }
  390.  
  391. public Cell ld(byte b) {
  392. return new Cell(this).substract((byte) -b, b).setDirection(Direction.LEFT_DOWN);
  393. }
  394.  
  395. public Cell rd() {
  396. return rd((byte) 1);
  397. }
  398.  
  399. public Cell rd(byte b) {
  400. return new Cell(this).add(b, b).setDirection(Direction.RIGHT_DOWN);
  401. }
  402.  
  403. public Cell ru() {
  404. return ru((byte) 1);
  405. }
  406.  
  407. public Cell ru(byte b) {
  408. return new Cell(this).add((byte) -b, b).setDirection(Direction.RIGHT_UP);
  409. }
  410.  
  411. public boolean isChecker() {
  412. return isLegal() && (Board.this.board[x][y] != 0);
  413. }
  414.  
  415. public byte value() {
  416. if (isLegal()) {
  417. return Board.this.board[x][y];
  418. }
  419. // Illegal cell
  420. return -128;
  421. }
  422.  
  423. public boolean isLegal() {
  424. return x > -1 && x < 8 && y > -1 && y < 8;
  425. }
  426.  
  427. private Cell setDirection(Direction d) {
  428. from = d;
  429. return this;
  430. }
  431.  
  432. @Override
  433. public String toString() {
  434. return "(" + x + "," + y + ")";
  435. }
  436.  
  437. }
  438.  
  439. private class MoveType {
  440. List<MoveChain> moves;
  441. boolean isBite;
  442.  
  443. MoveType(List<MoveChain> moves, boolean isBite) {
  444. this.moves = moves;
  445. this.isBite = isBite;
  446. }
  447. }
  448.  
  449. public static enum Direction {
  450. LEFT_UP, LEFT_DOWN, RIGHT_UP, RIGHT_DOWN, INITIAL;
  451. public Direction negate() {
  452. switch (this) {
  453. case LEFT_UP:
  454. return RIGHT_DOWN;
  455. case LEFT_DOWN:
  456. return RIGHT_UP;
  457. case RIGHT_UP:
  458. return LEFT_DOWN;
  459. case RIGHT_DOWN:
  460. return LEFT_UP;
  461. default:
  462. return INITIAL;
  463. }
  464. }
  465. }
  466.  
  467. private byte sign(byte b) {
  468. return (byte) (b > 0 ? 1 : -1);
  469. }
  470.  
  471. @Override
  472. public String toString() {
  473. StringBuilder sb = new StringBuilder();
  474. for (int x = 0; x < 8; x++) {
  475. for (int y = 0; y < 8; y++) {
  476. switch (board[x][y]) {
  477. case 1:
  478. sb.append('b');
  479. break;
  480. case 10:
  481. sb.append('B');
  482. break;
  483. case -1:
  484. sb.append('w');
  485. break;
  486. case -10:
  487. sb.append('W');
  488. break;
  489. default:
  490. sb.append('.');
  491. }
  492. }
  493. sb.append("\n");
  494. }
  495. return sb.toString();
  496. }
  497.  
  498. public Cell getCell(byte x, byte y) {
  499. return new Cell(x, y);
  500. }
  501.  
  502. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement