Skip to content

Method: checkDiagonaleDownLeftUpRight(VGBoard, VGFieldState, VGFieldState, VGFieldState, VGFieldState)

1: package de.fhdw.gaming.ipspiel22.vierGewinnt.strategy;
2:
3: import java.util.ArrayList;
4: import java.util.Collections;
5: import java.util.List;
6: import java.util.Objects;
7:
8: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.VGMove;
9: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.AbstractVGMove;
10: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG1ColumnMove;
11: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG2ColumnMove;
12: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG3ColumnMove;
13: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG4ColumnMove;
14: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG5ColumnMove;
15: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG6ColumnMove;
16: import de.fhdw.gaming.ipspiel22.vierGewinnt.moves.impl.VG7ColumnMove;
17: import de.fhdw.gaming.core.domain.GameException;
18: import de.fhdw.gaming.ipspiel22.searchtree.domain.MinMaxGame;
19: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGAnswerEnum;
20: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGBoard;
21: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGField;
22: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGFieldState;
23: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGPlayer;
24: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGPosition;
25: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.VGState;
26: import de.fhdw.gaming.ipspiel22.vierGewinnt.domain.impl.VGBoardImpl;
27:
28: /**
29: * MinMaxViergewinnt.
30: */
31: public class MinMaxViergewinnt implements MinMaxGame<VGPlayer, VGState, VGMove> {
32: /**
33: * Current given state.
34: */
35: private final VGState vgState;
36:
37: /**
38: * Current given state.
39: */
40: private final VGBoard inistialBoard;
41:
42: /**
43: * Current given player.
44: */
45: private final VGPlayer player;
46:
47: /**
48: * Playercolour for algorithm.
49: */
50: private Boolean playercolour;
51:
52: /**
53: * Saved Move.
54: */
55: private VGMove savedMove;
56:
57: /**
58: * For creating MinMaxViergewinnt.
59: *
60: * @param state Current given state.
61: * @param player Current given player.
62: */
63: public MinMaxViergewinnt(final VGState state, final VGPlayer player) {
64: this.vgState = state;
65: this.player = player;
66: this.playercolour = player.isUsingRedChips();
67: this.inistialBoard = new VGBoardImpl((VGBoardImpl) state.getBoard());
68: }
69:
70: @Override
71: public double evaluateStateful() {
72: double stateful;
73:
74: final VGFieldState state = playercolour ? VGFieldState.RED : VGFieldState.YELLOW;
75: final VGFieldState otherPlayerState = !playercolour ? VGFieldState.RED : VGFieldState.YELLOW;
76:
77: final List<Double> checkedStates = new ArrayList<>();
78: if (this.playercolour == this.player.isUsingRedChips()) {
79:
80: checkedStates.addAll(twoCombo(vgState.getBoard(), state, 6.0));
81: checkedStates.addAll(threeCombo(vgState.getBoard(), state, 12.0));
82: checkedStates.addAll(fourCombo(vgState.getBoard(), state, 24.0));
83:
84: stateful = Collections.max(checkedStates);
85: stateful += checkMiddle(vgState.getBoard(), playercolour);
86:
87: final List<Double> firstPossibleMoves = new ArrayList<>();
88: firstPossibleMoves.add(ifThreeWithMove(otherPlayerState,
89: !this.player.isUsingRedChips()));
90: firstPossibleMoves.add(ifThreeWithMove(state, this.player.isUsingRedChips()));
91: firstPossibleMoves.add(ifWonWithMove(otherPlayerState,
92: !this.player.isUsingRedChips()));
93: firstPossibleMoves.add(ifWonWithMove(state, this.player.isUsingRedChips()));
94: stateful += Collections.max(firstPossibleMoves);
95:
96: } else {
97: checkedStates.addAll(threeCombo(vgState.getBoard(), state, 5.0));
98: checkedStates.addAll(fourCombo(vgState.getBoard(), state, 20.0));
99:
100: stateful = Collections.max(checkedStates);
101: }
102: return stateful;
103: }
104:
105: @Override
106: public boolean isGameOver() {
107: final List<VGField> allFields = new ArrayList<>();
108: vgState.getBoard().getFields().forEach(allFields::addAll);
109:
110: if (allFields.stream().noneMatch(vgField -> vgField.getState().equals(VGFieldState.EMPTY))) {
111: return true;
112: } else {
113: return checkWinner(vgState.getBoard(), playercolour); // checkWinner(!playercolour);
114: }
115: }
116:
117: @Override
118: public List<VGMove> getPossibleMoves() {
119: final List<VGMove> movesList = new ArrayList<>();
120:
121: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.FIRSTCOLUMN))) {
122: movesList.add(new VG1ColumnMove());
123: }
124: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.SECONDCOLUMN))) {
125: movesList.add(new VG2ColumnMove());
126: }
127: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.THIRDCOLUMN))) {
128: movesList.add(new VG3ColumnMove());
129: }
130: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.FOURTHCOLUMN))) {
131: movesList.add(new VG4ColumnMove());
132: }
133: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.FITFHCOLUMN))) {
134: movesList.add(new VG5ColumnMove());
135: }
136: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.SIXTHCOLUMN))) {
137: movesList.add(new VG6ColumnMove());
138: }
139: if (Objects.nonNull(vgState.getBoard().getNextFieldInColumn(VGAnswerEnum.SEVENTHCOLUMN))) {
140: movesList.add(new VG7ColumnMove());
141: }
142: Collections.shuffle(movesList);
143: return movesList;
144: }
145:
146: @Override
147: public void commitMove(final VGMove move) throws GameException {
148: final VGPlayer playerMove = this.playercolour ? vgState.getRedPlayer() : vgState.getYellowPlayer();
149:
150: move.applyTo(this.vgState, playerMove);
151: this.playercolour = !this.playercolour;
152:
153: }
154:
155: @Override
156: public void rollbackMove(final VGMove move) {
157: if (move instanceof AbstractVGMove) {
158: vgState.getBoard().getFields().get(((AbstractVGMove) move).getColumnInt() - 1);
159:
160: int count = 0;
161: VGField field = vgState.getBoard().getFields().get(((AbstractVGMove) move)
162: .getColumnInt() - 1).get(count);
163: while (!field.getState().equals(VGFieldState.EMPTY) && count < 5) {
164: count += 1;
165: field = vgState.getBoard().getFields().get(((AbstractVGMove) move)
166: .getColumnInt() - 1).get(count);
167: }
168: vgState.getBoard().getFields().get(((AbstractVGMove) move).getColumnInt() - 1)
169: .get(count == 0 ? count : count - 1)
170: .setState(VGFieldState.EMPTY);
171: }
172: this.playercolour = !this.playercolour;
173: }
174:
175: @Override
176: public VGMove saveFirstMoves(final VGMove move) {
177: this.savedMove = move;
178: return move;
179: }
180:
181: /**
182: * If possible to win with next move.
183: *
184: * @param state
185: * @param playercolor
186: * @return
187: */
188: private double ifWonWithMove(final VGFieldState state, final Boolean playercolor) {
189: final double value = playercolor == player.isUsingRedChips() ? 100.0 : 50.0;
190: return letsWinIfPossible(state, getMoveAsAnswer(this.savedMove),
191: playercolor) ? value : 0;
192: }
193:
194: /**
195: * converts Move to Answer.
196: *
197: * @param move
198: * @return
199: */
200: private VGAnswerEnum getMoveAsAnswer(final VGMove move) {
201: if (move instanceof VG1ColumnMove) {
202: return VGAnswerEnum.FIRSTCOLUMN;
203: } else if (move instanceof VG2ColumnMove) {
204: return VGAnswerEnum.SECONDCOLUMN;
205: } else if (move instanceof VG3ColumnMove) {
206: return VGAnswerEnum.THIRDCOLUMN;
207: } else if (move instanceof VG4ColumnMove) {
208: return VGAnswerEnum.FOURTHCOLUMN;
209: } else if (move instanceof VG5ColumnMove) {
210: return VGAnswerEnum.FITFHCOLUMN;
211: } else if (move instanceof VG6ColumnMove) {
212: return VGAnswerEnum.SIXTHCOLUMN;
213: } else {
214: return VGAnswerEnum.SEVENTHCOLUMN;
215: }
216: }
217:
218: /**
219: * If possible to have three chips in next move.
220: *
221: * @param state
222: * @param playercolor
223: * @return
224: */
225: private double ifThreeWithMove(final VGFieldState state, final boolean playercolor) {
226: final double value = playercolor == player.isUsingRedChips() ? 20.0 : 10.0;
227: return putThreeIfPossible(state, getMoveAsAnswer(this.savedMove)) ? value : 0;
228: }
229:
230: /**
231: * Win if possible.
232: *
233: * @param state
234: * @param column
235: * @param playercolor
236: * @return
237: */
238: private Boolean letsWinIfPossible(final VGFieldState state, final VGAnswerEnum column,
239: final Boolean playercolor) {
240: final VGField field = inistialBoard.getNextFieldInColumn(column);
241: Boolean won = false;
242: if (Objects.nonNull(field)) {
243: field.setState(state);
244: won = checkWinner(inistialBoard, playercolor);
245: field.setState(VGFieldState.EMPTY);
246: }
247: return won;
248: }
249:
250: /**
251: * Three if possible.
252: *
253: * @param state
254: * @param column
255: * @return
256: */
257: private Boolean putThreeIfPossible(final VGFieldState state, final VGAnswerEnum column) {
258: final VGField field = inistialBoard.getNextFieldInColumn(column);
259: Boolean won = false;
260: if (Objects.nonNull(field)) {
261: field.setState(state);
262: won = Collections.max(threeCombo(inistialBoard, state, 20.0)) > 0;
263: field.setState(VGFieldState.EMPTY);
264: }
265: return won;
266: }
267:
268: // -----------------------------------------------------------------------------------------------------
269:
270: /**
271: * Returns boolean, if Player has won.
272: *
273: * @param board
274: * @param usingRedChips The current player.
275: */
276: private boolean checkWinner(final VGBoard board, final Boolean usingRedChips) {
277: final VGFieldState state = usingRedChips ? VGFieldState.RED : VGFieldState.YELLOW;
278: return checkHorizontaleLeftToRight(board, state, state, state, state)
279: || checkVertikaleDownUp(board, state, state, state, state)
280: || checkDiagonaleDownLeftUpRight(board, state, state, state, state)
281: || checkDiagonaleDownRightUpLeftght(board, state, state, state, state);
282: }
283:
284: /**
285: * Checks condition, if true return rating else 0.0.
286: * @param condition
287: * @param rating
288: * @return
289: */
290: private Double checkCondition(final Boolean condition, final Double rating) {
291: return condition ? rating : 0.0;
292: }
293:
294: /**
295: * Checks if a two combo exists.
296: *
297: * @param board
298: * @param state
299: * @param rating
300: * @return
301: */
302: public List<Double> twoCombo(final VGBoard board, final VGFieldState state,
303: final Double rating) {
304: final List<Double> checkedStates = new ArrayList<>();
305: checkedStates
306: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, VGFieldState.EMPTY, state,
307: VGFieldState.EMPTY, state), rating));
308: checkedStates.add(
309: checkCondition(checkDiagonaleDownRightUpLeftght(board, VGFieldState.EMPTY, state,
310: VGFieldState.EMPTY, state), rating));
311: checkedStates
312: .add(checkCondition(checkHorizontaleLeftToRight(board, VGFieldState.EMPTY, state,
313: VGFieldState.EMPTY, state), rating));
314:
315: checkedStates
316: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, VGFieldState.EMPTY,
317: state, VGFieldState.EMPTY), rating));
318: checkedStates.add(
319: checkCondition(checkDiagonaleDownRightUpLeftght(board, state, VGFieldState.EMPTY,
320: state, VGFieldState.EMPTY), rating));
321: checkedStates
322: .add(checkCondition(checkHorizontaleLeftToRight(board, state, VGFieldState.EMPTY,
323: state, VGFieldState.EMPTY), rating));
324:
325: checkedStates
326: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, state, VGFieldState.EMPTY,
327: VGFieldState.EMPTY), rating));
328: checkedStates.add(
329: checkCondition(checkDiagonaleDownRightUpLeftght(board, state, state, VGFieldState.EMPTY,
330: VGFieldState.EMPTY), rating));
331: checkedStates
332: .add(checkCondition(checkHorizontaleLeftToRight(board, state, state, VGFieldState.EMPTY,
333: VGFieldState.EMPTY), rating));
334:
335: checkedStates
336: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, VGFieldState.EMPTY,
337: VGFieldState.EMPTY, state), rating));
338: checkedStates.add(
339: checkCondition(checkDiagonaleDownRightUpLeftght(board, state, VGFieldState.EMPTY,
340: VGFieldState.EMPTY, state), rating));
341: checkedStates
342: .add(checkCondition(checkHorizontaleLeftToRight(board, state, VGFieldState.EMPTY,
343: VGFieldState.EMPTY, state), rating));
344:
345: checkedStates
346: .add(checkCondition(checkDiagonaleDownLeftUpRight(board, VGFieldState.EMPTY,
347: VGFieldState.EMPTY, state, state), rating));
348: checkedStates.add(
349: checkCondition(checkDiagonaleDownRightUpLeftght(board, VGFieldState.EMPTY,
350: VGFieldState.EMPTY, state, state), rating));
351: checkedStates
352: .add(checkCondition(checkHorizontaleLeftToRight(board, VGFieldState.EMPTY,
353: VGFieldState.EMPTY, state, state), rating));
354:
355: checkedStates
356: .add(checkCondition(checkVertikaleDownUp(board, state, state, VGFieldState.EMPTY,
357: VGFieldState.EMPTY), rating));
358: return checkedStates;
359: }
360:
361: /**
362: * Checks if three Combo exists.
363: *
364: * @param board
365: * @param state
366: * @param rating
367: * @return
368: */
369: public List<Double> threeCombo(final VGBoard board, final VGFieldState state, final Double rating) {
370: // Drei gewinnt
371: final List<Double> checkedStates = new ArrayList<>();
372: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board, state, state,
373: VGFieldState.EMPTY, state), rating));
374: checkedStates
375: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board, state, state,
376: VGFieldState.EMPTY, state), rating));
377: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board, state, state,
378: VGFieldState.EMPTY, state), rating));
379:
380: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board, state,
381: VGFieldState.EMPTY, state, state), rating));
382: checkedStates
383: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board, state,
384: VGFieldState.EMPTY, state, state), rating));
385: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board, state,
386: VGFieldState.EMPTY, state, state), rating));
387:
388: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board,
389: VGFieldState.EMPTY, state, state, state), rating));
390: checkedStates
391: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board,
392: VGFieldState.EMPTY, state, state, state), rating));
393: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board,
394: VGFieldState.EMPTY, state, state, state), rating));
395:
396: checkedStates.add(checkCondition(checkDiagonaleDownLeftUpRight(board, state,
397: state, state, VGFieldState.EMPTY), rating));
398: checkedStates.add(checkCondition(checkVertikaleDownUp(board, state, state,
399: state, VGFieldState.EMPTY), rating));
400: checkedStates
401: .add(checkCondition(checkDiagonaleDownRightUpLeftght(board, state,
402: state, state, VGFieldState.EMPTY), rating));
403: checkedStates.add(checkCondition(checkHorizontaleLeftToRight(board, state,
404: state, state, VGFieldState.EMPTY), rating));
405: return checkedStates;
406: }
407:
408: /**
409: * If four combo exists.
410: *
411: * @param board
412: * @param state
413: * @param rating
414: * @return
415: */
416: public List<Double> fourCombo(final VGBoard board, final VGFieldState state, final Double rating) {
417: // Vier gewinnt
418: final List<Double> checkedStates = new ArrayList<>();
419: checkedStates.add(checkDiagonaleDownLeftUpRight(board, state, state, state, state) ? rating : 0.0);
420: checkedStates.add(checkVertikaleDownUp(board, state, state, state, state) ? rating : 0.0);
421: checkedStates.add(checkDiagonaleDownRightUpLeftght(board, state, state, state, state) ? rating : 0.0);
422: checkedStates.add(checkHorizontaleLeftToRight(board, state, state, state, state) ? rating : 0.0);
423: return checkedStates;
424: }
425:
426:
427: /**
428: * Extra Points for chips in the middle.
429: *
430: * @param board
431: * @param usingRedChips
432: * @return result
433: */
434: private double checkMiddle(final VGBoard board, final boolean usingRedChips) {
435: double result = 0.0;
436: final VGFieldState state = usingRedChips ? VGFieldState.RED : VGFieldState.YELLOW;
437:
438: result += board.getFields().get(2).stream().filter(field -> field.getState().equals(state))
439: .mapToDouble(field -> {
440: return 2.0;
441: }).sum(); // Dritte Spalte
442: result += board.getFields().get(3).stream().filter(field -> field.getState().equals(state))
443: .mapToDouble(field -> {
444: return 5.0;
445: }).sum(); // Vierte Spalte
446: result += board.getFields().get(4).stream().filter(field -> field.getState().equals(state))
447: .mapToDouble(field -> {
448: return 2.0;
449: }).sum(); // Fünfte Spa 0;
450:
451: return result;
452: }
453:
454: /**
455: * Checks horizontal.
456: *
457: * @param board
458: * @param chip1
459: * @param chip2
460: * @param chip3
461: * @param chip4
462: * @return
463: */
464: private Boolean checkHorizontaleLeftToRight(final VGBoard board, final VGFieldState chip1,
465: final VGFieldState chip2,
466: final VGFieldState chip3, final VGFieldState chip4) {
467: for (int i = 0; i < board.getRows(); i++) {
468: for (int j = 0; j < 4; j++) {
469: if (board.getFieldAt(VGPosition.of(j, i)).getState().equals(chip1)
470: && board.getFieldAt(VGPosition.of(j + 1, i)).getState().equals(chip2)
471: && board.getFieldAt(VGPosition.of(j + 2, i)).getState().equals(chip3)
472: && board.getFieldAt(VGPosition.of(j + 3, i)).getState().equals(chip4)) {
473: return true;
474: }
475: }
476: }
477: return false;
478: }
479:
480: /**
481: * checks vertical.
482: *
483: * @param board
484: * @param chip1
485: * @param chip2
486: * @param chip3
487: * @param chip4
488: * @return
489: */
490: private Boolean checkVertikaleDownUp(final VGBoard board, final VGFieldState chip1, final VGFieldState chip2,
491: final VGFieldState chip3,
492: final VGFieldState chip4) {
493: for (int i = 0; i < board.getColumns(); i++) {
494: for (int j = 0; j < 3; j++) {
495: if (board.getFieldAt(VGPosition.of(i, j)).getState().equals(chip1)
496: && board.getFieldAt(VGPosition.of(i, j + 1)).getState().equals(chip2)
497: && board.getFieldAt(VGPosition.of(i, j + 2)).getState().equals(chip3)
498: && board.getFieldAt(VGPosition.of(i, j + 3)).getState().equals(chip4)) {
499: return true;
500: }
501: }
502: }
503: return false;
504: }
505:
506: /**
507: * checks diagonale down left to up right.
508: *
509: * @param board
510: * @param chip1
511: * @param chip2
512: * @param chip3
513: * @param chip4
514: * @return
515: */
516: private Boolean checkDiagonaleDownLeftUpRight(final VGBoard board, final VGFieldState chip1,
517: final VGFieldState chip2,
518: final VGFieldState chip3, final VGFieldState chip4) {
519:• for (int i = 0; i < 3; i++) {
520:• for (int j = 0; j < 4; j++) {
521:• if (board.getFieldAt(VGPosition.of(j, i)).getState().equals(chip1)
522: && board.getFieldAt(VGPosition.of(j + 1, i + 1)).getState()
523:• .equals(chip2)
524: && board.getFieldAt(VGPosition.of(j + 2, i + 2)).getState()
525:• .equals(chip3)
526: && board.getFieldAt(VGPosition.of(j + 3, i + 3)).getState()
527:• .equals(chip4)) {
528: return true;
529: }
530: }
531: }
532: return false;
533:
534: }
535:
536: /**
537: * checks diagonle down right to up left.
538: *
539: * @param board
540: * @param chip1
541: * @param chip2
542: * @param chip3
543: * @param chip4
544: * @return
545: */
546: private Boolean checkDiagonaleDownRightUpLeftght(final VGBoard board, final VGFieldState chip1,
547: final VGFieldState chip2, final VGFieldState chip3, final VGFieldState chip4) {
548: for (int i = 0; i < 3; i++) {
549: for (int j = 3; j < 7; j++) {
550: if (board.getFieldAt(VGPosition.of(j, i)).getState().equals(chip1)
551: && board.getFieldAt(VGPosition.of(j - 1, i + 1)).getState()
552: .equals(chip2)
553: && board.getFieldAt(VGPosition.of(j - 2, i + 2)).getState()
554: .equals(chip3)
555: && board.getFieldAt(VGPosition.of(j - 3, i + 3)).getState()
556: .equals(chip4)) {
557: return true;
558: }
559: }
560: }
561:
562: return false;
563: }
564:
565: }