Archief - Schaken in java

Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.

MilM

Legacy Member
ter verduidelijking: ik heb ook de code in de jar file niet gezien.

Tenzij de move controls in de klasse zelf zitten, is er echt geen reden om een aparte klasse per stuk aan te maken. Zeker omdat er echt geen nieuw schaakstuk zal bijkomen ofzo in het volgend jaar.

Je doet gewoon iets in de aard van:
rooster[7][5] = new Schaakstuk("Paard", "Zwart");
//zwart kun je ook vervangen door boolean en paard door een int die gedefinieerd is door een final constante bijvoorbeeld

Om te tekenen doe je dan gewoon:

Schaakstuk stuk = rooster[x][y];
String backColor = getBackColor(x,y); //geeft bijvoorbeeld 'OnWhite' of 'OnBlack' terug afhankelijk van x en y
String filename = stuk.getType() + stuk.getColor() + backColor +".jpg"';

Die filename is dan bijvoorbeeld = 'PaardZwartOnWhite.jpg'


De enigste reden om verschillende klassen te maken in dit geval is als je verschillend gedrag implementeert. Dit zou dus de move controls kunnen zijn. In dat geval inderdaad overerving, maar dat verandert niets aan de code hierboven. (je moet nog steeds de hoofdklasse 'Schaakstuk' gebruiken hier en niet de subklasse)

cuinhel

Legacy Member
oke, ja die nieuwe classen, dat moet ik er wel in zetten. Omdat ik dit zo geleerd heb op school.

Het is misschien niet echt nodig in dit project, maar ik moet wel laten zien dat ik dit kan.

Nogmaals bedankt voor de hulp!

cuinhel

Legacy Member
hierbij krijg ik de fout : Schaakstuk is abstract; cannot be instantiated
rooster[1][0] = new Schaakstuk("Pion",1);

cuinhel

