• Hallo liebe Userinnen und User,

    nach bereits längeren Planungen und Vorbereitungen sind wir nun von vBulletin auf Xenforo umgestiegen. Die Umstellung musste leider aufgrund der Serverprobleme der letzten Tage notgedrungen vorverlegt werden. Das neue Forum ist soweit voll funktionsfähig, allerdings sind noch nicht alle der gewohnten Funktionen vorhanden. Nach Möglichkeit werden wir sie in den nächsten Wochen nachrüsten. Dafür sollte es nun einige der Probleme lösen, die wir in den letzten Tagen, Wochen und Monaten hatten. Auch der Server ist nun potenter als bei unserem alten Hoster, wodurch wir nun langfristig den Tank mit Bytes vollgetankt haben.

    Anfangs mag die neue Boardsoftware etwas ungewohnt sein, aber man findet sich recht schnell ein. Wir wissen, dass ihr alle Gewohnheitstiere seid, aber gebt dem neuen Board eine Chance.
    Sollte etwas der neuen oder auch gewohnten Funktionen unklar sein, könnt ihr den "Wo issn da der Button zu"-Thread im Feedback nutzen. Bugs meldet ihr bitte im Bugtracker, es wird sicher welche geben die uns noch nicht aufgefallen sind. Ich werde das dann versuchen, halbwegs im Startbeitrag übersichtlich zu halten, was an Arbeit noch aussteht.

    Neu ist, dass die Boardsoftware deutlich besser für Mobiltelefone und diverse Endgeräte geeignet ist und nun auch im mobilen Style alle Funktionen verfügbar sind. Am Desktop findet ihr oben rechts sowohl den Umschalter zwischen hellem und dunklem Style. Am Handy ist der Hell-/Dunkelschalter am Ende der Seite. Damit sollte zukünftig jeder sein Board so konfigurieren können, wie es ihm am liebsten ist.


    Die restlichen Funktionen sollten eigentlich soweit wie gewohnt funktionieren. Einfach mal ein wenig damit spielen oder bei Unklarheiten im Thread nachfragen. Viel Spaß im ngb 2.0.

Programmieraufgabe (3): Bao - Das Steinchenspiel

Roin

Freier Denker

Registriert
22 Juli 2013
Beiträge
581
@theSplit: Ich habe die Aufgabenstellung mehr überflogen als was anderes und irgendwie verstehe ich einfach nicht, wo der Sinn des Spiels ist und was wo weggenommen werden darf.
Das ergibt sich vermutlich, wenn ich das mal in einer ruhigen Minute aufmerksam lese.
 

KaPiTN

♪♪♫ wild at heart ♪♫♫♪

Registriert
14 Juli 2013
Beiträge
29.138
  • Thread Starter Thread Starter
  • #22
@theSplit:
Jein.

Die oberste Reihe liefert zwar keine Informationen, aber das Spiel hat nun mal 4 Reihen. Manch einem ist die Zahlendarstellung ja schon zu abstrakt, da werde ich jetzt nicht noch irgend etwas weglassen und muß dann erklären, was.

@Roin:

Auf jeden Fall. :T

theSplit hat den Ablauf an einem Beispiel skizziert und es gibt 2 Videos
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.561
@Roin:

Das ist eigentlich easy... ehrlich.

Wenn du mal mehr lesen willst, hier meine Erklärung, vielleicht ist die einfacher:
Du hast 2 Reihen (unten), 2 Reihen der Mitspieler (oben) - jeweils 16 Felder, interessant ist immer nur die 2te Reihe des Gegners und deine eigenen 2. Also 3 Reihen der 4.
---
0
-------- [Spielfeld Mitte]
0
0


So fängt es zum Beispiel an:
Du nimmst bei einem Zug alle Spielsteine aus der Kuhle von der du ziehen willst. Sind zwei drinnen, nimmst du zwei raus. Sind drei, drei. usw.

In deinem Zug hast du 16 Felder in dem zu Beginn 2 Spielsteine drin sind.
Wenn du dich "bewegen" willst, nimmst du aus einem Feld 2 Steine und verteilst diese auf die nächste und die übernächste Kuhle.

Dann endet dein Zug. Jetzt hast du aber mehr als ein Spielstein in einer Kuhle, also 3 (weil 2+1 = 3) sind.
Dann fängst du nochmal an zu ziehen, wieder entnimmst du alle Steine (3) und füllst diese im Uhrzeigersinn auf die folgenden.
09 10 11 12 13 14 15 16
08 07 06 05 04 03 02 01

