-
Notifications
You must be signed in to change notification settings - Fork 0
/
BoterKaasEieren.java
245 lines (186 loc) · 7.02 KB
/
BoterKaasEieren.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
package nl.hanze.itann.ttt;
// deze import hebben we nodig voor gebruikersinput – let daar maar niet op.
import java.util.Scanner;
/*
EEN EXTRA VOORBEELD BIJ §7.6 VAN BLUEJ EDITIE 6: MULTI-DIMENSIONALE ARRAYS;
Een multi-dimensionale array kun je het beste vergelijken met een spelbord. Dit is meestal een
systeem waarbij coördinaten als (X,Y) kunnen worden weergegeven – denk aan een schaakbord waarbij
je de positie van stukken weergeeft als bijvoorbeeld 'H3'.
Om dit om een wat eenvoudiger manier duidelijk te maken, is onderstaand spel 'boter kaas en eieren'
uitgeprogrammeerd. Dit heeft een bord als volgt:
+------+------+------+
| (0,0 | (1,0 | (2,0 |
+------+------+------+
| (0,1 | (1,1 | (2,1 |
+------+------+------+
| (0,2 | (1,2 | (2,2 |
+------+------+------+
Je ziet hier twee arrays lopen: één voor de X en één voor de Y. Beide lopen van 0 tot 2
(drie elementen). In de code wordt dit in het private veld 'board' bijgehouden, waarvan
het data-type een twee-dimensionale array van char's is:
private char[3][3] board
^ ^
| |
X ----------- --------Y
Je kunt dit spel spelen door het op te starten en dan de coördinaten in te vullen wanneer het
programma daar om vraagt: als ik bijvoorbeeld een X wil zetten op het rechtsmiddelste vakje, typ
ik 2,1 (zonder haakjes).
Er is een minimale check op de input, want het gaat niet om een correcte werking; als het stuk
gaat door een verkeerde input kun je vast wel bedenken waarom.
Bestudeer de programmacode en het commentaar dat er tussendoor gegeven is.
*/
public class BoterKaasEieren {
public static void main(String[] args) {
new BoterKaasEieren();
}
// Dit is het interessante veld. Een twee-dimensionale array die het speelveld bijhoudt.
private char[][] board;
// De huidige speler. Dit is ofwel een 'X' of een 'O'
private char currentPlayerMark;
//constructor
public BoterKaasEieren() {
board = new char[3][3];
currentPlayerMark = 'X';
initializeBoard();
playGame();
}
// Dit is feitelijk de 'main loop'. Dit ding blijft lopen totdat het bord vol is
// of er een winnaar is.
private void playGame() {
//De regels hieronder is om user-input op te vangen. Maak je daar niet druk om.
//Van belang is dat de input wordt opgeslagen in de variable 'input'.
Scanner reader = new Scanner(System.in);
String input = "";
//De onderstaande loop wordt uitgevoerd zolang 'gameNotFinished' geen 'false'
//teruggeeft (hoe heet zo'n conditie?). Dat kan omdat er in die loop een methode
//wordt aangeroepen die de boel blokkeert tot iemand een input heeft gegeven.
while (gameNotFinished()) {
//we printen elke keer de nieuwe status van het speelbord even uit
printBoard();
changePlayer();
// Hier geven we aan wie er aan de beurt is en wat hij/zij moet invullen.
System.out.println("De beurt in aan "+currentPlayerMark);
System.out.println("Geef positie op (x,y): ");
//Deze methode blijft wachten totdat de gebruiker iets heeft ingeveoerd.
//Hierom kunnen we deze loop laten blijven lopen zonder dat er continu
//dingen op het scherm verschijnen.
input = reader.next();
//We maken een array van Strings van de input – check de API van de string:
// https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String)
String[] coords = input.split(",");
placeMark(coords);
}
// Even het winnende bord afdrukken
printBoard();
//als we hier komen, hebben we die reader niet meer nodig, en het is wel netjes om
//die even expliciet te sluiten.
reader.close();
}
private boolean placeMark(String[] coords) {
//We gaan er even van uit dat er in de input twee getallen zijn gegeven.
int col = Integer.parseInt(coords[0]);
int row = Integer.parseInt(coords[1]);
//Let op hoe we opnieuw door een twee-dimensionale array lopen
if ((row >= 0) && (row < 3)) {
if ((col >= 0) && (col < 3)) {
if (board[row][col] == '-') {
board[row][col] = currentPlayerMark;
return true;
}
}
}
return false;
}
//Hier initialiseren we de twee-dimensionale array. We hebben dus twee for-lussen nodig:
//voor elke array eentje. De variabel i loopt van 0 tot 2, net als de variabele j (dat
//klopt ook, want we hebben dat ding geïnitialiseerd op char[3][3]).
private void initializeBoard() {
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
board[i][j] = '-'; // initieel is elk element een '-'
}
}
//Even voor het gemak de exacte coördinaten weergeven
printBoardCoords();
}
private void changePlayer() {
// hoe heet deze constructie?
currentPlayerMark = (currentPlayerMark=='X') ? 'O' : 'X';
}
private boolean gameNotFinished() {
return !(isBoardFull() || checkForWin());
}
private void printBoard() {
System.out.println("+---+---+---+");
for (int i = 0; i < 3; i++) {
System.out.print("| ");
for (int j = 0; j < 3; j++) {
System.out.print(board[i][j] + " | ");
}
System.out.println();
System.out.println("+---+---+---+");
}
}
private void printBoardCoords() {
System.out.println("Vul de coördinaten in zonder haakjes, gescheiden door een komma.");
System.out.println("De coördinaten in het bord zijn als volgt:");
System.out.println("+-------+-------+-------+");
for (int i = 0; i < 3; i++) {
System.out.print("| ");
for (int j = 0; j < 3; j++) {
System.out.print("(" +j+","+i + ") | ");
}
System.out.println();
System.out.println("+-------+-------+-------+");
}
}
//Opnieuw hebben we hier een dubbele for-lus nodig, om door beide arrays heen te
//loopen. We checken hier nu voor elk element wat er exact is zit, en als er nog ergens
//een '-' voorkomt, is het bord nog niet vol (want initieel hebben we het bord volgezet
//met een '-', in de methode initializeBoard)
private boolean isBoardFull() {
boolean isFull = true;
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
if (board[i][j] == '-') {
isFull = false; //welke optimalisatie is hier nog mogelijk?
}
}
}
if (isFull) {
System.out.println("Het bord is vol; eind van het spel.");
return true;
}
return false;
}
// voor de rest: nevermind
private boolean checkForWin() {
if (checkRowsForWin() || checkColumnsForWin() || checkDiagonalsForWin()) {
System.out.println("We hebben een winnaar: " +currentPlayerMark);
return true;
}
return false;
}
private boolean checkRowsForWin() {
for (int i = 0; i < 3; i++) {
if (checkRowCol(board[i][0], board[i][1], board[i][2]) == true) {
return true;
}
}
return false;
}
private boolean checkColumnsForWin() {
for (int i = 0; i < 3; i++) {
if (checkRowCol(board[0][i], board[1][i], board[2][i]) == true) {
return true;
}
}
return false;
}
private boolean checkDiagonalsForWin() {
return ((checkRowCol(board[0][0], board[1][1], board[2][2]) == true) || (checkRowCol(board[0][2], board[1][1], board[2][0]) == true));
}
private boolean checkRowCol(char c1, char c2, char c3) {
return ((c1 != '-') && (c1 == c2) && (c2 == c3));
}
}