рдЬрд╛рд╡рд╛ рдореЗрдВ "рдкрдВрджреНрд░рд╣" - рдПрдХ рдкреВрд░реНрдг рдЧреЗрдо рдХреИрд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдП



рдкрдВрджреНрд░рд╣, рдпрд╛ рдкрдВрджреНрд░рд╣, рджреБрдирд┐рдпрд╛ рднрд░ рдореЗрдВ рд▓реЛрдХрдкреНрд░рд┐рдп рдПрдХ рд╕рд░рд▓ рддрд░реНрдХ рдЦреЗрд▓ рдХрд╛ рдПрдХ рдмрдбрд╝рд╛ рдЙрджрд╛рд╣рд░рдг рд╣реИред рдкрд╣реЗрд▓реА рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ рдЫреЛрдЯреЗ рд╕реЗ рдмрдбрд╝реЗ рддрдХ рдХреНрд░рдо рдореЗрдВ рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреЗ рд╕рд╛рде рд╡рд░реНрдЧреЛрдВ рдХреЛ рд╡реНрдпрд╡рд╕реНрдерд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдпрд╣ рдЖрд╕рд╛рди рдирд╣реАрдВ рд╣реИ, рд▓реЗрдХрд┐рди рджрд┐рд▓рдЪрд╕реНрдк рд╣реИред

рдЖрдЬ рдХреЗ рдЯреНрдпреВрдЯреЛрд░рд┐рдпрд▓ рдореЗрдВ, рд╣рдо рджрд┐рдЦрд╛рддреЗ рд╣реИрдВ рдХрд┐ рдЧреНрд░рд╣рдг рдХреЗ рд╕рд╛рде рдЬрд╛рд╡рд╛ 8 рдореЗрдВ рдкрдВрджреНрд░рд╣ рдХреЛ рдХреИрд╕реЗ рд╡рд┐рдХрд╕рд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдПред UI рд╡рд┐рдХрд╕рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕реНрд╡рд┐рдВрдЧ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред

рд╣рдо рдЖрдкрдХреЛ рдпрд╛рдж рджрд┐рд▓рд╛рддреЗ рд╣реИрдВ: "рд╣реИрдмрд░" рдХреЗ рд╕рднреА рдкрд╛рдардХреЛрдВ рдХреЗ рд▓рд┐рдП - "рд╣реИрдмрд░" рдкреНрд░реЛрдореЛ рдХреЛрдб рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдХрд┐рд╕реА рднреА рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдХреЛрд░реНрд╕ рдХреЗ рд▓рд┐рдП рдкрдВрдЬреАрдХрд░рдг рдХрд░рддреЗ рд╕рдордп 10,000 рд░реВрдмрд▓ рдХреА рдЫреВрдЯред

рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реИ: рдСрди-рд▓рд╛рдЗрди рд╢реИрдХреНрд╖рд┐рдХ рдкрд╛рдареНрдпрдХреНрд░рдо "рдкреНрд░реЛрдлреЗрд╢рди рдЬрд╛рд╡рд╛-рдбреЗрд╡рд▓рдкрд░" ред

рдЦреЗрд▓ рдбрд┐рдЬрд╛рдЗрди


рдЗрд╕ рд╕реНрддрд░ рдкрд░, рдЖрдкрдХреЛ рдЧреБрдгреЛрдВ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
  • рдЖрдХрд╛рд░ - рдЦреЗрд▓ рдХреЗ рдореИрджрд╛рди рдХрд╛ рдЖрдХрд╛рд░;
  • nbTiles - рдХреНрд╖реЗрддреНрд░ рдореЗрдВ рд╕реНрдкреЙрдЯ рдХреА рд╕рдВрдЦреНрдпрд╛ред nbTiles = рдЖрдХрд╛рд░ * рдЖрдХрд╛рд░ - 1;
  • рдЯрд╛рдЗрд▓ рдПрдХ рдЯреИрдЧ рд╣реИ, рдЬреЛ рдкреВрд░реНрдгрд╛рдВрдХреЛрдВ рдХрд╛ рдПрдХ рдЖрдпрд╛рдореА рдЖрдпрд╛рдо рд╣реИред рдкреНрд░рддреНрдпреЗрдХ рдЯреИрдЧ рдХреЛ рд░реЗрдВрдЬ рдореЗрдВ рдПрдХ рдЕрджреНрд╡рд┐рддреАрдп рдореВрд▓реНрдп рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛ [0, nbTiles]ред рд╢реВрдиреНрдп рдПрдХ рдЦрд╛рд▓реА рд╡рд░реНрдЧ рдХреЛ рджрд░реНрд╢рд╛рддрд╛ рд╣реИ;
  • blankPos - рд░рд┐рдХреНрдд рд╡рд░реНрдЧ рдХреА рд╕реНрдерд┐рддрд┐ред