Das sind die Felder, du fängst bei 1 an und hörst bei 16 auf zu zählen.

Bist du bei Feld 09, kannst du oberhalb des Felds die Spielsteine aus dem Feld des Gegner herausnehmen so wie deine eigenen und diese auf die Felder 10, 11, 12, 13, 14 usw. verteilen, bis du keine mehr in der Hand hast.

Und wenn du mehr als 1 Spielstein in der Kuhle hast wo du keine Steine mehr legen kannst, endet dein Zug, ansonsten nimmst du alle Steine aus dieser Kuhle und legst sie wieder rei rum von 16 auf 01 usw. bis du keine Steine mehr hast die du legen kannst.

Dann ist der Gegner dran.
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
Mir taucht gerade noch eine Frage auf: Wenn der Gegner meine Frontreihe leerräumt, hat er ja gewonnen. Wie ist das, wenn ich selbst im Lauf meiner Runde meine eigene Frontreihe leerräume? Hab ich dann auch verloren?
 

KaPiTN

♪♪♫ wild at heart ♪♫♫♪

Registriert
14 Juli 2013
Beiträge
29.138
  • Thread Starter Thread Starter
  • #25
@Brother John:

Die einzige Möglichkeit wäre, afaiks, wenn Du nur noch in Kuhle 16 in der Reihe Steine hättest.
Aber ja. So spielen wir das.

Die Regeln sind aber nicht din zertiziziert, glaube ;)

Es gibt auch Leute, die lassen die 4 Felder der eigenen oberen Reihe frei. Es gibt auch Bretter, die nicht aus 4 x 8 Feldern bestehen. Das sind die Regeln, wie ich sie kenne und im Netz auch mehrfach so gefunden habe.

Stichworte:
Bao
Hus
Mancala
 

MingsPing

NGBler

Registriert
15 Juli 2013
Beiträge
346
In Bezug auf Beitrag #22:
Ich denke, dass hier nur viele Profite gleich sind, weil das die Ausgangsstellung ist. Aber wer weiß?!

Meine Implementierung ist soweit auch fertig :-) Ist in Common Lisp und 110 Zeilen lang. Ein Großteil wegen richtigem Einlesen der Daten und umwandeln in die interne Repräsentation.
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
Bis zur Deadline kriegen wir die Regeln auch nicht mehr DIN-zertifiziert. ;) Klar ist das ne extrem unwahrscheinliche Situation. Die Frage kam bei der Überlegung, was das für ein Spielstatus ist, wenn ich als Input ein Board habe, wo *beide* Frontreihen leer sind.

Bis auf den Punkt Validierung bin ich auch durch. Ein bisschen Doku noch und der Algo kann ein/zwei Tests vertragen.
 

KaPiTN

♪♪♫ wild at heart ♪♫♫♪

Registriert
14 Juli 2013
Beiträge
29.138
  • Thread Starter Thread Starter
  • #28
@Brother John:

Entschuldige, falls das mit der DIN blöde rüberkam. Ich freue mich ja über jede Frage/Anregung und wünschte sogar, daß man sich mehr über die Problemstellung austauschen würde, statt das jeder nur ein Ergebnis abliefert.

Du hast mich halt ein wenig auf dem falschen Fuß erwischt, als Du nach Regeln gefragt hast. Es ist halt kein Schach oder Fifa-Fußball. Ich erkläre die Regeln, wie ich sie kenne, MauMau spielt man auch nicht einheitlich.

Wie gedenkst Du zu testen?

Was meinst ihr, wie wir uns in einem dermaßen frühen Stadium austauschen können, ohne zu spoilern?

Könnten wir für Schnelle/Interessierte bereits jetzt zusätzliche Herausforderungen erdenken, zur gemeinsamen Lösung oder als Wettbewerb?
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
Das kam überhaupt nicht blöde rüber. So sollte meine Antwort nicht klingen. Sorry. Ist ja auch ein extrem seltener Grenzfall.

Ich werde mir zum Testen eine normale Runde hernehmen, vom Algorithmus jeden Einzelschritt ausgeben lassen und manuell nachprüfen. Dann hab ich einen definitiven Satz an Quell- und Zielzustand, und der kann für einen automatischen Vorher-/Nachher-Test herhalten, wenn ich die Algo-Implementierung ändere. Dann bin ich mir sicher genug, dass der Bruteforce-Algo korrekt ist. Wenn ich mehr Algos baue, teste ich dann gegen den. Und zumindest einen zweiten hab ich mir vorgenommen.

