Programiranje

Kamere, kdo?

Pred nekaj meseci so me prosili, da ustvarim majhno knjižnico Java, do katere lahko dostopa aplikacija za upodabljanje grafičnega uporabniškega vmesnika (GUI) za igro Checkers. Poleg upodabljanja šahovnice in kockic mora tudi GUI omogočati vleko preverjalnika iz enega kvadrata v drugega. Preverjevalnik mora biti tudi centriran na kvadrat in ne sme biti dodeljen kvadratu, ki ga zaseda drug preglednik. V tem prispevku predstavljam svojo knjižnico.

Oblikovanje knjižnice GUI za preverjanje

Katere javne tipe naj knjižnica podpira? Pri damah vsak od dveh igralcev izmenično premakne enega od svojih rednih (ne-kraljevih) dama preko plošče samo v smeri naprej in po možnosti preskoči dama (-e) drugega igralca. Ko checker doseže drugo stran, je povišan v kralja, ki se lahko premakne tudi v smeri nazaj. Iz tega opisa lahko sklepamo na naslednje vrste:

  • Odbor
  • Checker
  • CheckerType
  • Igralec

A Odbor objekt identificira šahovnico. Služi kot posoda za Checker predmeti, ki zasedajo različne kvadratke. Lahko se nariše in zahteva, da je vsak vsebovan Checker predmet nariše sam.

A Checker objekt identificira preverjevalnik. Ima barvo in oznako, ali gre za navaden ali kraljev. Lahko se nariše in svojo velikost da na voljo Odbor, na velikost katerega vpliva Checker velikost.

CheckerType je enum, ki prek svojih štirih konstant identificira barvo in tip preverjevalnika: BLACK_KING, ČRNA_REGULARNA, RDEČE KRALJE, in RDEČA_REGULARNA.

A Igralec object je krmilnik za premikanje dame z neobveznimi skoki. Ker sem se odločil, da bom to igro implementiral v Swing, Igralec ni potrebno. Namesto tega sem se obrnil Odbor v komponento Swing, katere konstruktor registrira poslušalce gibanja miške in miške, ki v imenu človeškega predvajalnika upravljajo gibanje kontrolnikov. V prihodnosti bi lahko računalniški predvajalnik implementiral prek druge niti, sinhronizatorja in druge Odbor metoda (kot npr premakni ()).

Kaj počnejo javni API-ji Odbor in Checker prispevati? Po premisleku sem prišel do naslednje javnosti Odbor API:

  • Board (): Sestavite a Odbor predmet. Konstruktor izvaja različne naloge inicializacije, kot je registracija poslušalca.
  • void add (Checker checker, int vrstica, int stolpec): Dodaj checker do Odbor na položaju, ki ga je določil vrstici in stolpec. Vrstica in stolpec sta vrednosti 1, v nasprotju s tem, da sta 0 (glej sliko 1). The dodaj () meti java.lang.IllegalArgumentException ko je njegov argument vrstice ali stolpca manjši od 1 ali večji od 8. Prav tako vrže neoznačeno AlreadyOccupiedException ko poskušate dodati Checker na zaseden trg.
  • Dimenzija getPreferredSize (): Vrnite Odbor prednostna velikost komponente za namene postavitve.

Slika 1. Zgornji levi kot kontrolne plošče se nahaja na (1, 1)

Razvil sem tudi naslednjo javnost Checker API:

  • Checker (CheckerType checkerType): Sestavite a Checker predmet navedenega checkerType (BLACK_KING, ČRNA_REGULARNA, RDEČE KRALJE, ali RDEČA_REGULARNA).
  • void draw (grafike g, int cx, int cy): Nariši a Checker z uporabo določenega grafičnega konteksta g s središčem čekera na (cx, cy). To metodo naj bi poklicali iz Odbor samo.
  • logična vsebina vsebuje (int x, int y, int cx, int cy): A statično pomožna metoda, poklicana iz Odbor ki določa, ali bodo koordinate miške (x, y) ležijo znotraj kontrolnika, katerega sredinske koordinate so določene z (cx, cy) in katerih dimenzija je določena drugje v Checker razred.
  • int getDimension (): A statično pomožna metoda, poklicana iz Odbor ki določa velikost dama, tako da lahko plošča ustrezno prilagodi svoje kvadrate in celotno velikost.

