
Β«ΠΠ΅ΡΠ½Π°Π΄Π΅ΡΠ΅ΡΒ», ΠΈΠ»ΠΈ Β«ΠΡΡΠ½Π°ΡΠΊΠ°Β» β ΠΎΡΠ»ΠΈΡΠ΅Π½ ΠΏΡΠΈΠΌΠ΅Ρ Π·Π° ΠΏΡΠΎΡΡΠ° Π»ΠΎΠ³ΠΈΡΠ΅ΡΠΊΠ° ΠΈΠ³ΡΠ°, ΠΏΠΎΠΏΡΠ»ΡΡΠ½Π° Π² ΡΠ΅Π»ΠΈΡ ΡΠ²ΡΡ. ΠΠ° Π΄Π° ΡΠ΅ ΡΠ΅ΡΠΈ ΠΏΡΠ·Π΅Π»ΡΡ, Π΅ Π½Π΅ΠΎΠ±Ρ
ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° ΡΠ΅ ΠΏΠΎΠ΄ΡΠ΅Π΄ΡΡ ΠΊΠ²Π°Π΄ΡΠ°ΡΠΈΡΠ΅ Ρ ΡΠΈΡΠ»Π° ΠΏΠΎ ΡΠ΅Π΄, ΠΎΡ ΠΏΠΎ-ΠΌΠ°Π»ΠΊΠΎΡΠΎ ΠΊΡΠΌ ΠΏΠΎ-Π³ΠΎΠ»ΡΠΌΠΎΡΠΎ. Π’ΠΎΠ²Π° Π½Π΅ Π΅ Π»Π΅ΡΠ½ΠΎ, Π½ΠΎ Π΅ ΠΈΠ½ΡΠ΅ΡΠ΅ΡΠ½ΠΎ.
Π Π΄Π½Π΅ΡΠ½ΠΈΡ ΡΡΠΎΠΊ ΠΏΠΎΠΊΠ°Π·Π²Π°ΠΌΠ΅ ΠΊΠ°ΠΊ Π΄Π° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΈΠΌ Β«ΠΡΡΠ½Π°ΡΠΊΠ°Β» Π½Π° Java 8 Ρ Eclipse. ΠΠ° ΡΠ°Π·ΡΠ°Π±ΠΎΡΠΊΠ° Π½Π° UI ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Swing API.
ΠΠ°ΠΏΠΎΠΌΠ½ΡΠΌΠ΅: Π·Π° Π²ΡΠΈΡΠΊΠΈ ΡΠΈΡΠ°ΡΠ΅Π»ΠΈ Π½Π° Β«Π₯Π°Π±ΡΠ°Β» β ΠΎΡΡΡΡΠΏΠΊΠ° ΠΎΡ 10 000 ΡΡΠ±Π»ΠΈ ΠΏΡΠΈ Π·Π°ΠΏΠΈΡΠ²Π°Π½Π΅ Π½Π° Π²ΡΠ΅ΠΊΠΈ ΠΊΡΡΡ Skillbox Ρ ΠΏΡΠΎΠΌΠΎΠΊΠΎΠ΄ Β«Π₯Π°Π±ΡΒ».
Skillbox ΠΏΡΠ΅ΠΏΠΎΡΡΡΠ²Π°: ΠΠ±ΡΠ°Π·ΠΎΠ²Π°ΡΠ΅Π»Π΅Π½ ΠΎΠ½Π»Π°ΠΉΠ½ ΠΊΡΡΡ .
ΠΠΈΠ·Π°ΠΉΠ½ Π½Π° ΠΈΠ³ΡΠ°ΡΠ°
ΠΠ° ΡΠΎΠ·ΠΈ Π΅ΡΠ°ΠΏ Π΅ Π½ΡΠΆΠ½ΠΎ Π΄Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ ΡΠ²ΠΎΠΉΡΡΠ²Π°ΡΠ°:
- Size β ΡΠ°Π·ΠΌΠ΅Ρ Π½Π° ΠΈΠ³ΡΠ°Π»Π½ΠΎΡΠΎ ΠΏΠΎΠ»Π΅;
- nbTiles β Π±ΡΠΎΠΉ Π½Π° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠΈΡΠ΅ Π½Π° ΠΏΠΎΠ»Π΅ΡΠΎ. nbTiles = size*size β 1;
- Tiles β ΠΏΠ΅ΡΠ½Π°ΡΠΊa, ΠΏΡΠ΅Π΄ΡΡΠ°Π²Π»ΡΠ²Π°ΡΠ° Π΅Π΄Π½ΠΎΠΌΠ΅ΡΠ΅Π½ ΠΌΠ°ΡΠΈΠ² ΠΎΡ ΡΠ΅Π»ΠΈ ΡΠΈΡΠ»Π°. ΠΡΡΠΊΠ° ΠΎΡ ΠΏΠ΅ΡΠ½Π°ΡΠΊΠΈΡΠ΅ ΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈ ΡΠ½ΠΈΠΊΠ°Π»Π½Π° ΡΡΠΎΠΉΠ½ΠΎΡΡ Π² Π΄ΠΈΠ°ΠΏΠ°Π·ΠΎΠ½Π° [0, nbTiles]. ΠΡΠ»Π°ΡΠ° ΠΎΠ±ΠΎΠ·Π½Π°ΡΠ°Π²Π° ΠΏΡΠ°Π·Π΅Π½ ΠΊΠ²Π°Π΄ΡΠ°Ρ;
- blankPos β ΠΏΠΎΠ·ΠΈΡΠΈΡ Π½Π° ΠΏΡΠ°Π·Π½ΠΈΡ ΠΊΠ²Π°Π΄ΡΠ°Ρ.
ΠΠΎΠ³ΠΈΠΊΠ° Π½Π° ΠΈΠ³ΡΠ°ΡΠ°
ΠΡΠΆΠ½ΠΎ Π΅ Π΄Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ ΠΌΠ΅ΡΠΎΠ΄ Π·Π° Π½ΡΠ»ΠΈΡΠ°Π½Π΅ (reset), ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°Π½ Π·Π° ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½Π΅ Π½Π° Π½ΠΎΠ²Π° ΠΈΠ³ΡΠΎΠ²Π° ΠΏΠΎΠ·ΠΈΡΠΈΡ. Π’Π°ΠΊΠ° Π·Π°Π΄Π°Π²Π°ΠΌΠ΅ ΡΡΠΎΠΉΠ½ΠΎΡΡ Π·Π° Π²ΡΠ΅ΠΊΠΈ Π΅Π»Π΅ΠΌΠ΅Π½Ρ ΠΎΡ ΠΌΠ°ΡΠΈΠ²Π° Π½Π° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠΈΡΠ΅. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° ΠΏΠΎΡΡΠ°Π²ΡΠΌΠ΅ blankPos Π² ΠΏΠΎΡΠ»Π΅Π΄Π½Π°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ Π½Π° ΠΌΠ°ΡΠΈΠ²Π°.
Π‘ΡΡΠΎ ΡΠ°ΠΊΠ° Π΅ Π½ΡΠΆΠ΅Π½ ΠΌΠ΅ΡΠΎΠ΄ shuffle Π·Π° ΡΠ°Π·Π±ΡΡΠΊΠ²Π°Π½Π΅ Π½Π° ΠΌΠ°ΡΠΈΠ²Π° Π½Π° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠΈΡΠ΅. ΠΠ΅ Π²ΠΊΠ»ΡΡΠ²Π°ΠΌΠ΅ ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠ° Π² ΠΏΡΠΎΡΠ΅ΡΠ° Π½Π° ΡΠ°Π·Π±ΡΡΠΊΠ²Π°Π½Π΅, Π·Π° Π΄Π° Ρ ΠΎΡΡΠ°Π²ΠΈΠΌ Π½Π° ΠΏΡΠ΅Π΄ΠΈΡΠ½Π°ΡΠ° Ρ ΠΏΠΎΠ·ΠΈΡΠΈΡ.
Π’ΡΠΉ ΠΊΠ°ΡΠΎ ΡΠ°ΠΌΠΎ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°ΡΠ° ΠΎΡ Π²ΡΠ·ΠΌΠΎΠΆΠ½ΠΈΡΠ΅ ΡΡΠ°ΡΡΠΎΠ²ΠΈ ΠΏΠΎΠ·ΠΈΡΠΈΠΈ Π½Π° ΠΏΡΠ·Π΅Π»Π° ΠΈΠΌΠ°Ρ ΡΠ΅ΡΠ΅Π½ΠΈΠ΅, Π΅ Π½ΡΠΆΠ½ΠΎ Π΄Π° ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ ΠΏΠΎΠ»ΡΡΠ΅Π½ΠΈΡ ΡΠ΅Π·ΡΠ»ΡΠ°Ρ ΠΎΡ ΡΠ°Π·Π±ΡΡΠΊΠ²Π°Π½Π΅ΡΠΎ, Π·Π° Π΄Π° ΡΠΌΠ΅ ΡΠΈΠ³ΡΡΠ½ΠΈ, ΡΠ΅ ΡΠ΅ΠΊΡΡΠΎΡΠΎ ΡΠ°Π·ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ ΠΈΠ·ΠΎΠ±ΡΠΎ Π΅ ΡΠ°Π·ΡΠ΅ΡΠΈΠΌΠΎ. ΠΠ° ΡΠΎΠ²Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΡΠΌΠ΅ ΠΌΠ΅ΡΠΎΠ΄Π° isSolvable.
ΠΠΊΠΎ ΠΊΠΎΠ½ΠΊΡΠ΅ΡΠ½Π° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠ° Π΅ ΠΏΡΠ΅Π΄ΡΠ΅ΡΡΠ²Π°Π½Π° ΠΎΡ ΠΏΠ΅ΡΠ½Π°ΡΠΊΠ° Ρ ΠΏΠΎ-Π²ΠΈΡΠΎΠΊΠ° ΡΡΠΎΠΉΠ½ΠΎΡΡ, ΡΠΎΠ²Π° ΡΠ΅ ΡΡΠΈΡΠ° Π·Π° ΠΈΠ½Π²Π΅ΡΡΠΈΡ. ΠΠΎΠ³Π°ΡΠΎ ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠ° Π΅ Π½Π° ΡΠ²ΠΎΠ΅ΡΠΎ ΠΌΡΡΡΠΎ, Π±ΡΠΎΠΉΠΊΠ°ΡΠ° Π½Π° ΠΈΠ½Π²Π΅ΡΡΠΈΠΈΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° Π΅ ΡΠ΅ΡΠ½Π°, Π·Π° Π΄Π° Π±ΡΠ΄Π΅ ΠΏΡΠ·Π΅Π»ΡΡ ΡΠ°Π·ΡΠ΅ΡΠΈΠΌ. Π’Π°ΠΊΠ° ΡΠ΅, Π±ΡΠΎΠΈΠΌ ΠΈΠ½Π²Π΅ΡΡΠΈΠΈΡΠ΅ ΠΈ Π²ΡΡΡΠ°ΠΌΠ΅ true, Π°ΠΊΠΎ ΡΠΈΡΠ»ΠΎΡΠΎ Π΅ ΡΠ΅ΡΠ½ΠΎ.
Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° Π΅ Π²Π°ΠΆΠ½ΠΎ Π΄Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ ΠΌΠ΅ΡΠΎΠ΄Π° isSolved, Π·Π° Π΄Π° ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ Π΄Π°Π»ΠΈ Π½Π°ΡΠ΅ΡΠΎ ΡΠ°Π·ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Game Of Fifteen Π΅ ΡΠ΅ΡΠ΅Π½ΠΎ. ΠΡΡΠ²ΠΎ Π³Π»Π΅Π΄Π°ΠΌΠ΅ ΠΊΡΠ΄Π΅ ΡΠ΅ Π½Π°ΠΌΠΈΡΠ° ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠ°. ΠΠΊΠΎ Π΅ Π² Π½Π°ΡΠ°Π»Π½Π°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ, ΡΠ΅ΠΊΡΡΠΎΡΠΎ ΡΠ°Π·ΠΏΠΎΠ»ΠΎΠΆΠ΅Π½ΠΈΠ΅ Π΅ Π½ΠΎΠ²ΠΎ, ΠΊΠΎΠ΅ΡΠΎ Π½Π΅ Π΅ ΡΠ°Π·ΡΠ΅ΡΠ°Π²Π°Π½ΠΎ ΠΏΡΠ΅Π΄ΠΈ. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° ΠΎΠ±ΠΈΠΊΠ°Π»ΡΠΌΠ΅ ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅ Π² ΠΎΠ±ΡΠ°ΡΠ΅Π½ ΡΠ΅Π΄ ΠΈ, Π°ΠΊΠΎ ΡΡΠΎΠΉΠ½ΠΎΡΡΡΠ° Π½Π° ΠΏΠ΅ΡΠ½Π°ΡΠΊΠ°ΡΠ° ΡΠ΅ ΡΠ°Π·Π»ΠΈΡΠ°Π²Π° ΠΎΡ ΡΡΠΎΡΠ²Π΅ΡΠ½ΠΈΡ ΠΈΠ½Π΄Π΅ΠΊΡ +1, Π²ΡΡΡΠ°ΠΌΠ΅ false. Π ΠΏΡΠΎΡΠΈΠ²Π΅Π½ ΡΠ»ΡΡΠ°ΠΉ, Π² ΠΊΡΠ°Ρ Π½Π° ΠΌΠ΅ΡΠΎΠ΄Π° Π΅ Π²ΡΠ΅ΠΌΠ΅ Π΄Π° Π²ΡΡΠ½Π΅ΠΌ true, ΡΡΠΉ ΠΊΠ°ΡΠΎ ΠΏΡΠ·Π΅Π»ΡΡ Π²Π΅ΡΠ΅ Π΅ ΡΠ΅ΡΠ΅Π½.
ΠΡΠ΅ Π΅Π΄ΠΈΠ½ ΠΌΠ΅ΡΠΎΠ΄, ΠΊΠΎΠΉΡΠΎ ΡΡΡΠ±Π²Π° Π΄Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈ, Π΅ newGame. Π’ΠΎΠΉ Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌ Π·Π° ΡΡΠ·Π΄Π°Π²Π°Π½Π΅ Π½Π° Π½ΠΎΠ²Π° ΠΈΠ½ΡΡΠ°Π½ΡΠΈΡ Π½Π° ΠΈΠ³ΡΠ°ΡΠ°. ΠΠ° ΡΠ΅Π»ΡΠ° Π½ΠΈΠ΅ Π½ΡΠ»ΠΈΡΠ°ΠΌΠ΅ ΠΈΠ³ΡΠΎΠ²ΠΎΡΠΎ ΠΏΠΎΠ»Π΅, ΡΠ»Π΅Π΄ ΠΊΠΎΠ΅ΡΠΎ Π³ΠΎ ΡΠ°Π·Π±ΡΡΠΊΠ²Π°ΠΌΠ΅ ΠΈ ΠΏΡΠΎΠ΄ΡΠ»ΠΆΠ°Π²Π°ΠΌΠ΅, Π΄ΠΎΠΊΠ°ΡΠΎ ΠΈΠ³ΡΠΎΠ²Π°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ Π½Π΅ ΡΡΠ°Π½Π΅ ΡΠ°Π·ΡΠ΅ΡΠΈΠΌΠ°.
ΠΡΠΎ ΠΏΡΠΈΠΌΠ΅Ρ Π·Π° ΠΊΠΎΠ΄ Ρ ΠΊΠ»ΡΡΠΎΠ²Π°ΡΠ° Π»ΠΎΠ³ΠΈΠΊΠ° Π½Π° ΠΏΠ΅ΡΠ°Π½ΠΊΠΈΡΠ΅:
private void newGame() {
do {
reset(); // Π½ΡΠ»ΠΈΡΠ°Π½Π΅ Π² Π½Π°ΡΠ°Π»Π½ΠΎ ΡΡΡΡΠΎΡΠ½ΠΈΠ΅
shuffle(); // ΡΠ°Π·Π±ΡΡΠΊΠ²Π°Π½Π΅
} while(!isSolvable()); // ΠΏΡΠ°Π²ΠΈΠΌ Π³ΠΎ, Π΄ΠΎΠΊΠ°ΡΠΎ ΠΌΡΠ΅ΠΆΠ°ΡΠ° ΡΡΠ°Π½Π΅ ΡΠ°Π·ΡΠ΅ΡΠΈΠΌΠ°
gameOver = false;
}
private void reset() {
for (int i = 0; i 1) {
int r = RANDOM.nextInt(n--);
int tmp = tiles[r];
tiles[r] = tiles[n];
tiles[n] = tmp;
}
}
// Π‘Π°ΠΌΠΎ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°ΡΠ° ΠΎΡ ΠΏΠ΅ΡΠΌΡΡΠ°ΡΠΈΠΈΡΠ΅ Π½Π° ΠΏΡΠ·Π΅Π»Π° ΡΠ° ΡΠ°Π·ΡΠ΅ΡΠΈΠΌΠΈ/
// ΠΡΡΠΊΠ° ΠΏΡΡΠΊΠ°, ΠΊΠΎΡΡΠΎ Π΅ ΠΏΡΠ΅Π΄ΡΠ΅ΡΡΠ²Π°Π½Π° ΠΎΡ ΠΏΡΡΠΊΠ° Ρ ΠΏΠΎ-Π²ΠΈΡΠΎΠΊΠ° ΡΡΠΎΠΉΠ½ΠΎΡΡ, ΡΠ΅ Π±ΡΠΎΠΈ
// ΠΊΠ°ΡΠΎ ΠΈΠ½Π²Π΅ΡΡΠΈΡ. Π Π½Π°ΡΠΈΡ ΡΠ»ΡΡΠ°ΠΉ, Ρ ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ»ΠΎΡΠΊΠ° Π² ΡΠ°Π·ΡΠ΅ΡΠ΅Π½Π°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ,
// Π±ΡΠΎΡΡ Π½Π° ΠΈΠ½Π²Π΅ΡΡΠΈΠΈΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° Π΅ ΡΠ΅ΡΠ΅Π½, Π·Π° Π΄Π° Π΅ ΠΏΡΠ·Π΅Π»ΡΡ ΡΠ°Π·ΡΠ΅ΡΠΈΠΌ
private boolean isSolvable() {
int countInversions = 0;
for (int i = 0; i < nbTiles; i++) {
for (int j = 0; j tiles[i])
countInversions++;
}
}
return countInversions % 2 == 0;
}
private boolean isSolved() {
if (tiles[tiles.length - 1] != 0) // Π°ΠΊΠΎ ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ»ΠΎΡΠΊΠ° Π½Π΅ Π΅ Π² ΡΠ°Π·ΡΠ΅ΡΠ΅Π½Π°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ ==> Π½Π΅ Π΅ ΡΠ΅ΡΠ΅Π½
return false;
for (int i = nbTiles - 1; i >= 0; i--) {
if (tiles[i] != i + 1)
return false;
}
return true;
}ΠΠ°ΠΊΡΠ°Ρ ΡΡΡΠ±Π²Π° Π΄Π° ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΈΡΠ°ΠΌΠ΅ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ Π½Π° ΠΏΠ΅ΡΠ°Π½ΠΊΠΈΡΠ΅ Π² ΠΌΠ°ΡΠΈΠ²Π°. Π’ΠΎΠ·ΠΈ ΠΊΠΎΠ΄ ΡΠ΅ Π±ΡΠ΄Π΅ ΠΈΠ·Π²ΠΈΠΊΠ°Π½ ΠΏΠΎ-ΠΊΡΡΠ½ΠΎ ΡΡΠ΅Π· ΠΎΠ±ΡΠ°ΡΠ΅Π½ ΠΏΠΎΠ²ΠΈΠΊ (callback), Π·Π° Π΄Π° ΡΠ΅Π°Π³ΠΈΡΠ° Π½Π° Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ΡΠΎ Π½Π° ΠΊΡΡΡΠΎΡΠ°. ΠΠ°ΡΠ°ΡΠ° ΠΈΠ³ΡΠ° ΡΠ΅ ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ° ΠΌΠ½ΠΎΠ³ΠΎΠ±ΡΠΎΠΉΠ½ΠΈ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈ Π΅Π΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ. Π‘Π»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»Π½ΠΎ, ΡΠ»Π΅Π΄ ΠΊΠ°ΡΠΎ ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠ°ΠΌΠ΅ Π½Π°ΡΠΈΡΠ½Π°ΡΠ°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ Π½Π° Π΅ΠΊΡΠ°Π½Π° Π² ΠΏΠ΅ΡΠ°Π½ΠΊΠ°, ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΡΡΠ° Π½Π° ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ΅ΡΠ°Π½ΠΊΠ° ΠΈ ΡΡΡΡΠΈΠΌ ΠΏΠΎΡΠΎΠΊΠ°ΡΠ° Π½Π° Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅, Π·Π° Π΄Π° ΠΏΠΎΠ΄Π΄ΡΡΠΆΠ°ΠΌΠ΅ ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ Π½Π΅ΠΉΠ½ΠΈ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ Π΅Π΄Π½ΠΎΠ²ΡΠ΅ΠΌΠ΅Π½Π½ΠΎ.
ΠΡΠΎ ΠΏΡΠΈΠΌΠ΅Ρ Π·Π° ΠΊΠΎΠ΄:
// get position of the click
int ex = e.getX() - margin;
int ey = e.getY() - margin;
// click in the grid ?
if (ex < 0 || ex > gridSize || ey < 0 || ey > gridSize)
return;
// get position in the grid
int c1 = ex / tileSize;
int r1 = ey / tileSize;
// get position of the blank cell
int c2 = blankPos % size;
int r2 = blankPos / size;
// we convert in the 1D coord
int clickPos = r1 * size + c1;
int dir = 0;
// we search direction for multiple tile moves at once
if (c1 == c2 && Math.abs(r1 - r2) > 0)
dir = (r1 - r2) > 0 ? size : -size;
else if (r1 == r2 && Math.abs(c1 - c2) > 0)
dir = (c1 - c2) > 0 ? 1 : -1;
if (dir != 0) {
// we move tiles in the direction
do {
int newBlankPos = blankPos + dir;
tiles[blankPos] = tiles[newBlankPos];
blankPos = newBlankPos;
} while(blankPos != clickPos);
tiles[blankPos] = 0;Π Π°Π·ΡΠ°Π±ΠΎΡΠ²Π°ΠΌΠ΅ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ Π½Π° Swing API
Π‘Π΅Π³Π° Π΅ Π²ΡΠ΅ΠΌΠ΅ Π΄Π° ΡΠ΅ Π·Π°Π½ΠΈΠΌΠ°Π΅ΠΌ Ρ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°. ΠΡΡΠ²ΠΎ Π²Π·Π΅ΠΌΠ°ΠΌΠ΅ ΠΊΠ»Π°ΡΠ° Jpanel. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° ΡΠΈΡΡΠ²Π°ΠΌΠ΅ ΠΏΠ΅ΡΠ°Π½ΠΊΠΈΡΠ΅ Π½Π° ΠΏΠΎΠ»Π΅ΡΠΎ - Π·Π° Π΄Π° ΠΈΠ·ΡΠΈΡΠ»ΠΈΠΌ ΡΠ°Π·ΠΌΠ΅ΡΠΈΡΠ΅ Π½Π° Π²ΡΡΠΊΠ°, ΡΠ΅ ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ Π΄Π°Π½Π½ΠΈΡΠ΅, Π·Π°Π΄Π°Π΄Π΅Π½ΠΈ Π² ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡΠ° Π½Π° ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ° Π½Π° ΠΈΠ³ΡΠ°ΡΠ°:
gridSize = (dim - 2 * margin);
tileSize = gridSize / size;Margin ΡΡΡΠΎ Π΅ ΠΏΠ°ΡΠ°ΠΌΠ΅ΡΡΡ, Π·Π°Π΄Π°Π΄Π΅Π½ Π² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ° Π½Π° ΠΈΠ³ΡΠ°ΡΠ°.
Π‘Π΅Π³Π° ΡΡΡΠ±Π²Π° Π΄Π° ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ ΠΌΠ΅ΡΠΎΠ΄Π° drawGrid Π·Π° ΡΠΈΡΡΠ²Π°Π½Π΅ Π½Π° ΠΌΡΠ΅ΠΆΠ°ΡΠ° ΠΈ ΠΏΠ΅ΡΠ°Π½ΠΊΠΈΡΠ΅ Π½Π° Π΅ΠΊΡΠ°Π½Π°. ΠΠ½Π°Π»ΠΈΠ·ΠΈΡΠ°ΠΌΠ΅ ΠΌΠ°ΡΠΈΠ²Π° Π½Π° ΠΏΠ΅ΡΠ°Π½ΠΊΠΈΡΠ΅ ΠΈ ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠ°ΠΌΠ΅ ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈΡΠ΅ Π² ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈ Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΡΠΊΠΈΡ ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡ. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° ΡΠ΅ Π½Π°ΡΠΈΡΡΠ²Π°ΠΌΠ΅ Π²ΡΡΠΊΠ° ΠΏΠ΅ΡΠ°Π½ΠΊΠ° ΡΡΡ ΡΡΠΎΡΠ²Π΅ΡΠ½ΠΈΡ Π½ΠΎΠΌΠ΅Ρ Π² ΡΠ΅Π½ΡΡΡΠ°:
private void drawGrid(Graphics2D g) {
for (int i = 0; i < tiles.length; i++) {
// ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠ°ΠΌΠ΅ 1D ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈ Π² 2D ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈ Π½Π° Π±Π°Π·Π°ΡΠ° Π½Π° ΡΠ°Π·ΠΌΠ΅ΡΠ° Π½Π° 2D ΠΌΠ°ΡΠΈΠ²Π°
int r = i / size;
int c = i % size;
// ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠ°ΠΌΠ΅ Π² ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈ Π½Π° ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°
int x = margin + c * tileSize;
int y = margin + r * tileSize;
// ΠΏΡΠΎΠ²Π΅ΡΠΊΠ° Π·Π° ΡΠΏΠ΅ΡΠΈΠ°Π»Π΅Π½ ΡΠ»ΡΡΠ°ΠΉ Ρ ΠΏΡΠ°Π·Π½Π° ΠΏΠ»ΠΎΡΠΊΠ°
if(tiles[i] == 0) {
if (gameOver) {
g.setColor(FOREGROUND_COLOR);
drawCenteredString(g, "u2713", x, y);
}
continue;
}
// Π·Π° Π΄ΡΡΠ³ΠΈΡΠ΅ ΠΏΠ»ΠΎΡΠΊΠΈ
g.setColor(getForeground());
g.fillRoundRect(x, y, tileSize, tileSize, 25, 25);
g.setColor(Color.BLACK);
g.drawRoundRect(x, y, tileSize, tileSize, 25, 25);
g.setColor(Color.WHITE);
drawCenteredString(g, String.valueOf(tiles[i]), x , y);
}
}ΠΠ°ΠΊΡΠ°Ρ, ΡΠ΅ ΠΏΡΠ΅ΠΎΠΏΡΠ΅Π΄Π΅Π»ΠΈΠΌ ΠΌΠ΅ΡΠΎΠ΄Π° paintComponent, ΠΊΠΎΠΉΡΠΎ ΠΏΡΠΎΠΈΠ·Π»ΠΈΠ·Π° ΠΎΡ ΠΊΠ»Π°ΡΠ° JPane. Π‘Π»Π΅Π΄ ΡΠΎΠ²Π° ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΌΠ΅ΡΠΎΠ΄Π° drawGrid ΠΈ ΡΠ»Π΅Π΄ Π½Π΅Π³ΠΎ β ΠΌΠ΅ΡΠΎΠ΄Π° drawStartMessage, Π·Π° Π΄Π° ΠΏΠΎΠΊΠ°ΠΆΠ΅ΠΌ ΡΡΠΎΠ±ΡΠ΅Π½ΠΈΠ΅, ΠΊΠΎΠ΅ΡΠΎ ΠΏΡΠ΅Π΄Π»Π°Π³Π° ΠΊΠ»ΠΈΠΊΠ²Π°Π½Π΅ Π·Π° ΡΡΠ°ΡΡΠΈΡΠ°Π½Π΅ Π½Π° ΠΈΠ³ΡΠ°ΡΠ°:
private void drawStartMessage(Graphics2D g) {
if (gameOver) {
g.setFont(getFont().deriveFont(Font.BOLD, 18));
g.setColor(FOREGROUND_COLOR);
String s = "ΠΠ»ΠΈΠΊΠ½Π΅ΡΠ΅, Π·Π° Π΄Π° ΡΡΠ°ΡΡΠΈΡΠ°ΡΠ΅ Π½ΠΎΠ²Π° ΠΈΠ³ΡΠ°";
g.drawString(s, (getWidth() - g.getFontMetrics().stringWidth(s)) / 2,
getHeight() - margin);
}
}
private void drawCenteredString(Graphics2D g, String s, int x, int y) {
// ΡΠ΅Π½ΡΡΠΈΡΠ°ΠΌΠ΅ Π½ΠΈΠ· s Π·Π° Π΄Π°Π΄Π΅Π½Π°ΡΠ° ΠΏΠ»ΠΎΡΠΊΠ° (x,y)
FontMetrics fm = g.getFontMetrics();
int asc = fm.getAscent();
int desc = fm.getDescent();
g.drawString(s, x + (tileSize - fm.stringWidth(s)) / 2,
y + (asc + (tileSize - (asc + desc)) / 2));
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g;
g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
drawGrid(g2D);
drawStartMessage(g2D);
}Π Π΅Π°Π³ΠΈΡΠ°ΠΌΠ΅ Π½Π° Π΄Π΅ΠΉΡΡΠ²ΠΈΡΡΠ° Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»Ρ Π² ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°
ΠΠ° Π΄Π° ΠΈΠ³ΡΠ°ΡΠ° ΠΏΡΠΎΡΠΈΡΠ° Π½ΠΎΡΠΌΠ°Π»Π½ΠΎ, Π΅ Π½Π΅ΠΎΠ±Ρ ΠΎΠ΄ΠΈΠΌΠΎ Π΄Π° ΠΎΠ±ΡΠ°Π±ΠΎΡΠ²Π°ΠΌΠ΅ Π΄Π΅ΠΉΡΡΠ²ΠΈΡΡΠ° Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»Ρ Π² ΠΈΠ½ΡΠ΅ΡΡΠ΅ΠΉΡΠ°. ΠΠ° ΡΠ°Π·ΠΈ ΡΠ΅Π» Π΄ΠΎΠ±Π°Π²ΡΠΌΠ΅ ΠΈΠΌΠΏΠ»Π΅ΠΌΠ΅Π½ΡΠ°ΡΠΈΡ Π½Π° MouseListener Π² Jpanel ΠΈ ΠΊΠΎΠ΄ Π·Π° Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅, ΠΊΠΎΠΉΡΠΎ Π²Π΅ΡΠ΅ Π΅ ΠΏΠΎΠΊΠ°Π·Π°Π½ ΠΏΠΎ-Π³ΠΎΡΠ΅:
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΡΠ΅, Π·Π° Π΄Π° ΠΏΠΎΠ·Π²ΠΎΠ»ΠΈ Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅ Π΄Π° Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²Π°Ρ Ρ ΠΌΡΠ΅ΠΆΠ°ΡΠ° ΡΡΠ΅Π· ΠΊΠ»ΠΈΠΊΠ²Π°Π½Π΅
// Π²ΡΠ΅ΠΌΠ΅ Π΅ Π΄Π° ΡΠ΅Π°Π»ΠΈΠ·ΠΈΡΠ°ΠΌΠ΅ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Ρ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅ Π·Π° Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΠ΅ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅ Π·Π° ΡΠ΅ΡΠ°Π²Π°Π½Π΅ Π½Π° ΠΈΠ³ΡΠ°ΡΠ°!
if (gameOver) {
newGame();
} else {
// ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΡΡΠ° Π½Π° ΠΊΠ»ΠΈΠΊΠ°
int ex = e.getX() - margin;
int ey = e.getY() - margin;
// ΠΊΠ»ΠΈΠΊ Π² ΠΌΡΠ΅ΠΆΠ°ΡΠ°?
if (ex gridSize || ey gridSize)
return;
// ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΡΡΠ° Π² ΠΌΡΠ΅ΠΆΠ°ΡΠ°
int c1 = ex / tileSize;
int r1 = ey / tileSize;
// ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ ΠΏΠΎΠ·ΠΈΡΠΈΡΡΠ° Π½Π° ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΊΠ»Π΅ΡΠΊΠ°
int c2 = blankPos % size;
int r2 = blankPos / size;
// ΠΊΠΎΠ½Π²Π΅ΡΡΠΈΡΠ°ΠΌΠ΅ Π² 1D ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈ
int clickPos = r1 * size + c1;
int dir = 0;
// ΡΡΡΡΠΈΠΌ ΠΏΠΎΡΠΎΠΊΠ° Π·Π° ΠΌΠ½ΠΎΠ³ΠΎΠΊΡΠ°ΡΠ½ΠΈ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈ Π½Π°Π²Π΅Π΄Π½ΡΠΆ
if (c1 == c2 && Math.abs(r1 - r2) > 0)
dir = (r1 - r2) > 0 ? size : -size;
else if (r1 == r2 && Math.abs(c1 - c2) > 0)
dir = (c1 - c2) > 0 ? 1 : -1;
if (dir != 0) {
// Π΄Π²ΠΈΠΆΠΈΠΌ ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅ Π² ΠΏΠΎΡΠΎΠΊΠ°ΡΠ°
do {
int newBlankPos = blankPos + dir;
tiles[blankPos] = tiles[newBlankPos];
blankPos = newBlankPos;
} while(blankPos != clickPos);
tiles[blankPos] = 0;
}
// ΠΏΡΠΎΠ²Π΅ΡΡΠ²Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ ΠΈΠ³ΡΠ°ΡΠ° Π΅ ΡΠ΅ΡΠ΅Π½Π°
gameOver = isSolved();
}
// ΠΏΡΠ΅ΡΠΈΡΡΠ²Π°ΠΌΠ΅ ΠΏΠ°Π½Π΅Π»Π°
repaint();
}
});ΠΠΎΠ΄ΡΡ ΡΠ΅ ΠΏΠΎΡΡΠ°Π²Ρ Π² ΠΊΠΎΠ½ΡΡΡΡΠΊΡΠΎΡΠ° Π½Π° ΠΊΠ»Π°ΡΠ° GameOfFifteen. Π ΠΊΡΠ°Ρ Π½Π°ΠΊΡΠ°Ρ ΠΈΠ·Π²ΠΈΠΊΠ²Π°ΠΌΠ΅ ΠΌΠ΅ΡΠΎΠ΄Π° newGame, Π·Π° Π΄Π° Π·Π°ΠΏΠΎΡΠ½Π΅ΠΌ Π½ΠΎΠ²Π° ΠΈΠ³ΡΠ°.
ΠΡΠ»Π΅Π½ ΠΊΠΎΠ΄ Π½Π° ΠΈΠ³ΡΠ°ΡΠ°
ΠΠΎΡΠ»Π΅Π΄Π½Π°ΡΠ° ΡΡΡΠΏΠΊΠ°, ΠΏΡΠ΅Π΄ΠΈ Π΄Π° Π²ΠΈΠ΄ΠΈΡΠ΅ ΠΈΠ³ΡΠ°ΡΠ° Π² Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅, Π΅ Π΄Π° ΡΡΠ±Π΅ΡΠ΅ΡΠ΅ Π²ΡΠΈΡΠΊΠΈ Π΅Π»Π΅ΠΌΠ΅Π½ΡΠΈ Π½Π° ΠΊΠΎΠ΄Π° Π·Π°Π΅Π΄Π½ΠΎ. ΠΡΠΎ ΠΊΠ°ΠΊΠ²ΠΎ ΡΠ΅ ΠΏΠΎΠ»ΡΡΠΈΡΠ΅:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
// Π©Π΅ ΡΡΠ·Π΄Π°Π΄Π΅ΠΌ ΠΈΠ³ΡΠ° Π½Π° 15 Ρ Java 8 ΠΈ Swing
// ΠΠΊΠΎ ΠΈΠΌΠ°ΡΠ΅ Π²ΡΠΏΡΠΎΡΠΈ, Π½Π΅ ΡΠ΅ ΠΊΠΎΠ»Π΅Π±Π°ΠΉΡΠ΅ Π΄Π° ΠΏΡΠΎΡΠ΅ΡΠ΅ΡΠ΅ ΠΊΠΎΠΌΠ΅Π½ΡΠ°ΡΠΈΡΠ΅ ;)
public class GameOfFifteen extends JPanel { // Π½Π°ΡΠ°ΡΠ° ΠΌΡΠ΅ΠΆΠ° ΡΠ΅ Π±ΡΠ΄Π΅ Π½Π°ΡΠΈΡΡΠ²Π°Π½Π° Π² ΡΠΏΠ΅ΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½ ΠΏΠ°Π½Π΅Π»
// Π Π°Π·ΠΌΠ΅Ρ Π½Π° ΠΈΠ½ΡΡΠ°Π½ΡΠΈΡΡΠ° Π½Π° ΠΈΠ³ΡΠ°ΡΠ° ΠΠΎΠ»ΡΠΌΠ° ΠΎΡΠ΅ΠΌ
private int size;
// ΠΡΠΎΠΉ ΠΏΠ»ΠΎΡΠΊΠΈ
private int nbTiles;
// UI Π Π°Π·ΠΌΠ΅Ρ Π½Π° ΠΌΠ°ΡΡΠΈΡΠ°ΡΠ°
private int dimension;
// ΠΡΠ½ΠΎΠ²Π΅Π½ ΡΠ²ΡΡ
private static final Color FOREGROUND_COLOR = new Color(239, 83, 80); // ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π°ΠΌΠ΅ ΠΏΡΠΎΠΈΠ·Π²ΠΎΠ»Π΅Π½ ΡΠ²ΡΡ
// Π‘Π»ΡΡΠ°Π΅Π½ ΠΎΠ±Π΅ΠΊΡ Π·Π° ΡΠ°Π·Π±ΡΡΠΊΠ²Π°Π½Π΅ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅
private static final Random RANDOM = new Random();
// Π‘ΡΡ
ΡΠ°Π½ΡΠ²Π°Π½Π΅ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅ Π² 1D ΠΌΠ°ΡΠΈΠ² ΠΎΡ ΡΠ΅Π»ΠΈ ΡΠΈΡΠ»Π°
private int[] tiles;
// Π Π°Π·ΠΌΠ΅Ρ Π½Π° ΠΏΠ»ΠΎΡΠΊΠ°ΡΠ° Π² UI
private int tileSize;
// ΠΠΎΠ·ΠΈΡΠΈΡ Π½Π° ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ»ΠΎΡΠΊΠ°
private int blankPos;
// Margin Π·Π° ΠΌΠ°ΡΡΠΈΡΠ°ΡΠ° Π½Π° ΡΠ°ΠΌΠΊΠ°ΡΠ°
private int margin;
// Π Π°Π·ΠΌΠ΅Ρ Π½Π° UI ΠΌΠ°ΡΡΠΈΡΠ°ΡΠ°
private int gridSize;
private boolean gameOver; // true Π°ΠΊΠΎ ΠΈΠ³ΡΠ°ΡΠ° Π΅ Π·Π°Π²ΡΡΡΠΈΠ»Π°, false Π² ΠΏΡΠΎΡΠΈΠ²Π΅Π½ ΡΠ»ΡΡΠ°ΠΉ
public GameOfFifteen(int size, int dim, int mar) {
this.size = size;
dimension = dim;
margin = mar;
// ΠΈΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·ΠΈΡΠ°Π½Π΅ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅
nbTiles = size * size - 1; // -1, Π·Π°ΡΠΎΡΠΎ Π½Π΅ Π±ΡΠΎΠΈΠΌ ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ»ΠΎΡΠΊΠ°
tiles = new int[size * size];
// ΠΈΠ·ΡΠΈΡΠ»Π΅ΡΠ΅ ΡΠ°Π·ΠΌΠ΅ΡΠ° Π½Π° ΠΌΠ°ΡΡΠΈΡΠ°ΡΠ° ΠΈ ΡΠ°Π·ΠΌΠ΅ΡΠ° Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅
gridSize = (dim - 2 * margin);
tileSize = gridSize / size;
setPreferredSize(new Dimension(dimension, dimension + margin));
setBackground(Color.WHITE);
setForeground(FOREGROUND_COLOR);
setFont(new Font("SansSerif", Font.BOLD, 60));
gameOver = true;
addMouseListener(new MouseAdapter() {
@Override
public void mousePressed(MouseEvent e) {
// ΠΈΠ·ΠΏΠΎΠ»Π·Π²Π° ΡΠ΅ Π·Π° ΠΏΠΎΠ·Π²ΠΎΠ»ΡΠ²Π°Π½Π΅ Π½Π° ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅ Π΄Π° Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²Π°Ρ Ρ ΠΌΠ°ΡΡΠΈΡΠ°ΡΠ° ΡΡΠ΅Π· ΠΊΠ»ΠΈΠΊΠ²Π°Π½Π΅
// Π²ΡΠ΅ΠΌΠ΅ Π΅ Π΄Π° ΡΠ΅Π°Π»ΠΈΠ·ΠΈΡΠ°ΠΌΠ΅ Π²Π·Π°ΠΈΠΌΠΎΠ΄Π΅ΠΉΡΡΠ²ΠΈΠ΅ Ρ ΠΏΠΎΡΡΠ΅Π±ΠΈΡΠ΅Π»ΠΈΡΠ΅ Π·Π° ΠΏΡΠΈΠ΄Π²ΠΈΠΆΠ²Π°Π½Π΅ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅, Π·Π° Π΄Π° ΡΠ΅ΡΠΈΠΌ ΠΈΠ³ΡΠ°ΡΠ° !
if (gameOver) {
newGame();
} else {
// ΠΏΠΎΠ»ΡΡΠ°Π²Π°Π½Π΅ Π½Π° ΠΏΠΎΠ·ΠΈΡΠΈΡΡΠ° Π½Π° ΠΊΠ»ΠΈΠΊΠ°
int ex = e.getX() - margin;
int ey = e.getY() - margin;
// ΠΊΠ»ΠΈΠΊΠ½Π΅ΡΠ΅ Π² ΠΌΡΠ΅ΠΆΠ°ΡΠ° ?
if (ex gridSize || ey gridSize)
return;
// ΠΏΠΎΠ»ΡΡΠ°Π²Π°Π½Π΅ Π½Π° ΠΏΠΎΠ·ΠΈΡΠΈΡΡΠ° Π² ΠΌΠ°ΡΡΠΈΡΠ°ΡΠ°
int c1 = ex / tileSize;
int r1 = ey / tileSize;
// ΠΏΠΎΠ»ΡΡΠ°Π²Π°Π½Π΅ Π½Π° ΠΏΠΎΠ·ΠΈΡΠΈΡΡΠ° Π½Π° ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΊΠ»Π΅ΡΠΊΠ°
int c2 = blankPos % size;
int r2 = blankPos / size;
// ΠΏΡΠ΅Π²ΡΡΡΠ°ΠΌΠ΅ Π² 1D ΠΊΠΎΠΎΡΠ΄ΠΈΠ½Π°ΡΠΈ
int clickPos = r1 * size + c1;
int dir = 0;
// ΡΡΡΡΠΈΠΌ ΠΏΠΎΡΠΎΠΊΠ° Π·Π° ΠΌΠ½ΠΎΠΆΠ΅ΡΡΠ²ΠΎ Π΄Π²ΠΈΠΆΠ΅Π½ΠΈΡ Π½Π° ΠΏΠ»ΠΎΡΠΊΠΈ Π½Π°Π²Π΅Π΄Π½ΡΠΆ
if (c1 == c2 && Math.abs(r1 - r2) > 0)
dir = (r1 - r2) > 0 ? size : -size;
else if (r1 == r2 && Math.abs(c1 - c2) > 0)
dir = (c1 - c2) > 0 ? 1 : -1;
if (dir != 0) {
// Π΄Π²ΠΈΠΆΠΈΠΌ ΠΏΠ»ΠΎΡΠΊΠΈΡΠ΅ Π² ΠΏΠΎΡΠΎΠΊΠ°ΡΠ°
do {
int newBlankPos = blankPos + dir;
tiles[blankPos] = tiles[newBlankPos];
blankPos = newBlankPos;
} while(blankPos != clickPos);
tiles[blankPos] = 0;
}
// ΠΏΡΠΎΠ²Π΅ΡΡΠ²Π°ΠΌΠ΅ Π΄Π°Π»ΠΈ ΠΈΠ³ΡΠ°ΡΠ° Π΅ ΡΠ΅ΡΠ΅Π½Π°
gameOver = isSolved();
}
// ΠΎΡΠ²Π΅ΠΆΠ°Π²Π°ΠΌΠ΅ ΠΏΠ°Π½Π΅Π»Π°
repaint();
}
});
newGame();
}
private void newGame() {
do {
reset(); // Π½ΡΠ»ΠΈΡΠ°Π½Π΅ Π² Π½Π°ΡΠ°Π»Π½ΠΎ ΡΡΡΡΠΎΡΠ½ΠΈΠ΅
shuffle(); // ΡΠ°Π·Π±ΡΡΠΊΠ²Π°Π½Π΅
} while(!isSolvable()); // Π΄Π° Π³ΠΎ Π½Π°ΠΏΡΠ°Π²ΠΈΠΌ, Π΄ΠΎΠΊΠ°ΡΠΎ ΠΌΠ°ΡΡΠΈΡΠ°ΡΠ° Π½Π΅ ΡΡΠ°Π½Π΅ ΡΠ΅ΡΠΈΠΌΠ°
gameOver = false;
}
private void reset() {
for (int i = 0; i 1) {
int r = RANDOM.nextInt(n--);
int tmp = tiles[r];
tiles[r] = tiles[n];
tiles[n] = tmp;
}
}
// Π‘Π°ΠΌΠΎ ΠΏΠΎΠ»ΠΎΠ²ΠΈΠ½Π°ΡΠ° ΠΎΡ ΠΏΠ΅ΡΠ΅ΡΡΠ°Π½ΠΎΠ²ΠΊΠΈΡΠ΅ Π½Π° ΠΏΡΠ·Π΅Π»Π° ΡΠ° ΡΠ΅ΡΠΈΠΌΠΈ.
// ΠΡΡΠΊΠΎΠ³Π°, ΠΊΠΎΠ³Π°ΡΠΎ ΠΏΠ»ΠΎΡΠΊΠ° Π΅ ΠΏΡΠ΅Π΄ΡΠ΅ΡΡΠ²Π°Π½Π° ΠΎΡ Π΄ΡΡΠ³Π° Ρ ΠΏΠΎ-Π²ΠΈΡΠΎΠΊΠ° ΡΡΠΎΠΉΠ½ΠΎΡΡ, ΡΠΎΠ²Π° ΡΠ΅ Π±ΡΠΎΠΈ
// ΠΊΠ°ΡΠΎ ΠΈΠ½Π²Π΅ΡΡΠΈΡ. Π Π½Π°ΡΠΈΡ ΡΠ»ΡΡΠ°ΠΉ, Ρ ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ»ΠΎΡΠΊΠ° Π² ΡΠ΅ΡΠ΅Π½Π°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ,
// Π±ΡΠΎΡΡ Π½Π° ΠΈΠ½Π²Π΅ΡΡΠΈΠΈΡΠ΅ ΡΡΡΠ±Π²Π° Π΄Π° Π±ΡΠ΄Π΅ ΡΠ΅ΡΠ΅Π½ Π·Π° ΠΏΡΠ·Π΅Π»Π° Π΄Π° Π±ΡΠ΄Π΅ ΡΠ΅ΡΠΈΠΌ
private boolean isSolvable() {
int countInversions = 0;
for (int i = 0; i < nbTiles; i++) {
for (int j = 0; j tiles[i])
countInversions++;
}
}
return countInversions % 2 == 0;
}
private boolean isSolved() {
if (tiles[tiles.length - 1] != 0) // Π°ΠΊΠΎ ΠΏΡΠ°Π·Π½Π°ΡΠ° ΠΏΠ»ΠΎΡΠΊΠ° Π½Π΅ Π΅ Π² ΡΠ΅ΡΠ΅Π½Π°ΡΠ° ΠΏΠΎΠ·ΠΈΡΠΈΡ ==> Π½Π΅ Π΅ ΡΠ΅ΡΠ΅Π½Π°
return false;
for (int i = nbTiles - 1; i >= 0; i--) {
if (tiles[i] != i + 1)
return false;
}
return true;
}
private void drawGrid(Graphics2D g) {
for (int i = 0; i {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setTitle("ΠΠ³ΡΠ° Π½Π° ΠΠ΅ΡΠ½Π°Π΄Π΅ΡΠ΅Ρ");
frame.setResizable(false);
frame.add(new GameOfFifteen(4, 550, 30), BorderLayout.CENTER);
frame.pack();
// ΡΠ΅Π½ΡΡΠΈΡΠ°ΠΉΡΠ΅ Π½Π° Π΅ΠΊΡΠ°Π½Π°
frame.setLocationRelativeTo(null);
frame.setVisible(true);
});
}
}ΠΠ°ΠΊΡΠ°Ρ, ΠΈΠ³ΡΠ°Π΅ΠΌ!
ΠΡΠ΅ΠΌΠ΅ Π΅ Π΄Π° ΡΡΠ°ΡΡΠΈΡΠ°ΠΌΠ΅ ΠΈΠ³ΡΠ°ΡΠ° ΠΈ Π΄Π° Ρ ΠΏΡΠΎΠ²Π΅ΡΠΈΠΌ Π² Π΄Π΅ΠΉΡΡΠ²ΠΈΠ΅. ΠΠΎΠ»Π΅ΡΠΎ ΡΡΡΠ±Π²Π° Π΄Π° ΠΈΠ·Π³Π»Π΅ΠΆΠ΄Π° ΠΏΠΎ ΡΠ»Π΅Π΄Π½ΠΈΡ Π½Π°ΡΠΈΠ½:

ΠΠΏΠΈΡΠ²Π°ΠΌΠ΅ ΡΠ΅ Π΄Π° ΡΠ΅ΡΠΈΠΌ Π³ΠΎΠ»ΠΎΠ²ΠΎΠ»ΠΎΠΌΠΊΠ°. ΠΠΊΠΎ Π²ΡΠΈΡΠΊΠΎ Π΅ ΠΌΠΈΠ½Π°Π»ΠΎ ΡΡΠΏΠ΅ΡΠ½ΠΎ, ΠΏΠΎΠ»ΡΡΠ°Π²Π°ΠΌΠ΅ ΡΠΎΠ²Π°:

Π ΡΠΎΠ²Π° Π΅ Π²ΡΠΈΡΠΊΠΎ. ΠΡΠ°ΠΊΠ²Π°Ρ
ΡΠ΅ Π»ΠΈ ΠΏΠΎΠ²Π΅ΡΠ΅? π
Skillbox ΠΏΡΠ΅ΠΏΠΎΡΡΡΠ²Π°:
- ΠΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ ΠΊΡΡΡ .
- ΠΡΠΈΠΊΠ»Π°Π΄Π΅Π½ ΠΎΠ½Π»Π°ΠΉΠ½ ΠΊΡΡΡ .
- ΠΠ²ΡΠ³ΠΎΠ΄ΠΈΡΠ΅Π½ ΠΏΡΠ°ΠΊΡΠΈΡΠ΅ΡΠΊΠΈ ΠΊΡΡΡ .
ΠΠ·ΡΠΎΡΠ½ΠΈΠΊ: habr.com