Damit keiner gespoilert wird, sollte es doch reichen, Diskussionen über konkrete Algos in Spoilertags zu packen.
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
Ich mach dann mal den Aufschlag mit dem BOTF, dem Bao Optimal Turn Finder.

https://github.com/be-sc/botf

Gebaut in Python 3. Doku ist dabei. Insgesamt gut 400 Zeilen. @MingsPing, deine 110 Zeilen kann ich also nicht ganz toppen. ;)

Weil ich mir erstmal einen ganz stinkeinfachen Bruteforce-Algo vorgenommen habe, wollte ich mir die Tür zu zusätzlichen Algos nicht verbauen. Deswegen ist alles, was nicht direkt Spielzüge ausrechnet, ausgelagert. Der Algo ist hinter einem Mini-Interface wegabstrahiert, kriegt ein fertig validiertes und aufbereitetes Spielbrett rein und kann sofort loslegen. Wenn noch mehr Algorithmen dazukommen (noch einen hab ich mir vorgenommen): neue Pythondatei mit dem richtigen Namen schreiben, und dann kann man den Algo per Kommandozeilen-Option auswählen. … Ja, ich hatte meinen Spaß. :D

Zum Algo:
Bruteforce heißt wirklich Bruteforce. Er fängt bei Feld 1 an, rechnet von da aus eine vollständige Runde durch und merkt sich das Ergebnis. Dann fängt er bei Feld zwei an, rechnet die Runde und vergleicht. Wenn das Ergebnis höher ist, merkt er sich diese Runde. … usw. bis zu Feld 16. Damit ist der vollständige Lösungsraum abgegrast. Als einziges Erkerchen sitzt nach jedem Zug nur die Prüfung dran, ob das Spiel schon beendet ist (weil z.B. der Spieler die gegnerische Frontreihe leer geräumt hat).

Für den Spielstart als Ausgangslage liegen CSVs für alle Zwischenergebnisse nach jedem einzelnen Zug mit im Repo.

Laufzeit ist vernachlässigbar. Mit nem alten 3-GHz-Athlon kommt nur der Algorithmus-Teil auf grob 4ms.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.561
@Reek: Thema Git, da müsstest du dich an drfuture oder Larius wenden, wobei ersterer der Ansprechpartner dafür ist.

--------

Thema Testsequenzen für verschiedene Spielbretter:
Ich war auch nicht untätig, habe mir mal erlaubt einen Spielfeldgenerator zu basteln der euch vielleicht das testen etwas erleichtern könnte.

Das Teil hat auch Kommandos/Switches:
'p' : Anzahl der Spielesteine (Default: 32)
'f' : Anzahl der Felder für jeden Spieler, teilbar durch 2 (Default: 16)
'b' : Anzahl der zu generierenden Spielbretter (Default: 10)

Die Kommandos um 64 Spielsteine auf 30 Felder zu generieren auf 12 Spielbrettern-Varianten: "EXENAME p64 f30 b12"

Gespeichert wird in einer Datei Namens "playboard.csv".

Um ehrlich zu sein, es ist keine richtige CSV, aber das Format kann ich auch nochmal anpassen falls gewünscht, ich brauche dann nur eine Vorlage!

Wenn Bedarf besteht, lade ich mal zu Git die Source hoch, wie auch fertige Executables für Windows Systeme.

Und so sieht der Output aus: (Einstellungen: 32 Spielsteine, 16 Felder, Default: 10 Spielbretter, hier aber nur 5 gezeigt):
[src=text].05.01.00.00.01.03.03.01
.01.00.00.00.01.01.00.01
------------------------
.04.02.01.02.01.01.00.00
.01.00.02.02.01.01.01.00

.02.02.00.01.00.04.01.01
.01.02.00.00.01.00.01.01
------------------------
.03.03.02.00.02.03.01.03
.00.01.01.00.01.00.00.03

.00.03.00.00.00.03.00.03
.03.02.01.02.00.01.00.03
------------------------
.03.00.00.03.01.03.03.02
.02.02.01.00.01.00.00.02

.04.02.01.00.02.01.02.01
.01.01.02.00.01.00.00.01
------------------------
.00.01.05.02.02.00.03.02
.00.00.00.02.01.00.01.02

.03.03.01.00.02.00.01.00
.02.02.03.00.02.01.00.00
------------------------
.00.00.02.02.00.00.00.02
.00.00.02.02.03.01.00.02

.02.04.03.04.03.00.01.00
.01.02.01.01.00.00.00.00
------------------------
.04.03.00.01.02.03.02.01
.02.01.01.01.00.01.00.01
[newline][/src]


Ansonsten poste ich mal die Source jetzt damit ihr damit testen könnt:
[src=c]#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>

