Batch 4 gewinnt

batch

Newbie
Registriert
Okt. 2014
Beiträge
3
Hallo Leute,

ich habe eine Batch Datei geschrieben mit der man 4 gewinnt spielen kann (Mensch vs. Mensch).
Dass einzige was noch fehlt, ist das der Computer sagt wann wer gewonnen hat. Eine Möglichkeit wäre alle mögliche gewinn
Formationen als if abfrage hinzuschreiben, aber es gibt glaub ich über Millionen Möglichkeiten zu gewinn. da würde des doch sehr lang gehen.

ich bitte um schnellen Rat!!!

Lg Batch
 
Schau doch mal wie es andere gelöst haben. Gibt sicher etliche Beispielprogramme im Netz.
Ich würde auf die schnelle wohl nach jedem Zug checken, ob nun in alle Richtungen 4 in einer Reihe liegen, aber das nur grad so schnell überlegt. Also: Zug gemacht, Horizontal, Vertikal, und Diagonal prüfen.
Ob es clever ist, keine Ahnung.
 
Wow, Vier gewinnt ausgerechnet in Batch, das würde ich mir nicht antun.
Ich hab irgendwann auch mal Vier gewinnt als Spielerei programmiert, allerdings in Delphi (wenn du willst, kann ich dir den Code geben.)

Die sinnvollste Variante um auf Gewinn zu prüfen dürfte m.E. sein, nach jedem Zug die komplette Reihe, Spalte, sowie die beiden Diagonalen, die den gelegten Stein enthalten, von vorne durchzuprüfen. D.h. für jede Richtung fängst du vorne an und zählst einfach immer mit, ob ein Stein des Spielers liegt, liegt keiner, setzt du den Zähler wieder auf null.
 
Ich glaube des was ihr meint ist tic tac toe.
Bei vier gewinnt hat mein ein Feld 6x7 also 42 Felder und wenn man vier in einer Reihe hat gewinnt man

Ps. Es gibt sogar Monopoly für batch
 
Natürlich wissen wir was 4-gewinnt ist. Lies dir unsere Posts noch einmal durch und überlege noch einmal wie wir das meinen.
Nach jedem Zug schaust du nach links und rechts ob 4 in einer Reihe liegen, nach oben und unten ob vier Stück gestapelt sind, oder eben ob vier quer liegen. Und fertig bist du.
 
Was werden wir Tic-Tac-Toe meinen? Diese Unterstellung ist ja fast schon beleidigend ;)

Aber grundlegend ist die Prüfung bei Tic-Tac-Toe und Vier gewinnt nunmal dieselbe.
Wenn du dir Rechenzeit sparen willst, kannst du auch vom gelegten Stein nur jeweils 3 nach rechts und links gehen, beim Standardfeld der Größe 7x6 kann man sich das aber sparen.
 
sorry hab euch falsch verstanden :D

kannst du mir mal Beispiel schicken simpsonsfan?
währe mir eine große Hilfe :D
 
Monopoly in Batch klingt sogar noch blöder als 4-Gewinnt-für Batch =) Und nein hier verwechselt keiner Tic-Tac-Toe mit 4-Gewinnt, der Unterschied ist ja ein ganzer Stein mehr zum Gewinn ;) Der Lösungsalgorithmus ist allerdings grundsätzlich der gleiche. Wenn man es richtig macht sollte man sogar ganz einfach aus deinem 4-Gewinnt ein Tic-Tac-Toe oder ein 42-Gewinnt machen ;)

Ich gehe mal davon aus das du dein Spielfeld als Matrize angelegt hast, dann kannst du ja beim legen eines Steins eben einfach prüfen ob in eine oder mehreren Richtungen schon Steine des Spielers liegen, wenn ja die gleiche Überprüfung für diese Stelle auch machen (das ganze natürlich rekursiv). Als Input brauchst du ja einfach die Siegbedingung und die Spielfeld-Grenzen. Die Spielmechanik das ein Stein nur runterfallen kann und nicht gelegt werden kann wird vorgeschaltet(und ausschaltbar). Und so haste das ultimative ?-Gewinnt, was sogar Tic-Tac-Toe kann.
 