To v veliki meri pokriva vse knjižnice grafičnega uporabniškega vmesnika checkers glede na njihove vrste in njihove javne API-je. Zdaj se bomo osredotočili na to, kako sem uvedel to knjižnico.

Izvajanje knjižnice GUI za preverjanje

GUI knjižnica checkers je sestavljena iz štirih javnih vrst, ki se nahajajo v istoimenskih izvornih datotekah: AlreadyOccupiedException, Odbor, Checker, in CheckerType. Seznam 1 predstavlja AlreadyOccupiedExceptionizvorna koda.

Seznam 1. AlreadyOccupiedException.java

javni razred AlreadyOccupiedException razširja RuntimeException {public AlreadyOccupiedException (String msg) {super (msg); }}

AlreadyOccupiedException podaljša java.lang.RuntimeException, kar naredi AlreadyOccupiedException nepreverjena izjema (ni je treba ujeti ali prijaviti v meti klavzula). Če bi hotel narediti AlreadyOccupiedException preverjeno, podaljšal bi java.lang.Exception. Za to vrsto sem se odločil, da deluje nepreverjeno, ker deluje podobno kot nepreverjeno IllegalArgumentException.

AlreadyOccupiedException razglasi konstruktor, ki sprejme nizni argument, ki opisuje razlog za izjemo. Ta argument se posreduje RuntimeException superrazred.

Seznam 2 predstavlja Odbor.

Seznam 2. Board.java