int main(int argc, char *argv[]) {

int startPieces = 32;
int fields = 16;
int playboardsToCreate = 10;

if (argc > 1) {
for (int i = 1; i < argc; ++i) {
char *data[255];
if (argv[0] == 'p') {
startPieces = strtol(argv+1, data, 10);
} else if (argv[0] == 'b') {
playboardsToCreate = strtol(argv+1, data, 10);
} else if (argv[0] == 'f') {
fields = strtol(argv+1, data, 10);
} else {
printf("[ERROR] Unknown command: '%s'\nUse the switches 'p', 'b' or 'f' in combinations.\n\nLike\n'p12': 12 Game pieces\n'b10': 10 Playboards\n'f16': 16 fields.\n\n", argv);
return 1;
}
}
}

if (fields % 2 != 0) {
printf("[ERROR] Fields dont align by 2.\n");
return 1;
} else if (fields < 2) {
printf("[ERROR] Cant create playboards with less than 2 fields.\n");
return 1;
} else if (fields > 32) {
printf("[ERROR] Dont want to create playboards with more than 32 fields. Buy the full edition to continue!\n");
return 1;
}

if (startPieces < 4) {
printf("[ERROR] Need at least 4 gaming pieces to operate\n");
return 1;
} else if (startPieces > fields * 3) {
printf("[ERROR] Too many gaming pieces, cannot be more than 3 times the fields.\n");
return 1;
}

if (playboardsToCreate < 0) {
printf("[ERROR] Need at one playboard to generate, canceling.\n");
return 1;
} else if (playboardsToCreate > 100) {
printf("[ERROR] Too many playboards, in shareware, I generate only 100 a time! We are sorry.\n");
return 1;
}


// Generate the playboards
FILE *playboardStore = fopen("playboard.csv", "w");
if (playboardStore == NULL) {
printf("[ERROR] Cannot open 'playboard.csv' for writing playboard data.\n");
return 1;
}

int generatedPlayboards = 0;
char data[3];

int rows = fields / 2;

int player = 0;
int piecesToSet = 0;
int leftOverPieces = 0;

int playboard[2][fields];
int pieces[2];

while (playboardsToCreate--) {
srand(time(NULL) + clock());
generatedPlayboards++;

pieces[0] = startPieces;
pieces[1] = startPieces;

// Generate the playBoard
printf("\nPlayboard #%d\n\n", generatedPlayboards);

for (int i = 0; i < 5; ++i) {
if (i < 2) {
player = 0;
} else if (i == 2) {
player = -1;
} else {
player = 1;
}

for (int j = 0; j < rows; ++j) {
if (player == -1) {
printf("---");
fputs("---", playboardStore);
} else {
leftOverPieces = pieces[player];

if (leftOverPieces > 4) {
srand(time(NULL) + clock());
piecesToSet = (rand() % (int) round(leftOverPieces / floor(rand() % 4 + 5)) );
if (piecesToSet > leftOverPieces) {
piecesToSet = floor(leftOverPieces-(leftOverPieces/2));
}
} else {
piecesToSet = leftOverPieces;
}

pieces[player] -= piecesToSet;

if ((i == 1 || i == 4) && j+1 == rows && pieces[player] != 0) {
piecesToSet = pieces[player];
} else {
playboard[player][j] = piecesToSet;
}

printf(".%02d", piecesToSet);

sprintf(data, ".%02d", playboard[player][j]);
fputs(data, playboardStore);
}
}

printf("\n");
fputc('\n', playboardStore);
}

if (playboardsToCreate > 0) {
fputc('\n', playboardStore);
}

}

fclose(playboardStore);
}
[/src]


Kleine Notizen:
- Die Zufallsverteilung ist mit Sicherheit Verbesserungswürdig, aber es funktioniert
- Es können auch leere Kuhlen erzeugt werden auch wenn Spielsteine zur Verteilung verfügbar sind
 
Zuletzt bearbeitet:

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
@theSplit
Ein Spielfeldgenerator, perfekt! :) Wäre es aufwändig, ihn so anzupassen, dass er pro Spielbrett eine CSV-Datei so wie im Startpost ausspuckt? So könnte man die Bretter am einfachsten an die Rundenrechner verfüttern.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.561
Wäre möglich, man müßte sich nur auf ein Format einigen. :)

Mein Vorschlag wäre eine große Datei für alle Spielbretter, damit man nicht mit 100 kleinen Dateien arbeiten muß, wenn möglich, ich lasse mich da aber auch gern eines besseren belehren falls man den Namen der InputDatei als Ausgabevorlage verwenden will oder ähnliches.