рдЦреЗрд▓ рддрд░реНрдХ


рдЖрдкрдХреЛ рдПрдХ рдирдИ рдЧреЗрдо рдкреЛрдЬрд┐рд╢рди рдХреЛ рдЗрдирд┐рд╢рд┐рдпрд▓рд╛рдЗрдЬрд╝ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рдиреЗ рд╡рд╛рд▓реЗ рд░реАрд╕реЗрдЯ рд╡рд┐рдзрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдЗрд╕рд▓рд┐рдП рд╣рдо рдЯреИрдЧ рд╕рд░рдгреА рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП рдореВрд▓реНрдп рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдареАрдХ рд╣реИ, рддреЛ рд╣рдо рд╕рд░рдгреА рдХреА рдЕрдВрддрд┐рдо рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдмреНрд▓реИрдВрдХрдкреЛрд╕ рд▓рдЧрд╛рддреЗ рд╣реИрдВред

рдЖрдкрдХреЛ рдЯреИрдЧ рдХреА рдПрдХ рд╕рд░рдгреА рдореЗрдВ рдлреЗрд░рдмрджрд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдлреЗрд░рдмрджрд▓ рд╡рд┐рдзрд┐ рдХреА рднреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо рдЗрд╕реЗ рдкреВрд░реНрд╡ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рдЫреЛрдбрд╝рдиреЗ рдХреЗ рд▓рд┐рдП рдлреЗрд░рдмрджрд▓ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдПрдХ рдЦрд╛рд▓реА рдЯреИрдЧ рд╢рд╛рдорд┐рд▓ рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред

рдЪреВрдВрдХрд┐ рдкрд╣реЗрд▓реА рдХреЗ рд╕рдВрднрд╛рд╡рд┐рдд рд╢реБрд░реБрдЖрддреА рдкрджреЛрдВ рдореЗрдВ рд╕реЗ рдХреЗрд╡рд▓ рдЖрдзреЗ рдХрд╛ рд╣реА рд╕рдорд╛рдзрд╛рди рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЖрдкрдХреЛ рдпрд╣ рд╕реБрдирд┐рд╢реНрдЪрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд░рд┐рдгрд╛рдореА рдорд┐рд╢реНрд░рдг рдкрд░рд┐рдгрд╛рдо рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреА рд╣реЛрдЧреА рдХрд┐ рд╡рд░реНрддрдорд╛рди рд▓реЗрдЖрдЙрдЯ рдЖрдорддреМрд░ рдкрд░ рд╣рд▓ рд╣реЛред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо isSolvable рдкрджреНрдзрддрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рдпрджрд┐ рдХреЛрдИ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдЯреИрдЧ рдХрд┐рд╕реА рдЙрдЪреНрдЪ рдорд╛рди рдХреЗ рд╕рд╛рде рдЯреИрдЧ рд╕реЗ рдкрд╣рд▓реЗ рд╣реИ, рддреЛ рдЗрд╕реЗ рдЙрд▓рдЯрд╛ рдорд╛рдирд╛ рдЬрд╛рддрд╛ рд╣реИред рдЬрдм рдЦрд╛рд▓реА рдЯреИрдЧ рдХреА рдЬрдЧрд╣ рд╣реЛрддреА рд╣реИ, рддреЛ рдкрд╣реЗрд▓реА рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реНрдпреБрддреНрдХреНрд░рдореЛрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рднреА рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред рдЗрд╕рд▓рд┐рдП, рд╣рдо рд╕рдВрдЦреНрдпрд╛рдУрдВ рдХреА рд╕рдВрдЦреНрдпрд╛ рдХреЛ рдЧрд┐рдирддреЗ рд╣реИрдВ рдФрд░ рдпрджрд┐ рд╕рдВрдЦреНрдпрд╛ рд╕рдо рд╣реИ рддреЛ рд╡рд╛рдкрд╕ рд▓реМрдЯрддреЗ рд╣реИрдВред

