Verfasst am: 31.01.2011, 17:40
Titel: KI programmieren für Tic-Tac-Toe
Hallo zusammen,
ich hab für eine projektarbeit das bekannte spiel tictactoe programmiert. Es funktioniert auch alles soweit aber nur im player vs player modus und da das meinem prof nicht reicht muss ich noch eine art "KI" mit einbauen. Genau das ist mein problem,ich weis nicht wirklich wie ich diese schreiben soll. Mein beigefügter code ist die funktion, die es ermöglicht das ein player ein x und der andere eine o als symbol zugewiesen bekommt. Ich glaub man muss die KI genau da einbauen!?
Leider bin ich gerade erst mit matlab eingestiegen und habe kaum kenntnisse. Das problem was auf mich zukommt ist folgendes.
Vorher konnte man playervsplayer spielen nun soll aber der pc selbstständig gegen einer "player" spielen. Wie kann ich dem pc sagen dass er jetzt auf den button sein zeichen schreiben soll?
Oder dass er überhaupt an der reihe ist?
Mein gedanke dazu war es mit der anzahl an zügen(insgesamt 9) die zeichen zuweisen zu lassen, sprich bei ungeraden zügen ist der player an der reihe bzw. bei geraden der computer. Ein freund von mir meinte die funktion waitforbuttonpress() hilft mir vielleicht weiter aber da ich neuling bin konnte ich mir noch nicht wirklich ein bild davon machen, wie ich das in mein code einbau könnte.
Soweit der Stand der Dinge. Ich hoffe man wird schlau aus meinem text und es ist möglich mir tipps,anregungen oder vielleicht vorhandene lösungen zu präsentieren.
Aufgrund der tatsache, dass ich kaum ahnung von matlab habe und der jetztige stand des programms mich unzählige stunden gekostet hat, bitte ich um möglichst leichte und nachvollziehbare lösungsansätze.
Ich würde mich freun, wenn mir jemand helfen kann =)
Gruß Philipp
Code:
function klick_button(button,eventdata)
%Callback function fir die 9-Buttons
ifget(button,'String') == 'X'
errordlg('Diese Feld ist bereit besetzt!!')% Pop-up zeigt an dass das feld schon benutzt wurde return elseifget(button,'String') == 'O'
errordlg('Diese Feld ist bereit besetzt!!') return elseif turn == 0 % wenn X geht set(button,'String','X')
turn = 1;
% andernfalls geht O else set(button,'String','O')
turn = 0;
end
wenn du sagst, dass du wenig Ahnung von MATLAB hast, hast du da ja schon mal einiges geleistet.
Ich gehe mal von einer schlauen KI aus.
Zwei Möglichkeiten:
a) KI fängt an. KI macht Kreuz in die Mitte; dann gehts mit b) weiter.
b) Mensch fängt an. Mensch macht Kreis, und unmittelbar danach macht KI ein Kreuz. Nun ist die Frage: wo macht die KI das Kreuz hin? Ausgehend von meiner eigenen Strategie würde ich sagen:
- zunächst "Verteidigungsmodus": wenn nötig eine gegnerische Reihe verhindern (diese Abfrage dürfte etwas komplexer sein).
- wenn nicht nötig, "Angriffsmodus": versuchen, eine eigene Reihe zu bilden / zu vervollständigen (die Abfrage dürfte auch etwas komplexer sein, ich glaube "Mitte" [wenn frei] ist fast immer gut)
Beim Implementieren der komplexeren Abfragen kannst du wahrscheinlich ähnlich vorgehen wie in gewinnmoeglichkeiten.m .
Grüße,
Harald
_________________
1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Mr. P
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 31.01.2011, 21:54
Titel:
Hallo Harald,
ich danke dir schonmal für deine schnelle antwort =)
Die theorie die hinter der KI steckt hab ich auch schon versucht herzuleiten das war nicht ganz meine problem beim programmieren.
Mein problem ist es dem programm mitzuteilen,dass der pc selbst ein symbol setzt.Mit meinem geposteten code-auszug ist es nur möglich selbst ein feld anzuklicken und er wechselt zwischen den symbolen aber nicht das sofort nach dem klick des menschen der computer eigenständig ein symbol setzt. Diese abfrage stellt für mich ein problem da. Vielleicht hast du ja eine gute anregeung, wie ich das in die 'funktion turn' einbauen kann.
Variante a): KI fängt an, erstes Kreuz wird quasi als Initialisierung gesetzt. Dann folgt:
Solange das Spiel nicht entschieden ist:
Unmittelbar auf jeden Zug des Menschen (d.h. im Callback direkt angehängt) setzt die KI ihr Kreuz.
Du kannst es so sehen, dass durch das Setzen des Kreises durch den Menschen quasi direkt der Zug der KI (und das Setzen des folgenden Kreuzes) ausgelöst wird.
Auf Klick:
% Mensch macht Zug % Überprüfung ob Spiel entschieden. Falls entschieden -> Abbruch % KI macht Zug % Überprüfung ob Spiel entschieden. Falls entschieden -> Abbruch % (warten auf nächsten Zug des Menschen)
1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Ich glaub das Problem liegt einfach in dem Aufrufen der funktion. Bis jetzt wird die Funktion durch das klicken eines buttons aufgerufen. Du kannst sie aber auch einfach im Quelltext aufrufen.
Code:
function klick_button(button,eventdata)
%Callback function fir die 9-Buttons
ifget(button,'String') == 'X'
errordlg('Diese Feld ist bereit besetzt!!')% Pop-up zeigt an dass das feld schon benutzt wurde return elseifget(button,'String') == 'O'
errordlg('Diese Feld ist bereit besetzt!!') return elseif turn == 0 % wenn X geht set(button,'String','X')
turn = 1;
% andernfalls geht O else set(button,'String','O')
turn = 0;
end
gewinnmoeglichkeiten()
if turn == 1% 1 = Computer ist am Zug
button_ki = Berechnung welches Kreuz KI setzen muss
klick_button(button_ki,eventdata);
end
Ja du hast recht die Funktion wird nur aufgerufen, wenn ich einen Button anklicke. Das heißt ich müsste die komplette Funktion turn umschreiben oder?
Ich konnte noch nicht ganz nachvollziehen wie das funktionieren soll, wenn ich sie einfach im quelltext aufrufe, sozusagen für button_KI eine eigene funktion schreiben ?
man kanns doch auch komplizierter als nötig machen? Letzter Versuch meinerseits, den Ansatz darzulegen, den ich meine:
Code:
function klick_button(button,eventdata, handles)% <-- handles wird gebraucht % Callback function für die 9-Buttons <-- Mensch drückt % Hier grundsätzlich: Mensch macht O, KI macht X
% untersucht ob das feld noch frei ist
ifget(button,'String') == 'X'
errordlg('Diese Feld ist bereit besetzt!!')% Pop-up zeigt an dass das feld schon benutzt wurde return elseifget(button,'String') == 'O'
errordlg('Diese Feld ist bereit besetzt!!') return else set(button,'String','O')% Zug des Menschen
gewinnmoeglichkeiten()% überprüfen ob Spiel beendet (Sieger Mensch)
wahl = ...% Funktion, nach der KI ihren Zug wählt --> gibt 1-9 zurück % Annahme: Tags der Buttons sind button1 - button9 set(handles.(['button' num2str(wahl)]),'String','X')
gewinnmoeglichkeiten()% überprüfen ob Spiel beendet (Sieger KI) end
1.) Ask MATLAB Documentation
2.) Search gomatlab.de, google.de or MATLAB Answers
3.) Ask Technical Support of MathWorks
4.) Go mad, your problem is unsolvable ;)
Mr. P
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 01.02.2011, 23:51
Titel:
Hallo Harald,
jetzt habe auch ich deine ansatz verstanden ;P und danke dir für den guten Mühen. Es tut mir leid wenn ich dich hier vielleicht zur weißglut treibe aber wie gesagt ich bin nicht wirklich fit im programmieren.
Ich hab probiert deinen Ansatz umzusetzen und zum test wahl=3 gesetzt, dann kam mal wieder der tolle fehlerton von matlab,den ich übrigens mittlerweile auch schon im schlaf hören kann und zeigt mir im command window " Undefined variable handles." an. Um ehrlich zu sein ist mir nicht ganz klar warum ich hier handles benötige. Dient es dazu die oberfläche der schon gemachten züge abzuspeicher damit die ki function keine ewig lange if-abfrage wir?
(ich entschuldige mich jetzt schon mal für die frage aber ich weis mir wirklich nicht zu helfen)
handles ist ein struct in dem alle Informationen über die Elemente deines GUI stehen. Um die Eigenschaft eines anderen Elementes ausser button zu ändern (in deinem Fall die Eigenschaft String des Buttons welches die KI auswählt) musst du dieses struct mit an die callback funktion übergeben.
Falls du das GUI mit guide erstellt hast sollte es handles geben. Vielleicht hast du nur vergessen den Funktionsaufruf zu ändern ?!
Code:
function klick_button(button,eventdata, handles)% <-- handles wird gebraucht
zeigt mir im command window " Undefined variable handles."
Normal sind Fehlermeldungen etwas länger und beinhalten wertvolle informationen um den Fehler im Code zu finden.
Poste dann doch bitte beides um dir richtig helfen zu können und nicht raten zu müssen.
_________________
Ich hab das Spiel nicht mit hilfe des Guides programmiert sondern die einzelnen funktion des programms eigentständig geschrieben. Die guide oberfläche nur allgemein zugewiesen. Also die einzelnen buttons definiert (aussehen,größe,callback auf die sie zugreifen) usw.
Deswegen war mir handles auch nur bekannt aus den quasi vorgefertigten callbacks der guides.
Ich hab hier die idee von harald mal eingebaut um sie zu testen hat aber wie gesagt noch nicht so funktioniert wie ich mir das gedacht hatte.
Hier der gesamte code und darunter die Fehlermeldung
[code]
function tic_tac_toe_projekt()
%Formatieren der Bedienoberfläche
f = figure('Name','Tic-Tac-Toe','Color','green','Units','centimeters',...
'Position',[5,5,15,11]);
%Zeichenwechsel --> 0=X; 1=O
global turn
turn = 0;
global buttons
buttons = [button1,button2,button3,button4,button5,button6,button7,button8,button9];
end
function klick_button(button,eventdata,handles) % <-- handles wird gebraucht
% Callback function für die 9-Buttons <-- Mensch drückt
% Hier grundsätzlich: Mensch macht O, KI macht X
% untersucht ob das feld noch frei ist
if get(button,'String') == 'X'
errordlg('Diese Feld ist bereit besetzt!!') % Pop-up zeigt an dass das feld schon benutzt wurde
return
elseif get(button,'String') == 'O'
errordlg('Diese Feld ist bereit besetzt!!')
return
else
set(button,'String','O') % Zug des Menschen
gewinnmoeglichkeiten() % überprüfen ob Spiel beendet (Sieger Mensch)
wahl=3;
set(handles(['Button' num2str(wahl)]),'String','X')
gewinnmoeglichkeiten()
% überprüfen ob Spiel beendet (Sieger KI)
end
end
function gewinnmoeglichkeiten()
global button1 button2 button3 button4 button5 button6 button7 button8 button9
function neuesspiel(button,eventdata,handles)
%setzt alle felder zurück
global buttons turn
for btn = buttons
set(btn,'String','')
end
turn=0;
end
function gewinner(zeichen)
% Gewinner wird auf der plattform angezeigt
global button2 button4 button5 button6 button8
neuesspiel()
set(button2,'String',zeichen)
set(button4,'String','W')
set(button5,'String','I')
set(button6,'String','N')
set(button8,'String','!')
pause(2)
neuesspiel()
end
Fehlermeldung:
function ende(button,eventdata,handles,f)
%quit game
delete(f)
end
??? Input argument "handles" is undefined.
Error in ==> tic_tac_toe_projekt>klick_button at 60
set(handles(['Button' num2str(wahl)]),'String','X')
function klick_button(button,eventdata,handles)% <-- handles wird gebraucht % Callback function für die 9-Buttons <-- Mensch drückt % Hier grundsätzlich: Mensch macht O, KI macht X % untersucht ob das feld noch frei ist
ifget(button,'String') == 'X'
errordlg('Diese Feld ist bereit besetzt!!')% Pop-up zeigt an dass das feld schon benutzt wurde return elseifget(button,'String') == 'O'
errordlg('Diese Feld ist bereit besetzt!!') return else set(button,'String','O')% Zug des Menschen
gewinnmoeglichkeiten()% überprüfen ob Spiel beendet (Sieger Mensch)
wahl=3;
set(buttons(wahl),'String','X')
gewinnmoeglichkeiten() % überprüfen ob Spiel beendet (Sieger KI) end end
du musst die Eigenschaft des gewünschten buttons ändern. Allerdings musst du noch überprüfen ob das Feld bereits besetzt ist. Überhaupt hast du nirgends abgespeichert welche Felder wie belegt sind. Um die KI zu programmieren solltest du das tun.
Mr. P
Gast
Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
Verfasst am: 02.02.2011, 16:40
Titel:
Ich dachte es ist nich unbedingt wichtig abzuspeicher welche felder wie beleget sind, da ich das in der funktion der KI überprüfen wollte. Also eine größere if-schleife in der die KI abfragt ob das feld bereits ein zeichen enthät und wenn ja sich ein anderes feld sucht. Aufgrunddessen dachte ich handles seit nicht nötig oder muss ich die spieloberfläche zwingend abspeichern? Meiner Meinung würde das nur code sparen im Bezug auf die funktion der ki. (die ki ist im geposteten code nicht enthalten, da ich nur haralds lösungsansatz ausprobieren wollte und wahl=3 gesezt, darauf aber schon der gepostete fehler angezeigt wurde)
Gruß
Einstellungen und Berechtigungen
Du kannst Beiträge in dieses Forum schreiben. Du kannst auf Beiträge in diesem Forum antworten. Du kannst deine Beiträge in diesem Forum nicht bearbeiten. Du kannst deine Beiträge in diesem Forum nicht löschen. Du kannst an Umfragen in diesem Forum nicht mitmachen. Du kannst Dateien in diesem Forum posten Du kannst Dateien in diesem Forum herunterladen
MATLAB, Simulink, Stateflow, Handle Graphics, Real-Time Workshop, SimBiology, SimHydraulics, SimEvents, and xPC TargetBox are registered trademarks and The MathWorks, the L-shaped membrane logo, and Embedded MATLAB are trademarks of The MathWorks, Inc.