Also wenn ich dich richtig verstehe Brother John, sollte das Spielfeld so gespeichert werden?

2;2;2;2;2;2;2;2
2;2;2;2;2;2;2;2
2;2;2;2;2;2;2;2
2;2;2;2;2;2;2;2


Falls wir eine Datei verwenden, würde ich die einzelnen Spielfelder durch "newline" trennen, dann aber so wie die Vorlage, weiterspeichern.


* Habe jetzt mal nachgelegt:

Folgend die Versionen kompiliert unter 64bit Linux, "baogen", und die 32bit und 64bit Windows Versionen "baogen32.exe" und "baogen64.exe".

Die Windows Versionen habe ich jetzt nicht getestet, aber sie haben zumindest fehlerfrei kompiliert, hoffe aber sie laufen Ordnungsgemäß.

Baogen gibt die obige Struktur aus, wie von Brother John gewünscht, nur alles in einer Datei, worin die Spielfelder mit leerer Newline Zeile getrennt sind.

Hier ist der Download Link: Anhang anzeigen baogen.zip


Und so sieht die neue Source dafür aus:
[src=c]#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>

int main(int argc, char *argv[]) {

int startPieces = 32;
int fields = 16;
int playboardsToCreate = 10;

if (argc > 1) {
for (int i = 1; i < argc; ++i) {
char *data[255];
if (argv[0] == 'p') {
startPieces = strtol(argv+1, data, 10);
} else if (argv[0] == 'b') {
playboardsToCreate = strtol(argv+1, data, 10);
} else if (argv[0] == 'f') {
fields = strtol(argv+1, data, 10);
} else {
printf("[ERROR] Unknown command: '%s'\nUse the switches 'p', 'b' or 'f' in combinations.\n\nLike\n'p12': 12 Game pieces\n'b10': 10 Playboards\n'f16': 16 fields.\n\n", argv);
return 1;
}
}
}

if (fields % 2 != 0) {
printf("[ERROR] Fields dont align by 2.\n");
return 1;
} else if (fields < 4) {
printf("[ERROR] Cant create playboards with less than 4 fields.\n");
return 1;
} else if (fields > 32) {
printf("[ERROR] Dont want to create playboards with more than 32 fields. Buy the full edition to continue!\n");
return 1;
}

if (startPieces < 4) {
printf("[ERROR] Need at least 4 gaming pieces to operate\n");
return 1;
} else if (startPieces > fields * 3) {
printf("[ERROR] Too many gaming pieces, cannot be more than 3 times the fields.\n");
return 1;
}

if (playboardsToCreate < 0) {
printf("[ERROR] Need at one playboard to generate, canceling.\n");
return 1;
} else if (playboardsToCreate > 100) {
printf("[ERROR] Too many playboards, in shareware, I generate only 100 a time! We are sorry.\n");
return 1;
}


// Generate the playboards
FILE *playboardStore = fopen("playboard.csv", "w");
if (playboardStore == NULL) {
printf("[ERROR] Cannot open 'playboard.csv' for writing playboard data.\n");
return 1;
}

int generatedPlayboards = 0;
char data[128];

int rows = fields / 2;

int player = 0;
int piecesToSet = 0;
int leftOverPieces = 0;

int playboard[2][fields];
int pieces[2];

while (playboardsToCreate--) {
srand(time(NULL) + clock());
generatedPlayboards++;

pieces[0] = startPieces;
pieces[1] = startPieces;

// Generate the playBoard
printf("\nPlayboard #%d\n\n", generatedPlayboards);

for (int i = 0; i < 4; ++i) {
if (i < 2) {
player = 0;
} else {
player = 1;
}

for (int j = 0; j < rows; ++j) {
leftOverPieces = pieces[player];

if (leftOverPieces > 4) {
srand(time(NULL) + clock());
piecesToSet = (rand() % (int) ceil(leftOverPieces / floor((rand() % 4) + 3)) );
if (piecesToSet > leftOverPieces) {
piecesToSet = floor(leftOverPieces-(leftOverPieces/2));
}
} else {
piecesToSet = leftOverPieces;
}

pieces[player] -= piecesToSet;

if ((i == 1 || i == 3) && j+1 == rows && pieces[player] != 0) {
piecesToSet = pieces[player];
} else {
playboard[player][j] = piecesToSet;
}

if (j+1 < rows) {
printf("%d;", piecesToSet);
sprintf(data, "%d;", playboard[player][j]);
fputs(data, playboardStore);
} else {
printf("%d", piecesToSet);
sprintf(data, "%d", playboard[player][j]);
fputs(data, playboardStore);
}
}

printf("\n");
fputc('\n', playboardStore);
}

fputc('\n', playboardStore);
}

fclose(playboardStore);
}[/src]
 