рдлрд┐рд░ рдпрд╣ рдЬрд╛рдБрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐ рд╣рдорд╛рд░реЗ рдкрдВрджреНрд░рд╣ рд╕рдВрд░реЗрдЦрдг рдХрд╛ рд╕рдорд╛рдзрд╛рди рд╣реИ, рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП isSolved рд╡рд┐рдзрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдирд╛ рдорд╣рддреНрд╡рдкреВрд░реНрдг рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рджреЗрдЦрддреЗ рд╣реИрдВ рдХрд┐ рдЦрд╛рд▓реА рдЯреИрдЧ рдХрд╣рд╛рдВ рд╣реИред рдпрджрд┐ рдкреНрд░рд╛рд░рдВрднрд┐рдХ рд╕реНрдерд┐рддрд┐ рдореЗрдВ рд╣реИ, рддреЛ рд╡рд░реНрддрдорд╛рди рд╕рдВрд░реЗрдЦрдг рдПрдХ рдирдпрд╛ рд╣реИ, рдЬреЛ рдкрд╣рд▓реЗ рддрдп рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдлрд┐рд░ рд╣рдо рдЙрд▓реНрдЯреЗ рдХреНрд░рдо рдореЗрдВ рдЯрд╛рдЗрд▓реЛрдВ рдкрд░ рдкреБрдирд░рд╛рд╡реГрддрд┐ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдпрджрд┐ рдЯреИрдЧ рдорд╛рди рд╕рдВрдмрдВрдзрд┐рдд +1 рдЗрдВрдбреЗрдХреНрд╕ рд╕реЗ рднрд┐рдиреНрди рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдЭреВрдареЗ рд╡рд╛рдкрд╕ рдЖ рдЬрд╛рддреЗ рд╣реИрдВред рдЕрдиреНрдпрдерд╛, рдпрд╣ рд╡рд┐рдзрд┐ рдХреЗ рдЕрдВрдд рдореЗрдВ рд╕рдЪ рд▓реМрдЯрдиреЗ рдХрд╛ рд╕рдордп рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдкрд╣реЗрд▓реА рдкрд╣рд▓реЗ рд╣реА рд╣рд▓ рд╣реЛ рдЪреБрдХреА рд╣реИред

рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдФрд░ рддрд░реАрдХрд╛ рдирдпрд╛ рдирд╛рдо рд╣реИред рдЦреЗрд▓ рдХрд╛ рдПрдХ рдирдпрд╛ рдЙрджрд╛рд╣рд░рдг рдмрдирд╛рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЦреЗрд▓ рдХреЗ рдХреНрд╖реЗрддреНрд░ рдХреЛ рд░реАрд╕реЗрдЯ рдХрд░рддреЗ рд╣реИрдВ, рдлрд┐рд░ рдЗрд╕реЗ рдлреЗрд░рдмрджрд▓ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рддрдм рддрдХ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВ рдЬрдм рддрдХ рдХрд┐ рдЦреЗрд▓ рдХреА рд╕реНрдерд┐рддрд┐ рдлрд┐рд░ рд╕реЗ рд╢реБрд░реВ рди рд╣реЛ рдЬрд╛рдПред