Legacy Member
ja dat is natuurlijk omdat ik dat in die class heb gedefinieerd.
abstract public class Schaakstuk
{
....


Maar dat moet toch als je erving gaat toepassen?

Arboris

Legacy Member
Niet noodzakelijk, alleen als je klasse echt MOET geërfd worden.

Zoals in het voorbeeld dat ik gaf:
pion/koning/toren ... die overerven van schaakstuk, je wilt dat ieder van deze implementaties de method 'controleerMove' bevat (dit is eigen aan schaakstuk), maar je kan uiteraard geen default implementatie geven in de class schaakstuk zelf. Daarom ga je de method abstract maken (en dus ook de class). Andere methods in 'schaakstuk' kunnen wel default geïmplementeerd worden.

Abstract Methods and Classes (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

En natuurlijk kan je ook niet-abstracte classes overerven; eenvoudigste voorbeeld is de class Object -> is niet abstract (Object API ), maar toch erft ieder object hiervan ;)

NeverwinterX

Legacy Member
cuinhel zei:
hierbij krijg ik de fout : Schaakstuk is abstract; cannot be instantiated
rooster[1][0] = new Schaakstuk("Pion",1);

Je bent nu beide oplossingen aan het mixen. Je zal moeten kiezen:
ofwel ga je voor een algemene klasse SchaakStuk (en geen subklassen Pion, Paard ...) en dan mag SchaakStuk niet abstract zijn
ofwel ga je voor overerving met superklasse SchaakStuk die abstract is en subklassen Pion, Paard ... SchaakStuk mag je dan natuurlijk niet instantieren, maak dan een concrete Pion, Paard enz aan.

MilM

Legacy Member
Inderdaad.

Dan is uw tabel (rooster) van het type 'Schaakstuk', maar steek je daarin subklassen.
Maw, rooster[1][0] = new Pion("Zwart")

En ben je zeker dat de leraar dit perse wilt?
Zoals gezegd, ik heb de code niet bekeken, maar ik vermoed dat de logica van movement niet in deze klassen zit? Indien je dat niet van plan bent, komt het wel redelijk raar over om subklassen te hebben die op geen enkel vlak verschillend zijn buiten de naam van de klasse.

Stel dat je bijvoorbeeld de klasse 'Wagen' hebt.

Indien je veel variabelen en specifiek gedrag gaat implementeren voor specifieke wagens, dan is het normaal dat je met overerving werkt.

Als je echter enkel het merk en model wil bijhouden, dan heb je één klasse Auto met de variabelen 'merk' en 'model' die je gewoon meegeeft aan de constructor.

Mocht je in dat laatste geval voor elk mogelijk model en merk een klasse moeten gaan aanmaken die uiteindelijk niets van variabelen heeft ...

cuinhel

Legacy Member
Het enigste wat de docent wil is een werkend spel dat ik zelf heb gemaakt op het einde van het semester. Maar ik dacht gewoon zelf dat erin te stoppen omdat we dat ook bij iets anders hadden gezien in de les. Dus het moet er helemaal niet in.

Als ik het goed begrijp dan, zijn al die classes niet nodig omdat enkel de beweging van de stukken anders is. En dit kan ik dan in mijn controller zetten. Dmv die instance off pion (dat hij dan de variabele pion heeft meegekregen). En dan zeggen welke stappen een pion mag doen.

Die manier lijkt me dan ook beter, ik had er zo niet over nagedacht.

Wolf2000me

Legacy Member
cuinhel zei:
Het enigste wat de docent wil is een werkend spel dat ik zelf heb gemaakt op het einde van het semester. Maar ik dacht gewoon zelf dat erin te stoppen omdat we dat ook bij iets anders hadden gezien in de les. Dus het moet er helemaal niet in.

Als ik het goed begrijp dan, zijn al die classes niet nodig omdat enkel de beweging van de stukken anders is. En dit kan ik dan in mijn controller zetten. Dmv die instance off pion (dat hij dan de variabele pion heeft meegekregen). En dan zeggen welke stappen een pion mag doen.

Die manier lijkt me dan ook beter, ik had er zo niet over nagedacht.

De simpelste oplossing is bijna altijd de beste. Maar dat neemt ni weg dat je mogelijk ooit wel specifiek gedrag aan je stukken gaat willen toekennen waardoor je wel liever overerving zou toepassen. Maar da's eigenlijk al bij al nog redelijk snel aangepast als het nodig zou blijken. Ik denk dat eender welke approach daarin wel ok is, nu toch.

Wat ik nog zou aanraden voor het eerste geval zonder overerving is ergens een "enum" aan te maken waar je de namen van je stukken in stockeert. Bv. als public inner class in je Schaakstuk class. Je kan zo'n enum een beetje vergelijken met een collection van constanten. Dit heeft dan wel het voordeel dat het een type heeft zoals elke andere class. Op die manier kan je dan verplichten in je constructor om een enum type mee te geven. Anders kan je een Schaakstuk maken dat "Koe" of dergelijke nonsens heet.

Code:
public enum Voorbeeld {
        VOORBEELD1("Voorbeeld 1"),VOORBEELD2("Voorbeeld2"); //...
        
        //enum constructor
        Voorbeeld(String naam){
            this.naam = naam;    
        }
        
        private String naam;

        public String getNaam() {
            return naam;
        }
    }
    
    public class GebruiksVoorbeeld{
        
        private String gebruiksNaam;
        
        //hier verplicht je jezelf van een Voorbeeld enum object mee te geven.
        public GebruiksVoorbeeld(Voorbeeld voorbeeld){
            this.gebruiksNaam = voorbeeld.getNaam();   
        }
    }

Dit laatste is imo wel een "nice to have" terwijl je functionaliteit zelf uiteraard een "must have" is. Groot verschil tussen de twee. Maar het laat wel zien aan je leraar dat je aan meerdere dingen denkt dan zuiver functioneel ;)

Ik denk ook dat je met gebruik van gewone arrays wel goed zit. Je ziet dat zo vaak niet meer in de praktijk omwille van Collections, wat tal van voordelen oplevert. Maar natuurlijk ook weer extra overhead en gedrag per soort collectie. Dat is natuurlijk niet nodig.