Zuletzt bearbeitet:

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.561
Sorry für den Doppelpost, ich dachte nur ich Push das mal, damit es auch wirklich getestet wird, sonst denkt vielleicht noch jemand es gäbe nichts neues. ;)

Habe nachgelegt, jetzt gibt es offizell ein Paket mit Linux Build, Windows 32 und 64bit Build und Source falls es dennoch nicht läuft in einem Paket.
Rest siehe dem Edit über diesen Beitrag :)

Habe auch das Zahlenverteilen noch etwas angepasst, ist aber noch nicht perfekt - vielleicht sollte man den Teiler verkleinern, je höher man in den Felder fortschreitet - oder es ist okay so :unknown:
 

exomo

NGBler

Registriert
1 Aug. 2015
Beiträge
129
So, meine erste Version ist fertig. Da ich nicht genau weiß wie ich mit den uneindeutigen Ergebnissen soll, habe ich es jetzt so gemacht dass alle möglichen besten Züge ausgegeben werden (siehe Spoiler), aber nur eines (das mit der niedrigsten Kuhlennummer) in die Datei geschrieben wird.
Das Programm liest immer aus bao_in.txt und schreibt nach bao_out.txt, jeweils nur ein Spielstand (4 Zeilen).

Die Ausgabe für das Startfeld sieht dann so aus:
Meiste Steine gestohlen: 4
Beste(s) Spiel(e):
Waehle Kuhle #1
2;2;2;2;2;2;2;2
0;2;2;2;2;0;2;2
0;3;3;3;3;0;3;3
3;3;0;3;3;1;4;1

Waehle Kuhle #2
2;2;2;2;2;2;2;2
2;0;2;2;2;2;0;2
3;0;3;3;3;3;0;3
3;0;3;3;1;4;1;3

Waehle Kuhle #3
2;2;2;2;2;2;2;2
2;2;0;2;2;2;2;0
3;3;0;3;3;3;3;0
0;3;3;1;4;1;3;3

Waehle Kuhle #4
2;2;2;2;2;2;2;2
0;2;2;2;2;0;2;2
0;3;3;3;3;0;3;3
3;3;1;4;1;0;3;3

Waehle Kuhle #5
2;2;2;2;2;2;2;2
2;0;2;2;2;2;0;2
3;0;3;3;3;3;0;3
3;1;4;1;0;3;3;3

Waehle Kuhle #6
2;2;2;2;2;2;2;2
2;2;0;2;2;2;2;0
3;3;0;3;3;3;3;0
1;4;1;0;3;3;3;3

Waehle Kuhle #7
2;2;2;2;2;2;2;2
0;2;2;2;2;0;2;2
1;3;3;3;3;0;3;3
4;1;0;3;3;0;3;3

Waehle Kuhle #8
2;2;2;2;2;2;2;2
2;0;2;2;2;2;0;2
4;1;3;3;3;3;0;3
1;0;3;3;0;3;3;3

Waehle Kuhle #9
2;2;2;2;2;2;2;2
2;2;0;2;2;2;2;0
1;4;1;3;3;3;3;0
0;3;3;0;3;3;3;3

Waehle Kuhle #12
2;2;2;2;2;2;2;2
0;2;2;2;2;0;2;2
0;3;3;1;4;1;3;3
3;3;0;3;3;0;3;3

Waehle Kuhle #13
2;2;2;2;2;2;2;2
2;0;2;2;2;2;0;2
3;0;3;3;1;4;1;3
3;0;3;3;0;3;3;3

Waehle Kuhle #14
2;2;2;2;2;2;2;2
2;2;0;2;2;2;2;0
3;3;0;3;3;1;4;1
0;3;3;0;3;3;3;3

Der Code ist in meinem GitHub Repository zu finden:
https://github.com/exomo/Bao
Ich habe nur ein Code::Blocks Projekt eingecheckt, da es aber nur 2 cpp Dateien sind sollte das aber leicht auf andere Build-Mechanismen/IDEs portierbar sein. Es wird ein C++11 fähiger Compiler benötigt. (ich verwende einen MinGW-W64 g++ 5.3.0).

Im Moment funktioniert nur das Standardspiel mit 8 Kuhlen pro Reihe, Ein- und Ausgabe nur ein Spielfeld pro Datei. Fehlerbehandlung noch so gut wie nicht vorhanden. Als nächstes schaue ich mal wie ich das mit mehreren Spielfeldern in einer Datei umsetzen kann.

