Prieš keletą mėnesių manęs paprašė sukurti nedidelę „Java“ biblioteką, prie kurios galėtų prisijungti programa, kad būtų galima pateikti grafinę vartotojo sąsają (GUI) „Checkers“ žaidimui. GUI turi leisti ne tik perduoti šaškių lentą ir šaškes, bet ir tikrintuvą vilkti iš vieno kvadrato į kitą. Be to, tikrintuvas turi būti sutelktas į aikštę ir neturi būti priskirtas kvadratui, kurį užima kitas tikrintuvas. Šiame įraše pristatau savo biblioteką.
Šaškių GUI bibliotekos projektavimas
Kokius visuomenės tipus biblioteka turėtų palaikyti? Šaškėse kiekvienas iš dviejų žaidėjų pakaitomis perkelia vieną savo įprastą (ne karaliaus) šaškę tik į priekį ir galbūt peršoka kito žaidėjo šaškę. Kai tikrintuvas pasiekia kitą pusę, jis paaukštinamas iki karaliaus, kuris taip pat gali judėti atgal. Iš šio aprašymo galime spręsti šiuos tipus:
Lenta
Tikrintojas
„CheckerType“
Žaidėjas
A Lenta
objektas identifikuoja šaškių lentą. Jis tarnauja kaip konteineris Tikrintojas
objektai, užimantys įvairius kvadratus. Jis gali pats išsireikalauti ir paprašyti, kad kiekvienas būtų Tikrintojas
objektas pats piešia.
A Tikrintojas
objektas identifikuoja tikrintuvą. Jis turi spalvą ir nurodymą, ar tai paprastas, ar karališkas tikrintuvas. Jis gali pats nupiešti savo dydį Lenta
, kurio dydžiui įtakos turi Tikrintojas
dydžio.
„CheckerType“
yra enumas, kuris identifikuoja tikrintuvo spalvą ir tipą per keturias konstantas: BLACK_KING
, BLACK_REGULAR
, RED_KING
ir RED_REGULAR
.
A Žaidėjas
objektas yra valdiklis, skirtas judinti šaškę su pasirenkamais šuoliais. Kadangi pasirinkau šį žaidimą įgyvendinti „Swing“, Žaidėjas
nėra būtina. Užtat aš pasisukau Lenta
į „Swing“ komponentą, kurio konstruktorius registruoja pelės ir pelės judesio klausytojus, kurie tvarko tikrintuvo judėjimą žmogaus grotuvo vardu. Ateityje galėčiau įdiegti kompiuterio grotuvą per kitą giją, sinchronizatorių ir kitą Lenta
metodas (pvz., perkelti ()
).
Ką veikia viešosios API Lenta
ir Tikrintojas
prisidėti? Kiek pagalvojęs sugalvojau šią visuomenę Lenta
API:
Lenta()
: Sukonstruoti aLenta
objektas. Konstruktorius atlieka įvairias inicializavimo užduotis, tokias kaip klausytojo registracija.negaliojantis pridėjimas (tikrintuvo tikrintuvas, int eilutė, stulpelis int)
: Papildytitikrintojas
įLenta
nustatytoje vietojeeilutė
irstulpelį
. Eilutė ir stulpelis yra 1 vertės vertės, o ne 0 vertės (žr. 1 pav.).papildyti()
metimaijava.lang.IllegalArgumentException
kai jo eilutės ar stulpelio argumentas yra mažesnis nei 1 arba didesnis nei 8. Be to, jis išmeta nepažymėtąAlreadyOccupiedException
kai bandysite pridėti aTikrintojas
į užimtą aikštę.Aspektas getPreferredSize ()
: GrąžinkiteLenta
komponento pageidaujamas dydis išdėstymo tikslais.
1 paveikslas. Lentos viršutinis kairysis kampas yra (1, 1)
Aš taip pat išplėtojau šią visuomenę Tikrintojas
API:
Tikrintuvas („CheckerType“ tikrintuvo tipas)
: Sukonstruoti aTikrintojas
nurodyto objektocheckerType
(BLACK_KING
,BLACK_REGULAR
,RED_KING
arbaRED_REGULAR
).tuščias piešimas (grafika g, int cx, int cy)
: Pieškite aTikrintojas
naudojant nurodytą grafikos kontekstąg
tikrintuvo centre, esančiame (cx
,cy
). Šis metodas yra skirtas išLenta
tik.loginės reikšmės yra (int x, int y, int cx, int cy)
: Astatinis
paskambinta pagalbininko metoduLenta
kuris nustato, ar pelės koordinatės (x
,y
) guli tikrintuvo viduje, kurio centro koordinates nurodo (cx
,cy
) ir kurio matmuo nurodytas kiturTikrintojas
klasė.int getDimension ()
: Astatinis
paskambinta pagalbininko metoduLenta
tai nustato šaškės dydį, kad lenta galėtų tinkamai parinkti kvadratus ir bendrą dydį.
Tai beveik apima visas šaškių GUI bibliotekas, atsižvelgiant į jos tipus ir viešąsias API. Dabar sutelksime dėmesį į tai, kaip aš įgyvendinau šią biblioteką.
Šaškių GUI bibliotekos diegimas
Šaškių GUI biblioteką sudaro keturi viešieji tipai, esantys tame pačiame pavadinime esančiuose šaltinio failuose: AlreadyOccupiedException
, Lenta
, Tikrintojas
ir „CheckerType“
. Išvardinus 1 dovanas AlreadyOccupiedException
šaltinio kodas.
1 sąrašas. AlreadyOccupiedException.java
public class AlreadyOccupiedException pratęsia RuntimeException {public AlreadyOccupiedException (String msg) {super (msg); }}
AlreadyOccupiedException
tęsiasi java.lang.RuntimeException
, kuris padaro AlreadyOccupiedException
nepatikrinta išimtis (jos nereikia gaudyti ar deklaruoti metimai
sąlyga). Jei norėčiau pagaminti AlreadyOccupiedException
patikrinau, būčiau pratęsęs java.lang. Išimtis
. Aš pasirinkau, kad šis tipas būtų netikrinamas, nes jis veikia panašiai kaip ir nepažymėtas Neteisėtas argumentas. Išimtis
.
AlreadyOccupiedException
pareiškia konstruktorius, kuris pateikia eilutės argumentą, apibūdinantį išimties priežastį. Šis argumentas persiųstas RuntimeException
superklasė.
Išvardinus 2 dovanas Lenta
.
2 sąrašas. Board.java
importuoti java.awt.Color; importuoti java.awt.Dimension; importuoti java.awt.Grafika; importuoti java.awt.Grafika2D; importuoti java.awt.RenderingHints; importuoti java.awt.event.MouseEvent; importuoti java.awt.event.MouseAdapter; importuoti java.awt.event.MouseMotionAdapter; importuoti java.util.ArrayList; importuoti java.util.List; importuoti javax.swing.JComponent; public class Board praplečia JComponent {// šaškių lentos kvadrato matmenis (25% didesnis nei šaškė) private final static int SQUAREDIM = (int) (Checker.getDimension () * 1,25); // šaškių lentos matmuo (8 kvadratų plotis) privatus finalas int BOARDDIM = 8 * SQUAREDIM; // pageidaujamas plokštės komponento „private Dimension dimPrefSize“ dydis; // vilkimo vėliava - nustatyta kaip „true“, kai vartotojas paspaudžia pelės mygtuką virš tikrintuvo // ir išvaloma į „false“, kai vartotojas atleidžia pelės mygtuko privatų loginį elementą inDrag = false; // poslinkis tarp vilkimo pradžios koordinačių ir tikrintuvo centro koordinačių private int deltax, deltay; // nuoroda į padėtą tikrintuvą vilkimo privataus „PosCheck posCheck“ pradžioje; // centrinė tikrintuvo vieta vilkimo pradžioje private int oldcx, oldcy; // Checker objektų ir jų pradinių pozicijų sąrašas privatus List posChecks; viešoji lenta () {posChecks = new ArrayList (); dimPrefSize = naujas aspektas (BOARDDIM, BOARDDIM); addMouseListener (naujas MouseAdapter () {@Paisyti viešą tuštumą mousePressed (MouseEvent me) {// Paspaudimo metu gaukite pelės koordinates. int x = me.getX (); int y = me.getY (); // Raskite padėtą tikrintuvą pelės paspaudimu. ieškokite (PosCheck posCheck: posChecks) if (Checker.contains (x, y, posCheck.cx, posCheck.cy)) {Board.this.posCheck = posCheck; oldcx = posCheck.cx; oldcy = posCheck.cy ; deltax = x - posCheck.cx; deltay = y - posCheck.cy; inDrag = true; return;}} @Paisyti viešą void mouseReleased („MouseEvent me“) {// Paleidus pelę, išvalykite „inDrag“ (į vykdoma), jei inDrag yra // jau nustatytas. if (inDrag) inDrag = false; dar grįžti; // Pritvirtinkite tikrintuvą prie kvadrato centro. int x = me.getX (); int y = me.getY (); posCheck .cx = (x - deltax) / SQUAREDIM * SQUAREDIM + SQUAREDIM / 2; posCheck.cy = (y - delta) / SQUAREDIM * SQUAREDIM + SQUAREDIM / 2; // Neperkelkite tikrintuvo į užimtą aikštę. ((PosCheck posCheck) : posChecks) if (posCheck! = Board.this.posCheck && posC heck.cx == Board.this.posCheck.cx && posCheck.cy == Board.this.posCheck.cy) {Board.this.posCheck.cx = oldcx; Board.this.posCheck.cy = oldcy; } posCheck = null; perdažyti (); }}); // Prie programėlės pritvirtinkite pelės judesių klausytoją. Tas klausytojas klauso // pelės nuvilkimo įvykių. „addMouseMotionListener“ (naujas „MouseMotionAdapter“) ({@Orride public void mouseDragged (MouseEvent me) {if (inDrag) {// Atnaujinti tikrintuvo centro vietą. posCheck.cx = me.getX () - deltax; posCheck.cy = me.getY ( ) - deltay; perdažyti ();}}}); } public void add (tikrintuvo tikrintuvas, int eilutė, int col) {if (8 eilutė) mesti naują „IllegalArgumentException“ („eilutė už diapazono ribų:“ + eilutė); if (8 skiltis) mesti naują „IllegalArgumentException“ („col out of range:“ + col); PosCheck posCheck = naujas PosCheck (); posCheck.checker = tikrintuvas; posCheck.cx = (col - 1) * SQUAREDIM + SQUAREDIM / 2; posCheck.cy = (1 eilutė) * SQUAREDIM + SQUAREDIM / 2; už (PosCheck _posCheck: posChecks), jei (posCheck.cx == _posCheck.cx && posCheck.cy == _posCheck.cy) mesti naują „AlreadyOccupiedException“ („kvadratas ties (" + eilutė + "," + col + ") užimtas" ); posChecks.add (posCheck); } @Paisyti viešąjį aspektą getPreferredSize () {return dimPrefSize; } @Paisyti apsaugotą tuščią paintComponent (grafika g) {paintCheckerBoard (g); už (PosCheck posCheck: posChecks) if (posCheck! = Board.this.posCheck) posCheck.checker.draw (g, posCheck.cx, posCheck.cy); // Nuvilkite tikrintuvą paskutinį, kad jis pasirodytų virš bet kurio pagrindinio // tikrintuvo. if (posCheck! = null) posCheck.checker.draw (g, posCheck.cx, posCheck.cy); } private void paintCheckerBoard (grafika g) {((Graphics2D) g) .setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Dažų šaškių lenta. už (int eilutė = 0; eilutė <8; eilutė ++) {g.setColor ((((1 eilutė)! = 0)? Spalva. JUODA: Spalva. BALTA); for (int col = 0; col <8; col ++) {g.fillRect (col * SQUAREDIM, eilutė * SQUAREDIM, SQUAREDIM, SQUAREDIM); g.setColor ((g.getColor () == Color.BLACK)? Color.WHITE: Color.BLACK); }}} // padėtas tikrintuvo pagalbininkas klasės privati klasė „PosCheck“ {viešoji tikrintuvo tikrintoja; public int cx; visuomenės int cy; }}
Lenta
tęsiasi javax.swing.JKomponentas
, kuris padaro Lenta
a Sūpynės komponentas. Tokiu būdu galite tiesiogiai pridėti a Lenta
komponentą į „Swing“ programos turinio sritį.
Lenta
pareiškia SQUAREDIM
ir LENTELĖ
konstantos, identifikuojančios kvadrato ir langelio taškų matmenis. Inicijuojant SQUAREDIM
, Kviečiuosi Checker.getDimension ()
užuot patekęs į lygiavertę visuomenę Tikrintojas
pastovus. Joshua Block atsako, kodėl aš tai darau, 30 punkte (vietoj tarpt
konstantos) jo antrojo leidimo, Veiksminga „Java“"Programos, naudojančios tarpt
enum raštas yra trapus. Nes tarpt
enums yra kompiliavimo laiko konstantos, jos sudaromos klientams, kurie jas naudoja. Jei tarpt
susijęs su enum konstanta, jos klientai turi būti sudaryti iš naujo. Jei jų nėra, jie vis tiek bėgs, tačiau jų elgesys bus neapibrėžtas “.
Dėl išsamių komentarų neturiu daug daugiau pasakyti Lenta
. Tačiau atkreipkite dėmesį į įdėtą „PosCheck“
klasė, kuri apibūdina padėtą tikrintuvą saugodama a Tikrintojas
nuoroda ir jos centro koordinatės, palyginti su viršutiniu kairiuoju Lenta
komponentas. Kai pridėsite a Tikrintojas
prieštarauti Lenta
, jis saugomas naujame „PosCheck“
objektas kartu su tikrintuvo vidurio padėtimi, kuri apskaičiuojama pagal nurodytą eilutę ir stulpelį.
Išvardijamos 3 dovanos Tikrintojas
.