1 ding nog. Als je code post, wat een goeie zaak is, zet deze dan in de "code" tags, da's gemakkelijker om te lezen.

Arboris

Legacy Member
Voordeel van een enum is ook dat je die in een switch kunt gebruiken, kan je die if-structuur wat opkuisen :)

cuinhel

Legacy Member
hoi allemaal,

Ik heb het eff wat druk gehad, maar ben nu terug vollop bezig aan men spel :)

Maar ik heb weer een fout waar ik niet vanaf geraak. Dit is bij mijn mouselistener. Ik krijg een exception maar weet niet waarom.

code:

import java.awt.event.*;

public class Controller implements MouseListener
{
private View view;
private Level level;
private int z, f, breedte;

public Controller(Level level, View view)
{
level = level;
view = view;
z = 0;
f = 0;
view.addMouseListener(this);

}

public void mousePressed(MouseEvent e)
{
try
{
level.setCoordinaten(e.getX(), e.getY());
}

catch(Exception f)
{
System.out.println("some Exception");
}

}
public void mouseExited(MouseEvent e)
{

}
public void mouseClicked(MouseEvent e)
{
}
public void mouseEntered(MouseEvent e)
{
}
public void mouseReleased(MouseEvent e)
{
try
{

level.beweeg(e.getX(),e.getY());
}
catch(Exception f)
{
}
}
}

De errors komen als ik mijn muis indruk in het scherm en loslaat.

Arboris

Legacy Member
Wat is de stacktrace die je krijgt? (je slikt nu exceptions in, is niet altijd een goeie zaak :) Wat je wel al kunt doen, is ipv System.out.println(some string) te doen, gewoon de stacktrace naar je console sturen (door f.printStackTrace(); op te roepen; dit onderbreekt je programma nog altijd niet, maar geeft wel een hoop meer informatie)

In je constructor maak je een fout: je assignt level aan level (beide dezelfde, lokale variabele); hierdoor blijft de class variabele level null.

Hierdoor krijg je dus nullpointers.

Hoe dan wel?
Code:
this.level = level
Uitleg (altijd duidelijk dan dat ik het zelf zou proberen :) ): Using the this Keyword (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

cuinhel

Legacy Member
dat was inderdaad een van de fouten

de andere fouten zitten blijkbaar in men level


Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 318
at Level.beweeg(Level.java:85)
at Controller.mouseReleased(Controller.java:45)
at java.awt.Component.processMouseEvent(Component.java:6289)
at java.awt.Component.processEvent(Component.java:6054)
at java.awt.Component.dispatchEventImpl(Component.java:4652)
at java.awt.Component.dispatchEvent(Component.java:4482)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:644)
at java.awt.EventQueue.access$000(EventQueue.java:85)
at java.awt.EventQueue$1.run(EventQueue.java:603)
at java.awt.EventQueue$1.run(EventQueue.java:601)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:98)
at java.awt.EventQueue$2.run(EventQueue.java:617)
at java.awt.EventQueue$2.run(EventQueue.java:615)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:614)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)

public void setCoordinaten( int z, int f)
{
z = z/80;
f = f/80;

}

public void beweeg (int r, int o)
{

Schaakstuk vw = rooster[z][f];
if(vw instanceof Pion)
{
Pion pion = (Pion)vw;
rooster[r][o] = vw;
rooster[z][f] = null;
}
}

Arboris

Legacy Member
Als regel 85 -> Schaakstuk vw = rooster[z][f];
z of f is 318
Als regel 85 -> rooster[r][o] = vw;
r of o is 318

Kan je debuggen met je IDE? Dan kan je kijken waar dat getal vandaan komt. En anders moet je het doen met system outs.

MilM

Legacy Member
Bij uw mouseReleased gebruik je de X en Y positie van de muis rechtstreeks in uw tabel in de beweeg methode.

Je moet die r en o ook delen door 80 veronderstel ik.