PS: Ich mache mir auch noch Gedanken über den "KI-Wettkampf". Meine Idee wären die folgenden Anforderungen an die Teilnehmer:
- Anwendung muss über einen Konsolenbefehl gestartet werden
- Ein Dateiname für den Input kann als Kommandozeilenparameter angegeben werden
- Die Anwendung gibt eine Zahl zwischen 1 und 16 zurück als Exit-Code, als Zug der gemacht wird
(z.B. ./ki_in_c.exe input.txt, java -jar ki_in_java-jar input.txt)
- Es gibt eine Zeitbegrenzung pro Zug, z.B. 10 Sekunden, wer das Limit nicht einhält hat verloren.
- Jeder Teilnehmer ist "der untere Spieler"
- Keine Dateiausgabe erforderlich, dafür ist der "Spielleiter" verantwortlich

Der "Spielleiter" ist das Kontrollprogramm, das den Wettbewerb durchführt
Der "Spielleiter" erhält die Kommandozeilen für die Teilnehmer und macht die folgendne Schritte bis ein Gewinner feststeht
- Erzeugt die Eingabedateien aus dem aktuellen Stand des Spielfelds
- Ruft den Teilnehmer über Kommandozeile auf, der an der Reihe ist, und erhält dadurch den nächsten Zug
- Prüft ob der Zug gültig ist und ob dadurch jemand gewonnen hat
- Aktualisiert das Spielfeld und wechselt den Spieler, der an der Reihe ist
 
Zuletzt bearbeitet:

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
@exomo
Ich hab mich gewundert, dass bei gleicher Ausgangslage deine und meine Lösung unterschiedliche Ergebnisse liefern. Sieht so aus als arbeiten wir nach unterschiedlichen Regeln. Denn: Wenn der allererste Zug der Runde in der Frontreihe anfängt, nimmst du nur die Steine aus deiner eigenen Kuhle. Ich nehme auch die Steine aus der angrenzenden Gegnerkuhle dazu.

@KaPiTN
Wie solls denn sein?

@theSplit
Irgendwas passt beim Generator noch nicht. Er spuckt regelmäßig weniger Steine als angefordert aus. Ich hab mal einen Satz generierter Bretter inkl. Auswertung angehängt: Anhang anzeigen baogen-problem.zip Vielleicht hilfts, das Problem einzugrenzen. Passiert mit beiden Windows-Versionen aus deinem Archiv. Ich hab auch selber nochmal eine 64bit-Windows gebaut. Die hat dasselbe Verhalten.

Und mein BOTF kann jetzt auch Multiboard-CSVs lesen und hat einen Standalone-Validator für Boards bekommen.
 

MingsPing

NGBler

