WICHTIG: Der Betrieb von goMatlab.de wird privat finanziert fortgesetzt. - Mehr Infos...

Mein MATLAB Forum - goMatlab.de

Mein MATLAB Forum

 
Gast > Registrieren       Autologin?   

Partner:




Forum
      Option
[Erweitert]
  • Diese Seite per Mail weiterempfehlen
     


Gehe zu:  
Neues Thema eröffnen Neue Antwort erstellen

KI programmieren für Tic-Tac-Toe

 

Mr. P

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 31.01.2011, 17:40     Titel: KI programmieren für Tic-Tac-Toe
  Antworten mit Zitat      
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

global turn

% 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
elseif  turn == 0
% wenn X geht
    set(button,'String','X')
    turn = 1;
% andernfalls geht O
else
    set(button,'String','O')
    turn = 0;
end


gewinnmoeglichkeiten()

end


Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 31.01.2011, 18:26     Titel:
  Antworten mit Zitat      
Hallo,

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 ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Mr. P

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 31.01.2011, 21:54     Titel:
  Antworten mit Zitat      
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.

gruß
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 31.01.2011, 23:18     Titel:
  Antworten mit Zitat      
Hallo,

das habe ich ja schon versucht, zu sagen:

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.

Oder anders gesagt:
Code:
if (KI beginnt)
% KI macht ersten Zug.
end

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)


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 ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Thomas84
Forum-Meister

Forum-Meister


Beiträge: 546
Anmeldedatum: 10.02.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.02.2011, 07:45     Titel:
  Antworten mit Zitat      
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

global turn

% 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
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



end






 
Private Nachricht senden Benutzer-Profile anzeigen
 
Mr. P

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.02.2011, 20:43     Titel:
  Antworten mit Zitat      
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 ?
 
Harald
Forum-Meister

Forum-Meister


Beiträge: 24.501
Anmeldedatum: 26.03.09
Wohnort: Nähe München
Version: ab 2017b
     Beitrag Verfasst am: 01.02.2011, 20:54     Titel:
  Antworten mit Zitat      
Hallo,

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

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 = ... % 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
 


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 ;)
Private Nachricht senden Benutzer-Profile anzeigen
 
Mr. P

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 01.02.2011, 23:51     Titel:
  Antworten mit Zitat      
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)

Gruß
 
Thomas84
Forum-Meister

Forum-Meister


Beiträge: 546
Anmeldedatum: 10.02.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.02.2011, 07:47     Titel:
  Antworten mit Zitat      
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
 
Private Nachricht senden Benutzer-Profile anzeigen
 
_Peter_
Moderator

Moderator


Beiträge: 537
Anmeldedatum: 08.12.10
Wohnort: ---
Version: 7.10, 2010a
     Beitrag Verfasst am: 02.02.2011, 08:36     Titel:
  Antworten mit Zitat      
Zitat:

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.
_________________

Gruß
Peter
_________________
goMatlab-Knigge - dran gehalten?!
Schon in den FAQ gesucht? Oder der MATLAB Hilfe?
Ist vielleicht bei den Skripten oder den Tutorials was für dich dabei?
Private Nachricht senden Benutzer-Profile anzeigen
 
Mr. P

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.02.2011, 13:53     Titel:
  Antworten mit Zitat      
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;

% Buttons Zuweisen
global button1 button2 button3 button4 button5 button6 button7 button8 button9
button1 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[3,7.5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button2 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[5.5,7.5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button3 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[8,7.5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button4 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[3,5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button5 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[5.5,5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button6 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[8,5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button7 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[3,2.5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button8 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[5.5,2.5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
button9 = uicontrol(f,'Style','pushbutton','BackgroundColor','white','Units','centimeters',...
'Position',[8,2.5,2.5,2.5],'FontSize',36,'Callback',@klick_button);
uicontrol(f,'Style','pushbutton','Units','centimeters',...
'Position',[3.5,1.5,4,1],'String','Neues Spiel','FontSize',14,...
'Callback',@neuesspiel);
uicontrol(f,'Style','pushbutton','Units','centimeters',...
'Position',[7.5,1.5,2,1],'String','Ende','FontSize',14,...
'Callback',{@ende,f})


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

% Gewinnmöglichkeiten ( true=1 --> true+true=2)
if (get(button1,'String') == get(button2,'String')) + (get(button2,'String')== get(button3,'String'))==2 %
gewinner(get(button1,'String')) %
elseif (get(button4,'String') == get(button5,'String')) + (get(button5,'String')== get(button6,'String'))==2 % horizontaler Sieg
gewinner(get(button4,'String')) %
elseif (get(button7,'String') == get(button8,'String')) + (get(button8,'String')== get(button9,'String'))==2 %
gewinner(get(button7,'String'))
elseif (get(button1,'String') == get(button4,'String')) + (get(button4,'String')== get(button7,'String'))==2 %
gewinner(get(button1,'String')) %
elseif (get(button2,'String') == get(button5,'String')) + (get(button5,'String')== get(button8,'String'))==2 % vertikaler Sieg
gewinner(get(button2,'String')) %
elseif (get(button3,'String') == get(button6,'String')) + (get(button6,'String')== get(button9,'String'))==2 %
gewinner(get(button4,'String'))
elseif (get(button1,'String') == get(button5,'String')) + (get(button5,'String')== get(button9,'String'))==2 %
gewinner(get(button1,'String')) % diagonale Sieg
elseif (get(button3,'String') == get(button5,'String')) + (get(button5,'String')== get(button7,'String'))==2 %
gewinner(get(button3,'String'))
end

end


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')

??? Error while evaluating uicontrol Callback


Vielen dank für eure Mühen bisher
Gruß philipp
 
Thomas84
Forum-Meister

Forum-Meister


Beiträge: 546
Anmeldedatum: 10.02.10
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.02.2011, 14:05     Titel:
  Antworten mit Zitat      
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

global buttons

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(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.
Private Nachricht senden Benutzer-Profile anzeigen
 
Mr. P

Gast


Beiträge: ---
Anmeldedatum: ---
Wohnort: ---
Version: ---
     Beitrag Verfasst am: 02.02.2011, 16:40     Titel:
  Antworten mit Zitat      
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ß
 
Neues Thema eröffnen Neue Antwort erstellen



Einstellungen und Berechtigungen
Beiträge der letzten Zeit anzeigen:

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
.





 Impressum  | Nutzungsbedingungen  | Datenschutz | FAQ | goMatlab RSS Button RSS

Hosted by:


Copyright © 2007 - 2025 goMatlab.de | Dies ist keine offizielle Website der Firma The Mathworks

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.