uvoz java.awt.Color; import java.awt.Dimension; uvoz java.awt.Graphics; uvoz java.awt.Graphics2D; uvoz java.awt.RenderingHints; import java.awt.event.MouseEvent; uvoz java.awt.event.MouseAdapter; uvoz java.awt.event.MouseMotionAdapter; uvoz java.util.ArrayList; uvoz java.util.List; uvoz javax.swing.JComponent; javni razred Board razširja JComponent {// dimenzija kvadrata (25% večja od checkerja) private final static int SQUAREDIM = (int) (Checker.getDimension () * 1.25); // dimenzija šahovnice (širina 8 kvadratov) private final int BOARDDIM = 8 * SQUAREDIM; // prednostna velikost komponente plošče private Dimension dimPrefSize; // vlečna zastavica - nastavljena na true, ko uporabnik pritisne gumb miške na preverjevalnik // in odstranjena na false, ko uporabnik sprosti zasebni logični gumb inDrag = false; // premik med koordinatami vlečnega zagona in koordinatami centra preverjanja private int deltax, deltay; // sklic na pozicioniran preverjevalec na začetku povlečenja zasebnega PosCheck posCheck; // osrednja lokacija pregledovalnika na začetku povlečenja private int oldcx, oldcy; // seznam predmetov Checker in njihovi začetni položaji private List posChecks; javni odbor () {posChecks = nov ArrayList (); dimPrefSize = nova dimenzija (BOARDDIM, BOARDDIM); addMouseListener (new MouseAdapter () {@Override public void mousePress (MouseEvent me) {// Pridobi koordinate miške v času pritiska. int x = me.getX (); int y = me.getY (); // Poiščite pozicioniran kontrolnik pod pritiskom miške. for (PosCheck posCheck: posChecks) if (Checker.contens (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;}} @Override public void mouseReleased (MouseEvent me) {// Ko je miš sproščena, počistite inDrag (za // pomeni, da ni povlečenja v teku), če je inDrag // že nastavljen. if (inDrag) inDrag = false; else return; // Snap checker v sredino kvadrata. int x = me.getX (); int y = me.getY (); posCheck .cx = (x - deltax) / SQUAREDIM * SQUAREDIM + SQUAREDIM / 2; posCheck.cy = (y - deltay) / SQUAREDIM * SQUAREDIM + SQUAREDIM / 2; // Ne premikajte dame na zasedeni kvadrat. za (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 = starost; } posCheck = null; prebarvati (); }}); // Na programček priključimo poslušalca gibanja miške. Ta poslušalec // posluša dogodke vlečenja miške. addMouseMotionListener (new MouseMotionAdapter () {@Override public void mouseDragged (MouseEvent me) {if (inDrag) {// Posodobi lokacijo centra za preverjanje. posCheck.cx = me.getX () - deltax; posCheck.cy = me.getY ( ) - deltay; prebarvaj ();}}}); } public void add (Checker checker, int row, int col) {if (vrstica 8) vrže novo IllegalArgumentException ("vrstica izven obsega:" + vrstica); če (col 8) vrže novo IllegalArgumentException ("col out of range:" + col); PosCheck posCheck = nov PosCheck (); posCheck.checker = preveritelj; posCheck.cx = (col - 1) * SQUAREDIM + SQUAREDIM / 2; posCheck.cy = (vrstica - 1) * SQUAREDIM + SQUAREDIM / 2; za (PosCheck _posCheck: posChecks), če (posCheck.cx == _posCheck.cx && posCheck.cy == _posCheck.cy) vrže nov AlreadyOccupiedException ("kvadrat pri (" + vrstica + "," + col + ") je zaseden" ); posChecks.add (posCheck); } @Override public Dimension getPreferredSize () {return dimPrefSize; } @Override protected void paintComponent (Graphics g) {paintCheckerBoard (g); za (PosCheck posCheck: posChecks) if (posCheck! = Board.this.posCheck) posCheck.checker.draw (g, posCheck.cx, posCheck.cy); // Nazadnje narišite povlečeni preverjevalnik, tako da se prikaže nad katerim koli temeljnim // preverjalnikom. if (posCheck! = null) posCheck.checker.draw (g, posCheck.cx, posCheck.cy); } private void paintCheckerBoard (Graphics g) {((Graphics2D) g) .setRenderingHint (RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); // Prebarvaj šahovnico. za (int vrstica = 0; vrstica <8; vrstica ++) {g.setColor (((vrstica & 1)! = 0)? Color.BLACK: Color.WHITE); for (int col = 0; col <8; col ++) {g.fillRect (col * SQUAREDIM, vrstica * SQUAREDIM, SQUAREDIM, SQUAREDIM); g.setColor ((g.getColor () == Color.BLACK)? Color.WHITE: Color.BLACK); }}} // pozicijski razred pomožnega razreda checker zasebni razred PosCheck {javni Checker checker; javni int cx; javni int cy; }}

Odbor podaljša javax.swing.JComponent, kar naredi Odbor Swing komponenta. Kot tak lahko neposredno dodate Odbor komponento v podokno z vsebino aplikacije Swing.

Odbor izjavlja SQUAREDIM in BOARDDIM konstante, ki določajo dimenzije pikslov kvadrata in kontrolne plošče. Pri inicializaciji SQUAREDIM, Prikličem Checker.getDimension () namesto dostopa do enakovredne javnosti Checker konstanten. Joshua Block odgovarja, zakaj to počnem, v postavki št. 30 (namesto int konstante) druge izdaje njegove knjige, Učinkovita Java: "Programi, ki uporabljajo int enum vzorec so krhki. Ker int enumi so konstante časa prevajanja in so zbrane v odjemalcih, ki jih uporabljajo. Če je int povezana s konstanto enum spremenjena, je treba njene stranke ponovno sestaviti. Če niso, bodo še vedno kandidirali, vendar njihovo vedenje ne bo določeno. "

Zaradi obsežnih komentarjev o tem ne bi imel kaj več povedati Odbor. Vendar upoštevajte ugnezdene PosCheck razred, ki opisuje nameščen preglednik s shranjevanjem datoteke Checker referenca in njene sredinske koordinate, ki so glede na zgornji levi kot Odbor komponenta. Ko dodate Checker ugovarjajo Odbor, shranjeno je v novem PosCheck predmet skupaj s središčnim položajem pregledovalnika, ki se izračuna iz podane vrstice in stolpca.

Seznam 3 predstavlja Checker.

$config[zx-auto] not found$config[zx-overlay] not found