рдпрд╣рд╛рдВ рдХреБрдВрдЬреА рдЯреИрдЧ рддрд░реНрдХ рдХреЗ рд╕рд╛рде рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЛрдб рджрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ:
private void newGame() { do { reset(); // reset in initial state shuffle(); // shuffle } while(!isSolvable()); // make it until grid be solvable gameOver = false; } private void reset() { for (int i = 0; i < tiles.length; i++) { tiles[i] = (i + 1) % tiles.length; } // we set blank cell at the last blankPos = tiles.length - 1; } private void shuffle() { // don't include the blank tile in the shuffle, leave in the solved position int n = nbTiles; while (n > 1) { int r = RANDOM.nextInt(n--); int tmp = tiles[r]; tiles[r] = tiles[n]; tiles[n] = tmp; } } // Only half permutations of the puzzle are solvable/ // Whenever a tile is preceded by a tile with higher value it counts // as an inversion. In our case, with the blank tile in the solved position, // the number of inversions must be even for the puzzle to be solvable private boolean isSolvable() { int countInversions = 0; for (int i = 0; i < nbTiles; i++) { for (int j = 0; j < i; j++) { if (tiles[j] > tiles[i]) countInversions++; } } return countInversions % 2 == 0; } private boolean isSolved() { if (tiles[tiles.length - 1] != 0) // if blank tile is not in the solved position ==> not solved return false; for (int i = nbTiles - 1; i >= 0; i--) { if (tiles[i] != i + 1) return false; } return true; } 

рдЕрдВрдд рдореЗрдВ, рдЖрдкрдХреЛ рд╕рд░рдгреА рдореЗрдВ рд╕реНрдкреЙрдЯ рдХреЗ рдЖрдВрджреЛрд▓рди рдХреЛ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдХрд░реНрд╕рд░ рд╕рдВрдЪрд▓рди рдХрд╛ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрд▓рдмреИрдХ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЗрд╕ рдХреЛрдб рдХреЛ рдмрд╛рдж рдореЗрдВ рдХреЙрд▓ рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛ред рд╣рдорд╛рд░рд╛ рдЦреЗрд▓ рдПрдХ рд╕рд╛рде рдХрдИ рдЯрд╛рдЗрд▓ рдЪрд╛рд▓реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░реЗрдЧрд╛ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рд╣рдордиреЗ рд╕реНрдХреНрд░реАрди рдкрд░ рджрдмрд╛рдП рдЧрдП рд╕реНрдерд╛рди рдХреЛ рдЯреИрдЧ рдореЗрдВ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЦрд╛рд▓реА рдЯреИрдЧ рдХреА рд╕реНрдерд┐рддрд┐ рдкреНрд░рд╛рдкреНрдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рд╣реА рд╕рдордп рдореЗрдВ рдЗрд╕рдХреЗ рдХрдИ рдЖрдВрджреЛрд▓рдиреЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдВрджреЛрд▓рди рдХреА рджрд┐рд╢рд╛ рдХреА рддрд▓рд╛рд╢ рдХрд░рддреЗ рд╣реИрдВред

рдпрд╣рд╛рдБ рдПрдХ рдирдореВрдирд╛ рдХреЛрдб рд╣реИ:
 // 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; 

рд╣рдо рд╕реНрд╡рд┐рдВрдЧ рдПрдкреАрдЖрдИ рдкрд░ рдпреВрдЖрдИ рд╡рд┐рдХрд╕рд┐рдд рдХрд░рддреЗ рд╣реИрдВ


рдпрд╣ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рд╣реИред рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ рд╣рдо Jpanel рдХреНрд▓рд╛рд╕ рд▓реЗрддреЗ рд╣реИрдВред рдлрд┐рд░ рд╣рдо рдореИрджрд╛рди рдкрд░ рд╕реНрдкреЙрдЯ рдмрдирд╛рддреЗ рд╣реИрдВ - рдкреНрд░рддреНрдпреЗрдХ рдХреЗ рдЖрдХрд╛рд░ рдХреА рдЧрдгрдирд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЧреЗрдо рдХреЗ рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдбреЗрдЯрд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗ:
 gridSize = (dim -  2 * margin); tileSize = gridSize / size; 

рдорд╛рд░реНрдЬрд┐рди рднреА рдЧреЗрдо рдХрдВрд╕реНрдЯреНрд░рдХреНрдЯрд░ рдореЗрдВ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдкреИрд░рд╛рдореАрдЯрд░ рд╣реИред

рдЕрдм рдЖрдкрдХреЛ рд╕реНрдХреНрд░реАрди рдкрд░ рдЧреНрд░рд┐рдб рдФрд░ рд╕реНрдкреЙрдЯ рдЦреАрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП drawGrid рд╡рд┐рдзрд┐ рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо рдЯреИрдЧ рдХреА рд╕рд░рдгреА рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдХреЗ рдирд┐рд░реНрджреЗрд╢рд╛рдВрдХ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рдлрд┐рд░ рдХреЗрдВрджреНрд░ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рд╕рдВрдЦреНрдпрд╛ рдХреЗ рд╕рд╛рде рдкреНрд░рддреНрдпреЗрдХ рдЯреИрдЧ рдмрдирд╛рдПрдВ:
 private void drawGrid(Graphics2D g) { for (int i = 0; i < tiles.length; i++) { // we convert 1D coords to 2D coords given the size of the 2D Array int r = i / size; int c = i % size; // we convert in coords on the UI int x = margin + c * tileSize; int y = margin + r * tileSize; // check special case for blank tile if(tiles[i] == 0) { if (gameOver) { g.setColor(FOREGROUND_COLOR); drawCenteredString(g, "\u2713", x, y); } continue; } // for other tiles 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); } } 

рдЕрдВрдд рдореЗрдВ, рд╣рдо рдкреЗрдВрдЯрдХрдВрдкреЛрдиреЗрдВрдЯ рд╡рд┐рдзрд┐ рдХреЛ рдлрд┐рд░ рд╕реЗ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рдХрд┐ рдЬреЗрдкрдиреА рд╡рд░реНрдЧ рдХрд╛ рд╡реНрдпреБрддреНрдкрдиреНрди рд╣реИред рддрдм рд╣рдо рдбреНрд░рд╛рдЧреНрд░рд┐рдб рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ, рдФрд░ рдЙрд╕рдХреЗ рдмрд╛рдж рд╣рдо рдЧреЗрдо рд╢реБрд░реВ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреНрд▓рд┐рдХ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдореЗрдВ рдкреНрд░реЗрд░рд┐рдд рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рд╕рдВрджреЗрд╢ рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдбреНрд░рд╛рд╕реНрдЯрд╛рд░реНрдЯрдореЗрд╕реЗрдЬ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
 private void drawStartMessage(Graphics2D g) { if (gameOver) { g.setFont(getFont().deriveFont(Font.BOLD, 18)); g.setColor(FOREGROUND_COLOR); String s = "Click to start new game"; g.drawString(s, (getWidth() - g.getFontMetrics().stringWidth(s)) / 2, getHeight() - margin); } } private void drawCenteredString(Graphics2D g, String s, int x, int y) { // center string s for the given tile (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); } 

рд╣рдо рдпреВрдЖрдИ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдЬрд╡рд╛рдм рджреЗрддреЗ рд╣реИрдВ


рдЦреЗрд▓ рдХреЛ рдЕрдкрдирд╛ рдХреЛрд░реНрд╕ рд▓реЗрдиреЗ рдХреЗ рд▓рд┐рдП, рдпреВрдЖрдИ рдореЗрдВ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдКрдкрд░ рджрд┐рдЦрд╛рдП рдЧрдП рд╕реНрдкреЙрдЯ рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬреЗрдкрдиреЗрд▓ рдФрд░ рдХреЛрдб рдкрд░ рдорд╛рдЙрд╕ рд▓рд┐рд╕реНрдЯрдирд░ рдХреЛ рд▓рд╛рдЧреВ рдХрд░реЗрдВ:
 addMouseListener(new MouseAdapter() { @Override public void mousePressed(MouseEvent e) { // used to let users to interact on the grid by clicking // it's time to implement interaction with users to move tiles to solve the game ! if (gameOver) { newGame(); } else { // 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; } // we check if game is solved gameOver = isSolved(); } // we repaint panel 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; // We are going to create a Game of 15 Puzzle with Java 8 and Swing // If you have some questions, feel free to read comments ;) public class GameOfFifteen extends JPanel { // our grid will be drawn in a dedicated Panel // Size of our Game of Fifteen instance private int size; // Number of tiles private int nbTiles; // Grid UI Dimension private int dimension; // Foreground Color private static final Color FOREGROUND_COLOR = new Color(239, 83, 80); // we use arbitrary color // Random object to shuffle tiles private static final Random RANDOM = new Random(); // Storing the tiles in a 1D Array of integers private int[] tiles; // Size of tile on UI private int tileSize; // Position of the blank tile private int blankPos; // Margin for the grid on the frame private int margin; // Grid UI Size private int gridSize; private boolean gameOver; // true if game over, false otherwise public GameOfFifteen(int size, int dim, int mar) { this.size = size; dimension = dim; margin = mar; // init tiles nbTiles = size * size - 1; // -1 because we don't count blank tile tiles = new int[size * size]; // calculate grid size and tile 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) { // used to let users to interact on the grid by clicking // it's time to implement interaction with users to move tiles to solve the game ! if (gameOver) { newGame(); } else { // 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; } // we check if game is solved gameOver = isSolved(); } // we repaint panel repaint(); } }); newGame(); } private void newGame() { do { reset(); // reset in intial state shuffle(); // shuffle } while(!isSolvable()); // make it until grid be solvable gameOver = false; } private void reset() { for (int i = 0; i < tiles.length; i++) { tiles[i] = (i + 1) % tiles.length; } // we set blank cell at the last blankPos = tiles.length - 1; } private void shuffle() { // don't include the blank tile in the shuffle, leave in the solved position int n = nbTiles; while (n > 1) { int r = RANDOM.nextInt(n--); int tmp = tiles[r]; tiles[r] = tiles[n]; tiles[n] = tmp; } } // Only half permutations of the puzzle are solvable. // Whenever a tile is preceded by a tile with higher value it counts // as an inversion. In our case, with the blank tile in the solved position, // the number of inversions must be even for the puzzle to be solvable private boolean isSolvable() { int countInversions = 0; for (int i = 0; i < nbTiles; i++) { for (int j = 0; j < i; j++) { if (tiles[j] > tiles[i]) countInversions++; } } return countInversions % 2 == 0; } private boolean isSolved() { if (tiles[tiles.length - 1] != 0) // if blank tile is not in the solved position ==> not solved 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 < tiles.length; i++) { // we convert 1D coords to 2D coords given the size of the 2D Array int r = i / size; int c = i % size; // we convert in coords on the UI int x = margin + c * tileSize; int y = margin + r * tileSize; // check special case for blank tile if(tiles[i] == 0) { if (gameOver) { g.setColor(FOREGROUND_COLOR); drawCenteredString(g, "\u2713", x, y); } continue; } // for other tiles 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); } } private void drawStartMessage(Graphics2D g) { if (gameOver) { g.setFont(getFont().deriveFont(Font.BOLD, 18)); g.setColor(FOREGROUND_COLOR); String s = "Click to start new game"; g.drawString(s, (getWidth() - g.getFontMetrics().stringWidth(s)) / 2, getHeight() - margin); } } private void drawCenteredString(Graphics2D g, String s, int x, int y) { // center string s for the given tile (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); } public static void main(String[] args) { SwingUtilities.invokeLater(() -> { JFrame frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setTitle("Game of Fifteen"); frame.setResizable(false); frame.add(new GameOfFifteen(4, 550, 30), BorderLayout.CENTER); frame.pack(); // center on the screen frame.setLocationRelativeTo(null); frame.setVisible(true); }); } } 

рдЕрдВрдд рдореЗрдВ, рдЦреЗрд▓рддреЗ рд╣реИрдВ!


рдЦреЗрд▓ рд╢реБрд░реВ рдХрд░рдиреЗ рдФрд░ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдореЗрдВ рдЗрд╕рдХреА рдЬрд╛рдВрдЪ рдХрд░рдиреЗ рдХрд╛ рд╕рдордп рдЖ рдЧрдпрд╛ рд╣реИред рдлрд╝реАрд▓реНрдб рдХреЛ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП:



рдкрд╣реЗрд▓реА рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИред рдпрджрд┐ рд╕рдм рдХреБрдЫ рдареАрдХ рд░рд╣рд╛, рддреЛ рд╣рдореЗрдВ рдпрд╣ рдорд┐рд▓рд╛:



рд╡рд╣ рд╕рдм рд╣реИред рдХреНрдпрд╛ рдЖрдкрдХреЛ рдЬреНрдпрд╛рджрд╛ рдЙрдореНрдореАрдж рдереА? :)

рд╕реНрдХрд┐рд▓рдмреЙрдХреНрд╕ рдЕрдиреБрд╢рдВрд╕рд╛ рдХрд░рддрд╛ рд╣реИ:

Source: https://habr.com/ru/post/hi445758/


All Articles