//**************************//
//Vier gewinnt © t.heyn 2000//
//**************************//
import java.awt.*;
import java.awt.event.*;
import java.applet.*;
public class VierGewinntApplet extends Applet implements ActionListener, ItemListener
{
final int GROESSE=50, HOEHE=6, BREITE=7, STRICH=10, ZEIT=40;
final int ANFAENGER=1, NORMALO=2, PROFI=3, ROT=1, BLAU=2;
final String kommentar[] = {"Viel Glück!!","Rot Gewinnt!","Blau gewinnt!","Unentschieden",
"Weiter so!","Gib alles!","Wow!","Nicht nachlassen!","Sehr gut!"};
final int testdaten[] =
{
0,0,-1,0,-2,0,-3,0, 1,0,0,0,-1,0,-2,0, 2,0,1,0,0,0,-1,0, 3,0,2,0,1,0,0,0, //waagrecht
0,0,-1,-1,-2,-2,-3,-3, 1,1,0,0,-1,-1,-2,-2, 2,2,1,1,0,0,-1,-1, 3,3,2,2,1,1,0,0, //diagonal
0,0,-1,1,-2,2,-3,3, 1,-1,0,0,-1,1,-2,2, 2,-2,1,-1,0,0,-1,1, 3,-3,2,-2,1,-1,0,0, //diagonal
0,-3,0,-2,0,-1,0,0, 0,-2,0,-1,0,0,0,1, 0,-1,0,0,0,1,0,2, 0,0,0,1,0,2,0,3 //senkrecht
};//nach priorität geordnet
int feld[][] = new int[HOEHE][BREITE];
int zeichnen[][] = new int[HOEHE][BREITE];
int gefahr[][][] = new int[HOEHE][BREITE][ROT+BLAU];
int hoehe[] = new int[BREITE];
int prioritaet[] = new int[BREITE];
TextArea text= new TextArea("",15,12,TextArea.SCROLLBARS_NONE);
Choice anfang = new Choice();
Choice level = new Choice();
Image bild[] = new Image[3];
int werBeginnt=ROT;
int amZug=ROT;
int derLevel=ANFAENGER;
int sieger,total;
long startzeit, endzeit;
AudioClip yahoo, laugh, muh, boing, gong;
Sprite sprite[] = new Sprite[ROT+BLAU];
Image HintergrundBild = null;
Graphics HintergrundGrafik = null;
Dimension HintergrundGroesse = null;
FallThread fallThread;
public void init()
{
laden();
showStatus("Vier gewinnt © t.heyn 2000");
addMouseListener(new MyMouse()); //GUI erstellen
setLayout(new BorderLayout());
Panel anzeige = new Panel();
anzeige.setLayout(new BorderLayout());
add("East",anzeige);
Label titel = new Label("Vier gewinnt",Label.CENTER);
titel.setBackground(Color.yellow);
titel.setFont(new Font("SansSerif",Font.BOLD,18));
anzeige.add("North",titel);
anzeige.add("Center",text);
text.setEnabled(false);
Panel controls = new Panel();
controls.setLayout(new BorderLayout());
anzeige.add("South",controls);
anfang.add("Rot beginnt");
anfang.add("Blau beginnt");
anfang.addItemListener(this);
controls.add("Center",anfang);
level.add("Anfänger");
level.add("Normalo");
level.add("Profi");
level.addItemListener(this);
controls.add("North",level);
Button neu= new Button("Neues Spiel");
neu.addActionListener(this);
controls.add("South",neu);
sprite[ROT] = new Sprite(bild[ROT],0,0);
sprite[BLAU] = new Sprite(bild[BLAU],0,0);
neuesSpiel();
}
public void paint(Graphics g) //aktuelles applet zeichnen
{
sprite[ROT].paint(g);
sprite[BLAU].paint(g);
for (int s=0;s<BREITE;s++)
{
for (int z=0;z<HOEHE;z++)
{
g.drawImage(bild[0],s*(GROESSE+STRICH),(HOEHE-z-1)*(GROESSE+STRICH),this);
if (zeichnen[z][s] != 0)
g.drawImage(bild[zeichnen[z][s]],STRICH+s*(GROESSE+STRICH),STRICH+(HOEHE-z-1)*(GROESSE+STRICH),this);
}
}
}
public final void update(Graphics g) //Flimmerfreie Grafik mit Double Buffering
{
Dimension dim = getSize();
if((HintergrundBild==null) || (dim.width != HintergrundGroesse.width) || (dim.height != HintergrundGroesse.height))
{
HintergrundBild = createImage(dim.width, dim.height);
HintergrundGroesse = dim;
HintergrundGrafik = HintergrundBild.getGraphics();
}
HintergrundGrafik.clearRect(0, 0, HintergrundGroesse.width, HintergrundGroesse.height);
paint(HintergrundGrafik);
g.drawImage(HintergrundBild,0,0,null);
}
public void start()
{
FallThread fallThread=new FallThread();
fallThread.start();
}
public void stop()
{
if (fallThread != null) fallThread.interrupt();
}
public void itemStateChanged(ItemEvent e) // all die doofen listener
{
String farbe=(String) anfang.getSelectedItem();
if (farbe=="Rot beginnt") werBeginnt=ROT;
if (farbe=="Blau beginnt") werBeginnt=BLAU;
String grad=(String) level.getSelectedItem();
if (grad=="Anfänger") derLevel=ANFAENGER;
if (grad=="Normalo") derLevel=NORMALO;
if (grad=="Profi") derLevel=PROFI;
neuesSpiel();
}
public void actionPerformed(ActionEvent e)
{
neuesSpiel();
}
private class MyMouse extends MouseAdapter
{
public void mousePressed(MouseEvent e)
{
schreiben(kommentar[sieger]);
int s=(int)((e.getX()-(STRICH/2))/(GROESSE+STRICH));
if (s>=BREITE || hoehe[s]>=HOEHE || sieger>0 || sprite[ROT].isMoving || sprite[BLAU].isMoving) return;
sieger=siegtest(ROT,s);
setzen(ROT,s);
if (total==HOEHE*BREITE && sieger==0) sieger=3;
kommentar[0]=kommentar[(int)(Math.random()*4+4)];
schreiben(kommentar[0]);
if (sieger>0) schluss();
}
}
private class FallThread extends Thread
{
public void run()
{
while (! isInterrupted())
{
if (! sprite[amZug].isMoving) continue;
startzeit = System.currentTimeMillis();
//bewegen
sprite[amZug].setSpeed(sprite[amZug].getSpeed()+3);//fall beschleunigen
sprite[amZug].tick();
//wenn unten kommt anderer dran
int spalte = (int)((sprite[amZug].x - GROESSE/2 - STRICH)/(GROESSE+STRICH));
if (sprite[amZug].y>=(HOEHE-hoehe[spalte])*(GROESSE+STRICH)+(GROESSE/2))
{
sprite[amZug].stopMovement();
sprite[amZug].setSpeed(1);
sprite[amZug].y=-GROESSE;
zeichnen[hoehe[spalte]-1][spalte]=amZug;
update(getGraphics());
amZug=3-amZug;
if(boing != null) boing.play();
if (amZug==BLAU && sieger==0)
{
sieger=computerZugBerechnen();
if (total==HOEHE*BREITE && sieger==0) sieger=3;
if (sieger>0) schluss();
}
}
//schlafen
try
{
update(getGraphics());
endzeit = System.currentTimeMillis(); //nur solange schlafen wie noetig
if (endzeit - startzeit < ZEIT) sleep(ZEIT - endzeit + startzeit);
}
catch (Exception e)
{
break;
}
}
}
}
private void neuesSpiel()
{
if (gong != null) gong.play();
total=0;
sieger=0;
for (int farbe=ROT;farbe<=BLAU;farbe++)
{
sprite[farbe].setPosition(0,-GROESSE);
sprite[farbe].stopMovement();
sprite[farbe].setSpeed(1);
}
for (int s=0;s<BREITE;s++)
{
for (int z=0;z<HOEHE;z++)
{
feld[z][s]=0;
zeichnen[z][s]=0;
gefahr[z][s][ROT ]=0;
gefahr[z][s][BLAU]=0;
}
hoehe[s]=0;
}
repaint();
schreiben(kommentar[sieger]);
amZug=werBeginnt;
if (amZug==BLAU) setzen(BLAU,(int)(Math.random()*BREITE));
}
private int computerZugBerechnen() //berechnet den besten zug für den computer
{
int s;
int dringendste=-90;
if (derLevel != ANFAENGER) gefahrtest(); //testet ganzes brett nach gefahren ab
for (s=0;s<BREITE;s++) //tests für jede spalte einzeln
{
prioritaet[s]=0; //standardpriorität der spalte
if (hoehe[s]==HOEHE) //test ob spalte voll
{
prioritaet[s]=-1000;
continue;
}
//tests level anfänger
if (prioritaet[s]==0)
{
if (siegtest(BLAU,s)==BLAU) //siegtest -> sofort setzen
{
setzen(BLAU,s);
return BLAU;
}
if (siegtest(ROT,s)==ROT) //siegtest -> sofort setzen
{
setzen(BLAU,s);
return 0;
}
if (tabutest(ROT,s)) //test ob spalte tabu -> nächste spalte
{
prioritaet[s]=-90;
continue;
}
}
//tests level normalo
if (derLevel != ANFAENGER)
{
if (hoehe[s]==0) prioritaet[s]=-10; //test auf leere spalte
if (tabutest(BLAU,s)) prioritaet[s]=-85; //test ob chance selbst verbaut
if (prioritaet[s]>-80) prioritaet[s]+=20*naechsterZugTest(ROT,s);
}
//tests level profi
if (derLevel==PROFI)
{
if (doppeltest(BLAU,s)) prioritaet[s]=200; //forcieren wenn 2 blaue übereinander
if (prioritaet[s]>-80)
{
if (werBeginnt==ROT && hoehe[s]%2==1) prioritaet[s] += 5;//besser in ungerade zeilen
if (werBeginnt==BLAU && hoehe[s]%2==0) prioritaet[s] += 5;
prioritaet[s]+=25*naechsterZugTest(BLAU,s);
prioritaet[s]-=10*uebernaechsterZugTest(BLAU,s);
}
}
if (prioritaet[s]>=dringendste) dringendste=prioritaet[s];
}
//zufällig setzen in eine der spalten mit dringendster priorität
boolean suchen=true;
while (suchen)
{
s=(int)(Math.random()*BREITE);
if (prioritaet[s]==dringendste) suchen=false;
}
setzen(BLAU,s);
return 0;
}
private int siegtest(int farbe,int s) //testet, ob 4 geschafft
{
int anzahl=0;
int resultat=0;
int sieger=0;
feld[hoehe[s]][s]=farbe;
for (int i=0;i<4;i++)//4 richtungen
{
for (int j=0;j<4;j++)//4 positionen
{
anzahl=0;
for (int k=0;k<8;k+=2)//4*2 koordinaten
{
try
{
resultat=feld[hoehe[s]+testdaten[(32*i)+(8*j)+k+1]] [s+testdaten[(32*i)+(8*j)+k]];
if (resultat==farbe) anzahl++;
if (resultat==3-farbe) anzahl=0;
}
catch (ArrayIndexOutOfBoundsException e) {}
if (anzahl==4)
{
feld[hoehe[s]][s]=0;
sieger=farbe;
}
}
}
}
feld[hoehe[s]][s]=0;
return sieger;
}
private int naechsterZugTest(int farbe,int s) //testet den nächsten zug
{
int hTemp=0;
int anzahl=0;
feld[hoehe[s]][s]=farbe; //setzen
hoehe[s]++;
for (int sx=0;sx<BREITE;sx++) //anzahl entstehende siegpositionen zählen
{
if (hoehe[sx]==HOEHE) continue; //wenn spalte voll dann nächste
hTemp=hoehe[sx];
for (int h=hTemp;h<HOEHE;h++)
{
if (gefahr[h][sx][farbe]==farbe) continue;
feld[h][sx]=farbe;
hoehe[sx]=h;
if (siegtest(farbe,sx)==farbe) //anzahl gefahren der spalte erhöhen
{
anzahl++;
if (h>0 && h<HOEHE-1 && derLevel==PROFI) //test auf doppelsiegposition (wichtig!!)
{
if (gefahr[h+1][sx][farbe]==farbe || gefahr[h-1][sx][farbe]==farbe) anzahl=9;
}
}
feld[h][sx]=0;
}
hoehe[sx]=hTemp;
}
hoehe[s]--;
feld[hoehe[s]][s]=0;
return anzahl;
}
private int uebernaechsterZugTest(int farbe,int s) //testet den übernächsten zug
{
int hTemp=0;
int anzahl=0;
if (hoehe[s]<=HOEHE-2)
{
feld[hoehe[s]][s]=farbe;
hoehe[s]++;
anzahl=naechsterZugTest((3-farbe),s); //schauen, ob andere farbe gefahren schafft
hoehe[s]--;
feld[hoehe[s]][s]=0;
}
return anzahl;
}
private void gefahrtest() //testet, ob hier 4 erreicht werden könnten
{
int hTemp=0;
for (int s=0;s<BREITE;s++)
{
hTemp=hoehe[s];
for (int h=hTemp;h<HOEHE;h++)
{
hoehe[s]=h;
for (int farbe=BLAU;farbe>=ROT;farbe--)
{
feld[h][s]=farbe;
gefahr[h][s][farbe]=siegtest(farbe,s); //wenn gefahr, dann markieren
feld[h][s]=0;
}
}
hoehe[s]=hTemp;
}
}
private boolean tabutest(int farbe, int s) //testet, ob hier setzen verboten ist
{
boolean tabu=false;
if (hoehe[s]<HOEHE-1)
{
if (gefahr[hoehe[s]+1][s][farbe]==farbe) tabu=true;
}
return tabu;
}
private boolean doppeltest(int farbe, int s) //testet, ob blau eine doppelsiegposition hat
{
boolean doppelter=false;
for (int h=hoehe[s];h<HOEHE-1;h++)
{
if (gefahr[h][s][farbe]+gefahr[h+1][s][farbe]==2*farbe) doppelter=true;
}
return doppelter;
}
private void schluss()
{
schreiben(kommentar[sieger]);
if (sieger==ROT && yahoo != null) yahoo.play();
if (sieger==BLAU && laugh != null) laugh.play();
if (sieger==3 && muh != null) muh.play();
}
private void setzen(int farbe, int s)
{
feld[hoehe[s]][s]=farbe;
hoehe[s]++;
total++;
sprite[farbe].startMovement();
sprite[farbe].x = (int)(STRICH + GROESSE/2 + s*(GROESSE+STRICH));
}
private void schreiben(String kommentar)
{
text.setText("Wer zuerst vier waagrecht, senkrecht oder diagonal hat, gewinnt. Du hast Rot,"
+" der Computer Blau. Klicke in die Spalte, in welche du setzen willst.");
text.appendText("\n\n\n"+kommentar);
}
private void laden()
{
yahoo= getAudioClip(getCodeBase(),"yahoo.au");
muh= getAudioClip(getCodeBase(),"muh.au");
laugh= getAudioClip(getCodeBase(),"laugh.au");
boing= getAudioClip(getCodeBase(),"boing.au");
gong= getAudioClip(getCodeBase(),"gong.au");
MediaTracker tracker=new MediaTracker(this);
for (int i=0;i<=2;i++)
{
bild[i] = getImage(getCodeBase(),i+".gif");
tracker.addImage(bild[i],1);
}
try
{
tracker.waitForAll();
}
catch(InterruptedException e) {}
}
}