OK, kannst du haben, Delphi ist als Pascalableger ja sehr nahe an Pseudocode und sollte damit ganz gut lesbar sein.

Code:
unit vier_U;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls, Spin;

type
  TForm1 = class(TForm)
    PaintBox1: TPaintBox;
    Button1: TButton;
    Label1: TLabel;
    SpinEdit1: TSpinEdit;
    SpinEdit2: TSpinEdit;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    CheckBox1: TCheckBox;
    Timer1: TTimer;
    procedure Button1Click(Sender: TObject);
    procedure PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
      Shift: TShiftState; X, Y: Integer);
    procedure PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
      Y: Integer);
    procedure CheckBox1Click(Sender: TObject);
    procedure FormActivate(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    type tfeldarray = array[1..22,1..13] of integer;
  private
    { Private-Deklarationen }
    linetrisaktiv, fallen, fertig: boolean;
    spieler, zählkette, breite, höhe, poswin: integer;
    spielfeld: tfeldarray;
  const
  {  abstand=8;
    kästchen=abstand*8;
    gewinnlänge=4;
    breite=14;
    höhe=11;    }

  public
    { Public-Deklarationen }
  end;


type tfeldarray = array[1..22,1..13] of integer;

const
  abstand=8;
  kästchen=abstand*8;
  gewinnlänge=4;

var
  Form1: TForm1;
  weiter, hell: boolean;
  xpos, ypos, richtung : integer;
  farbeaktiv: integer;

implementation

{$R *.dfm}


procedure gitterzeichnen(Feld: Tpaintbox; breite, höhe, kästchen, abstand : integer);
var i,j: integer;
begin
  with Feld.canvas do
   begin
    brush.Color := rgb(0,121,187);
    pen.Color := rgb(0,123,190);
    rectangle(0,0,(kästchen+abstand)*(breite)+abstand,(kästchen+abstand)*(höhe)+abstand);
    brush.Color := clbtnface;
    for I := 0 to (breite-1) do
      for j := 0 to (höhe-1) do
        begin
          Ellipse(i*(kästchen+abstand)+abstand, j*(kästchen+abstand)+abstand, i*(kästchen+abstand)+abstand+kästchen, j*(kästchen+abstand)+abstand+kästchen);
        end;
   end;
end;

procedure kreisezeichnen(Feld: Tpaintbox; feldarray: tform1.tfeldarray; breite, höhe, kästchen, abstand : integer);
var i, j: integer;
begin
  for I := 1 to breite do
    for j := 1 to höhe do
      begin
        case feldarray[i,j] of
          1: begin
              feld.Canvas.Brush.color := clred;
              feld.Canvas.Ellipse((i-1)*(kästchen+abstand)+abstand, (j-1)*(kästchen+abstand)+abstand, (i-1)*(kästchen+abstand)+abstand+kästchen, (j-1)*(kästchen+abstand)+abstand+kästchen);
             end;
          2: begin
              feld.Canvas.Brush.color := clblue;
              feld.Canvas.Ellipse((i-1)*(kästchen+abstand)+abstand, (j-1)*(kästchen+abstand)+abstand, (i-1)*(kästchen+abstand)+abstand+kästchen, (j-1)*(kästchen+abstand)+abstand+kästchen);
             end;
        end;
      end;
end;

procedure gewonnen(player, Position, feldx, feldy: integer);
var i: integer;
begin
  weiter:=false;
  case player of
    1: begin
         application.MessageBox('Spieler 1 (rot) gewinnt', 'Spielende');
         farbeaktiv:= clred;
       end;
    2: begin
         application.MessageBox('Spieler 2 (blau) gewinnt', 'Spielende');
         farbeaktiv:=clblue;
       end;
  end;

  case richtung of
    1: begin
         xpos:= (feldx-gewinnlänge+1+position)-1;
         ypos:= feldy-1;
        end;
    2: begin
         xpos:= feldx-1;
         ypos:= (feldy-gewinnlänge+1+position)-1;
        end;
    3: begin
         xpos:= (feldx-gewinnlänge+1+position)-1;
         ypos:= (feldy-gewinnlänge+1+position)-1;
        end;
    4: begin
         xpos:= (feldx+gewinnlänge-1-position)-1;
         ypos:= (feldy-gewinnlänge+1+position)-1;
        end;
  end;

end;

procedure TForm1.Button1Click(Sender: TObject);
var i,j : integer;
begin
breite:=spinedit1.value;
höhe:=spinedit2.value;
form1.ClientWidth := (kästchen+abstand)*(breite)+abstand+32;
form1.ClientHeight := (kästchen+abstand)*(höhe)+abstand+71;
paintbox1.Width := (kästchen+abstand)*(breite)+abstand;
paintbox1.Height := (kästchen+abstand)*(höhe)+abstand;
button1.Top := (kästchen+abstand)*(höhe)+abstand+20;
button1.Left := 16;
label2.Top := (kästchen+abstand)*(höhe)+abstand+25;
label2.Left := 110;
label3.Top := (kästchen+abstand)*(höhe)+abstand+47;
label3.Left := 110;
label4.Top := (kästchen+abstand)*(höhe)+abstand+49;
label4.Left := 18;
spinedit1.Top := (kästchen+abstand)*(höhe)+abstand+22;
spinedit1.Left := 144;
spinedit2.Top := (kästchen+abstand)*(höhe)+abstand+44;
spinedit2.Left := 144;
Checkbox1.Top := (kästchen+abstand)*(höhe)+abstand+25;
Checkbox1.Left := 196;


paintbox1.refresh;
for I := 1 to breite do
  for j := 1 to höhe do
    spielfeld[i,j]:=0;

//zeichnen gitter
gitterzeichnen(paintbox1, breite, höhe, kästchen, abstand);
//ende gitter

//spiel beginnnen
weiter:=true;
spieler:=1;
for I := 1 to breite do spielfeld[i, höhe] := -1;
label4.Font.Color := clred;
label4.Caption:='Spieler 1 am Zug';
fertig:=false;
timer1.Enabled:=false;

end;

procedure TForm1.CheckBox1Click(Sender: TObject);
begin
  case checkbox1.checked of
    true: linetrisaktiv:=true;
    false: linetrisaktiv:=false;
  end;
end;

procedure TForm1.FormActivate(Sender: TObject);
begin
  breite:=spinedit1.value;
  höhe:=spinedit2.value;
  paintbox1.refresh;
  gitterzeichnen(paintbox1, breite, höhe, kästchen, abstand);
  kreisezeichnen(paintbox1, spielfeld, breite, höhe, kästchen, abstand);
end;

procedure TForm1.PaintBox1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
var feldx, feldy, i, j, linetris, farbe : integer;
begin
  if weiter then
    begin
      feldx := round((X-abstand) div (kästchen+abstand))+1;
      feldy := 1; //round((Y-abstand) div (kästchen+abstand))+1;

      if spielfeld[feldx, feldy] = 0 then repeat
                                             feldy :=feldy+1
                                          until spielfeld[feldx, feldy] = -1; //stein soll in der Spalte fallen

      if spielfeld[feldx, feldy] = -1 then  //prüfung ob das Feld unten liegt (-1) setzbar
         begin
               spielfeld[feldx, feldy] := spieler;
               if feldy-1>0 then spielfeld[feldx, feldy-1] := -1;  //oberes Spielfeld möglich setzen
               case spieler of
                1: farbe := clred;
                2: farbe := clblue;
               end;
               paintbox1.Canvas.Brush.Color:=farbe;
               //stein fallen lassen
               if not fallen then
               begin
               for I := 1 to feldy do
                 begin
                   paintbox1.Canvas.Brush.Color:=clbtnface;
                   paintbox1.Canvas.Ellipse((feldx-1)*(kästchen+abstand)+abstand, (i-2)*(kästchen+abstand)+abstand, (feldx-1)*(kästchen+abstand)+abstand+kästchen, (i-2)*(kästchen+abstand)+abstand+kästchen);
                   paintbox1.Canvas.Brush.Color:=farbe;
                   paintbox1.Canvas.Ellipse((feldx-1)*(kästchen+abstand)+abstand, (i-1)*(kästchen+abstand)+abstand, (feldx-1)*(kästchen+abstand)+abstand+kästchen, (i-1)*(kästchen+abstand)+abstand+kästchen);
                   sleep(40);
                 end;
               end
               else
                 paintbox1.Canvas.Ellipse((feldx-1)*(kästchen+abstand)+abstand, (feldy-1)*(kästchen+abstand)+abstand, (feldx-1)*(kästchen+abstand)+abstand+kästchen, (feldy-1)*(kästchen+abstand)+abstand+kästchen);


               //gewinnprüfung
                 //waagrecht 1
                 for I := (1-gewinnlänge) to (gewinnlänge - 1) do
                   if not fertig then
                   if (feldx+i>=1) and (feldx+i<=breite) then
                     if spielfeld[feldx+i,feldy] = spieler then
                       begin
                         zählkette:=zählkette+1;
                         poswin:=i;
                         if zählkette=gewinnlänge then fertig:=true;
                       end

                   else if zählkette<gewinnlänge then zählkette:=0;

                 if zählkette>=gewinnlänge then
                   begin
                     richtung:= 1;
                     gewonnen(spieler, poswin, feldx, feldy);
                     timer1.enabled:=true;
                   end;
                 zählkette:=0;

                 //senkrecht 2
                 for I := (1-gewinnlänge) to (gewinnlänge - 1) do
                   if not fertig then
                   if (feldy+i>=1) and (feldy+i<=höhe) then
                     if spielfeld[feldx, feldy+i] = spieler then
                       begin
                         zählkette:=zählkette+1;
                         poswin:=i;
                         if zählkette=gewinnlänge then fertig:=true;
                       end

                   else if zählkette<gewinnlänge then zählkette:=0;

                 if zählkette>=gewinnlänge then
                 begin
                   richtung:= 2;
                   gewonnen(spieler, poswin, feldx, feldy);
                   timer1.enabled:=true;
                 end;
                 zählkette:=0;

                 //diagonal rechts unten 3
                 for I := (1-gewinnlänge) to (gewinnlänge - 1) do
                     if not fertig then
                     if (feldx+i>=1) and (feldx+i<=breite) and (feldy+i>=1) and (feldy+i<=höhe) then
                         if spielfeld[feldx+i, feldy+i] = spieler then
                       begin
                         zählkette:=zählkette+1;
                         poswin:=i;
                         if zählkette=gewinnlänge then fertig:=true;
                       end

                   else if zählkette<gewinnlänge then zählkette:=0;

                   if zählkette>=gewinnlänge then
                    begin
                      richtung:= 3;
                      gewonnen(spieler, poswin, feldx, feldy);
                      timer1.enabled:=true;
                    end;
                 zählkette:=0;

                 //diagonal rechts oben 4
                 for I := (1-gewinnlänge) to (gewinnlänge - 1) do
                     if not fertig then
                     if (feldx-i>=1) and (feldx-i<=breite) and (feldy+i>=1) and (feldy+i<=höhe) then
                         if spielfeld[feldx-i, feldy+i] = spieler then
                       begin
                         zählkette:=zählkette+1;
                         poswin:=i;
                         if zählkette=gewinnlänge then fertig:=true;
                       end

                   else if zählkette<gewinnlänge then zählkette:=0;

                 if zählkette>=gewinnlänge then
                   begin
                     richtung:= 4;
                     gewonnen(spieler, poswin, feldx, feldy);
                     timer1.enabled:=true;
                   end;
                 zählkette:=0;

               //unentschieden
               for I := 1 to breite do
                 for j := 1 to höhe do
                 if (Spielfeld[i,j] = 1) or (Spielfeld[i,j] = 2) then zählkette:=zählkette+1;
               if zählkette=breite*höhe then
                 begin
                   weiter:=false;
                   application.MessageBox('Es ist unentschieden!', 'Gleichstand')
                 end
                 else zählkette:=0;
               //

               //spielerwechsel
               case spieler of
                 2: begin
                      label4.Font.Color := clred;
                      label4.Caption:='Spieler 1 am Zug';
                      spieler:=1;
                    end;

                 1: begin
                      label4.Font.Color := clblue;
                      label4.Caption:='Spieler 2 am Zug';
                      spieler:=2;
                    end;
               end;
         end;

          //linetris abschnitt, letzte reihe leeren
          if linetrisaktiv then
          begin

          linetris:= breite;
          for I := 1 to breite do
            if spielfeld[i, höhe] <> -1 then linetris :=linetris-1;

          if linetris=0 then
            begin
             for I := 1 to breite do
             begin
               for j := höhe downto 2 do spielfeld[i, j]:= spielfeld[i, j-1];
               if (spielfeld[i,2]=0) or (spielfeld[i,2]=-1) then spielfeld[i,1]:=0;
               if (spielfeld[i,2]=1) or (spielfeld[i,2]=2) then spielfeld[i,1]:=-1;
             end;
             //zeichnen
              paintbox1.Refresh;
               //zeichnen gitter
                 gitterzeichnen(paintbox1, breite, höhe, kästchen, abstand);
               //zeichnen kreise
                 kreisezeichnen(paintbox1, spielfeld, breite, höhe, kästchen, abstand);
            end; //begin


          end;//linetrisaktiv




    end; //begin if weiter


end;

procedure TForm1.PaintBox1MouseMove(Sender: TObject; Shift: TShiftState; X,
  Y: Integer);
begin
  label1.Caption := 'X: ' + inttostr(round((X-abstand) div (kästchen+abstand))+1) + '; Y: ' + inttostr(round((Y-abstand) div (kästchen+abstand))+1);
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var i: integer;
begin
  hell := not hell;
  if hell then paintbox1.Canvas.Brush.Color:=rgb(240,240,240) else paintbox1.Canvas.Brush.Color:=farbeaktiv;
  for i:= 0 to (gewinnlänge-1) do
    begin
      case richtung of
        1: paintbox1.Canvas.Ellipse((xpos+i)*(kästchen+abstand)+abstand, (ypos)*(kästchen+abstand)+abstand, (xpos+i)*(kästchen+abstand)+abstand+kästchen, (ypos)*(kästchen+abstand)+abstand+kästchen);
        2: paintbox1.Canvas.Ellipse((xpos)*(kästchen+abstand)+abstand, (ypos+i)*(kästchen+abstand)+abstand, (xpos)*(kästchen+abstand)+abstand+kästchen, (ypos+i)*(kästchen+abstand)+abstand+kästchen);
        3: paintbox1.Canvas.Ellipse((xpos+i)*(kästchen+abstand)+abstand, (ypos+i)*(kästchen+abstand)+abstand, (xpos+i)*(kästchen+abstand)+abstand+kästchen, (ypos+i)*(kästchen+abstand)+abstand+kästchen);
        4: paintbox1.Canvas.Ellipse((xpos-i)*(kästchen+abstand)+abstand, (ypos+i)*(kästchen+abstand)+abstand, (xpos-i)*(kästchen+abstand)+abstand+kästchen, (ypos+i)*(kästchen+abstand)+abstand+kästchen);
      end;
    end;
end;

end.

Die Gewinnprüfung findest du in Zeile 237-320.

Ich bin hierbei den Weg geganegn, nur 3 Felder im Umkreis zu testen, damit bei größeren Spielfeldern nicht die kompletten Reihen getestet werden müssen.

Anbei hast du auch nochmal das Endprodukt als exe.

Und was das Batchmonopoly angeht.... ich hab's mir vorhin mal angeschaut, wie gesagt, ich würde mir sowas nicht antun wollen.
 

Anhänge

Zurück
Oben