Registriert
15 Juli 2013
Beiträge
346
Also meine Ausgabe sieht so aus:
Kuhle Nr.: 0, Profit: 4
(2 2 2 2 2 2 2 2)
(0 2 2 2 2 0 2 2)
(0 3 3 3 3 0 3 3)
(3 3 0 3 3 1 4 1)
Kuhle Nr.: 1, Profit: 4
(2 2 2 2 2 2 2 2)
(2 0 2 2 2 2 0 2)
(3 0 3 3 3 3 0 3)
(3 0 3 3 1 4 1 3)
Kuhle Nr.: 2, Profit: 4
(2 2 2 2 2 2 2 2)
(2 2 0 2 2 2 2 0)
(3 3 0 3 3 3 3 0)
(0 3 3 1 4 1 3 3)
Kuhle Nr.: 3, Profit: 4
(2 2 2 2 2 2 2 2)
(0 2 2 2 2 0 2 2)
(0 3 3 3 3 0 3 3)
(3 3 1 4 1 0 3 3)
Kuhle Nr.: 4, Profit: 4
(2 2 2 2 2 2 2 2)
(2 0 2 2 2 2 0 2)
(3 0 3 3 3 3 0 3)
(3 1 4 1 0 3 3 3)
Kuhle Nr.: 5, Profit: 4
(2 2 2 2 2 2 2 2)
(2 2 0 2 2 2 2 0)
(3 3 0 3 3 3 3 0)
(1 4 1 0 3 3 3 3)
Kuhle Nr.: 6, Profit: 4
(2 2 2 2 2 2 2 2)
(0 2 2 2 2 0 2 2)
(1 3 3 3 3 0 3 3)
(4 1 0 3 3 0 3 3)
Kuhle Nr.: 7, Profit: 4
(2 2 2 2 2 2 2 2)
(2 0 2 2 2 2 0 2)
(4 1 3 3 3 3 0 3)
(1 0 3 3 0 3 3 3)
Kuhle Nr.: 8, Profit: 4
(2 2 2 2 2 2 2 2)
(2 2 0 2 2 2 2 0)
(1 4 1 3 3 3 3 0)
(0 3 3 0 3 3 3 3)
Kuhle Nr.: 9, Profit: 2
(2 2 2 2 2 2 2 2)
(2 2 2 0 2 2 2 2)
(3 1 3 0 3 3 3 3)
(3 0 3 3 0 3 3 0)
Kuhle Nr.: 10, Profit: 2
(2 2 2 2 2 2 2 2)
(2 2 2 2 0 2 2 2)
(3 3 1 3 0 3 3 3)
(0 3 3 0 3 3 0 3)
Kuhle Nr.: 11, Profit: 4
(2 2 2 2 2 2 2 2)
(0 2 2 2 2 0 2 2)
(0 3 3 1 4 1 3 3)
(3 3 0 3 3 0 3 3)
Kuhle Nr.: 12, Profit: 4
(2 2 2 2 2 2 2 2)
(2 0 2 2 2 2 0 2)
(3 0 3 3 1 4 1 3)
(3 0 3 3 0 3 3 3)
Kuhle Nr.: 13, Profit: 4
(2 2 2 2 2 2 2 2)
(2 2 0 2 2 2 2 0)
(3 3 0 3 3 1 4 1)
(0 3 3 0 3 3 3 3)
Kuhle Nr.: 14, Profit: 2
(2 2 2 2 2 2 2 2)
(2 0 2 2 2 2 2 2)
(3 0 3 3 3 3 1 3)
(3 0 3 3 0 3 3 0)
Kuhle Nr.: 15, Profit: 2
(2 2 2 2 2 2 2 2)
(2 2 0 2 2 2 2 2)
(3 3 0 3 3 3 3 1)
(0 3 3 0 3 3 0 3)
Ist das gleiche wie exomos, glaube ich.
 

theSplit

1998
Veteran Barkeeper

Registriert
3 Aug. 2014
Beiträge
28.561
@Brother John:

Also es gab in der Tat einen Fehler, die erste Kuhle (rechts unten in der eigenen Reihe) sollte verbleibenden Spielsteine bekomme, so sollte es jedenfalls sein.
Da wurden allerdings Spielsteine entfernt, die eigentlich aber noch zusätzlich gesetzt werden sollten. Zu früh abgerechnet und dann nicht einbezogen!
Das habe ich behoben.

Warum du allerdings so viele Leerfelder bekommst, ist mir ein Rätsel.

Es wird nun daher über die Kommandozeile nach jeder Spielerreihen-Verteilung noch zusätzlich angezeigt wie viele der Spielsteine übrig sind, sein sollen es : "Pieces left: 0 left of 32" oder statt 32 die Anzahl der eingestellten.

Brother John, teste doch mal bitte der beigefügten Source wenn du diese selbst kompilierst: Anhang anzeigen baoGen_0.9.c.zip

Im Grunde sind die Änderungen lediglich:
[src=c]// Hier wird nun getestet ob in der letzten Reihe in in der letzten Kuhle noch Spielsteine uebrig sind, wenn ja werden diese in die Kuhle gelegt
if ((i == 1 || i == 3) && j+1 == rows && (pieces[player] - piecesToSet) != 0) {


piecesToSet = pieces[player];
playboard[player][j] = piecesToSet;
} else {
playboard[player][j] = piecesToSet;
}
// Das war vorher vor der If Abfrage, daher, die Steine wurden abgezogen und dem Fundus entnommen, obwohl diese noch fuer die letzte Reihe verfuegbar haetten sein sollen
pieces[player] -= piecesToSet[/src]
 

Brother John

(schein)heilig
Veteran

Registriert
1 Aug. 2013
Beiträge
235
So, bin endlich zum Testen gekommen. Felderanzahl passt jetzt. :)

Die seltsamen Verteilungen kamen daher, dass du in jedem Schleifendurchlauf den Zufallszahlengenerator neu seedest. Das ist schädlich für die Qualität des Zufalls. Ich hab das erste srand aus der while-Schleife rausgezogen und das zweite srand gelöscht. Damit sehen die Verteilungen viel vernünftiger aus.

Patch im Anhang.
 

Anhänge

  • baoGen_0.9_srand-patch.diff.zip
    512 Bytes · Aufrufe: 208
Oben