Ik veronderstel dat je die 80 trouwens uitgerekend hebt aan de hand van de fixed grootte van uw View?

Je kan trouwens ook overwegen om met MouseClicked te werken. Is mss handiger voor een gebruiker dat hij eerst op het schaakstuk klikt en daarna op de bestemming? (zonder dus ingedrukt te moeten houden)

cuinhel

Legacy Member
MilM zei:
Bij uw mouseReleased gebruik je de X en Y positie van de muis rechtstreeks in uw tabel in de beweeg methode.

Je moet die r en o ook delen door 80 veronderstel ik.

Ik veronderstel dat je die 80 trouwens uitgerekend hebt aan de hand van de fixed grootte van uw View?

Je kan trouwens ook overwegen om met MouseClicked te werken. Is mss handiger voor een gebruiker dat hij eerst op het schaakstuk klikt en daarna op de bestemming? (zonder dus ingedrukt te moeten houden)

je hebt gelijk!!
man man zo dom, en daar heb ik zo lang achter liggen zoeken xD

Ja dat is idd makkelijker, alleen om het te programmeren vind ik wat moeilijker.
Misschien een tip?

Moet ik dan als ik klik iets true maken, en dan als ik nog eens klik ook kijken bij elk stuk als er iets true is geworden?

cuinhel

Legacy Member
nog een gek probleem, als ik een pion beweeg, kan ik daarna geen meer bewegen :s

dus ik kan maar 1 x een zet doen, and thats it

Arboris

Legacy Member
Dat zou inderdaad een oplossing kunnen zijn, in 'Schaakstuk' een variabele 'activated' bijhouden, en die dan iedere keer op- of afzetten. (dat laatste zeker niet vergeten :P )

Kan je nog fancy gaan; als er een 2e keer gedrukt wordt, zet je activated terug af; verander background van activated stukken;... :)

Zet anders uw code nog eens online, is gemakkelijker om te volgen :)

MilM

Legacy Member
Kan met boolean, maar hoeft niet.

Je houdt ergens de waarde bij van waar geklikt werd. Bijvoorbeeld private int r en private int c (van row en column).

In mouseClicked() werk je met drie if/else lussen.
Pak dat x en y de positie van de muis is gedeeld door 80.

if(r == 0 || c == 0)
Indien zo: er is nog geen vakje geklikt, dus r = y en c = x

else if(r == y && c == x)
User klikt op zelfde vakje nog eens -> user wil zijn selectie dus cancellen
doe r == 0 en c ==0

else
Beweeg stuk van r,c naar y,x
zet r en c terug op 0

cuinhel

Legacy Member
MilM zei:
Kan met boolean, maar hoeft niet.

Je houdt ergens de waarde bij van waar geklikt werd. Bijvoorbeeld private int r en private int c (van row en column).

In mouseClicked() werk je met drie if/else lussen.
Pak dat x en y de positie van de muis is gedeeld door 80.

if(r == 0 || c == 0)
Indien zo: er is nog geen vakje geklikt, dus r = y en c = x

else if(r == y && c == x)
User klikt op zelfde vakje nog eens -> user wil zijn selectie dus cancellen
doe r == 0 en c ==0

else
Beweeg stuk van r,c naar y,x
zet r en c terug op 0

Ik denk dat dit idd wel een goede oplossing is :D bedankt!
ik ga het zo proberen, en daarna men code nog eens uploaden
Het archief is een bevroren moment uit een vorige versie van dit forum, met andere regels en andere bazen. Deze posts weerspiegelen op geen enkele manier onze huidige ideeën, waarden of wereldbeelden en zijn op sommige plaatsen gecensureerd wegens ontoelaatbaar. Veel zijn in een andere tijdsgeest gemaakt, al dan niet ironisch - zoals in het ironische subforum Off-Topic - en zouden op dit moment niet meer gepost (mogen) worden. Toch bieden we dit archief nog graag aan als informatiedatabank en naslagwerk. Lees er hier meer over of start een gesprek met anderen.
Terug
Bovenaan