![]() |
AW: Memory-Spiel: Ideen
Zitat:
Logisch dass ich keine ![]() |
AW: Memory-Spiel: Ideen
Wenn ich mich richtig erinnere schrieb ich ProgrammAblaufPlan. Oder wie ein geschätztes Mitglied dieses Forums schreibt "dann programmiere mal mit Bleistift und Papier".
Es geht ja nicht darum nach irgendeiner Norm ein Schaubild zu erstellen, sondern notwendige Strukturen, Abhängigkeiten und Abläufe einmal für sich selbst darzustellen. Und die gewünschte Logik daran zu überprüfen. Und ich bin wahrhaftig kein Fan der "Klassen, Klassen über alles"-Bewegung, aber manchmal kommt man nicht daran vorbei, machmal machen sie das Leben einfacher, aber um das zu beurteilen muß man schon wissen was Klassen überhaupt sind und wofür und wie man sie einsetzen kann/muß. Und wenn Du jetzt die Gelegenheit hast, Dich damit auseinander zu setzen, dann solltest Du das auch tun. Später könnte zu spät sein. Wenn die anderen das nicht brauchen, deren Sache. Gruß K-H |
AW: Memory-Spiel: Ideen
Mavarick, ich kann dich darin nur bestätigen: Ohne minimale Aufzeichnungen dessen, was die Anwendung machen soll und wie ich die einzelnen Anforderungen unterteile und umsetze, fange ich schon lange nicht mehr zu programmieren an. Bevor bei mir Delphi für eine neue Anwendung gestartet wird, wird erst einmal OpenOffice gestartet und ein bissel was geschrieben. Ist die Anwendung sehr komplex, starte ich CorelDraw und mache mir eine schematische Darstellung. Spezielle Struktogramm-Software verwende ich nicht, wäre aber sicher interessant.
Mir passiert es häufig, daß ich mitten in der Programmierung (ich arbeite zu Hause) bemerke, daß mir die Konzentration schwerzufallen beginnt, weil ich z.B. schon seit über 10 Stunden ununterbrochen an etwas dran bin. Dann bin ich so frei und lege mich hin, egal welche Tages- oder Nachtzeit. Manchmal kann ich dann nicht gleich einschlafen, weil mir noch Dinge durch den Kopf gehen, und nicht selten kommt es dann vor, daß mir eine Lösung einfällt. Deshalb liegt bei mir vor dem Bett oder manchmal auch im Bett (das ist riesig) immer ein Block mit Bleistift, und der ist schon wieder fast voll. Oft wache ich auch auf und habe eine Idee, die ich dann ebenfalls erstmal notiere, bevor ich aufstehe. Aber ich versteh auch die Schüler, nicht zuletzt, weil in der EE ein Gymnasiallehrer (Mathematiker) genau darüber schon geschrieben hat: Die Schüler interessiert die Programmiererei meistens nicht wirklich, die wollen gewöhnlich nur eine gute Note. Sogar diese Mimi (eine Schülerin von Mathematiker) in diesem berühmten EE-Thread, wo ein User ihr wochenlang täglich beim Verständnis von Delphi geholfen hat, zeigt nun, da sie für ihre Mühe eine 1 erhalten hat, keinerlei weiteres Interesse mehr am Programmieren. Natürlich wissen die Schüler, die hier und in den anderen Delphi-Foren aufschlagen, auch meist ganz genau, wie sie sich zu verhalten haben, um bei den Leuten hier die eine oder andere Copy&Paste-Fähige Lösung herauszukitzeln. Manche werden auch gleich unverschämt und halten das dann auch noch für Stärke, mit der sie bei ihren Kumpels protzen können: "Guck ma, dem hab ich's aber gezeigt, wa?" |
AW: Memory-Spiel: Ideen
Liste der Anhänge anzeigen (Anzahl: 1)
Da ich mich gerade mit der StateMachine befasst habe hier ein Zahlen-Paar-Ratespiel mit der StateMachine realisiert.
Der gesamte Ablauf-Plan wird in der StateMachine abgebildet. Der Rest ist nur noch Reaktion auf den Wechsel der States. Der Quellcode ist keine CopyPaste-Vorlage für den TE, sondern als Anhaltspunkt für den benötigten Ablaufplan gedacht. Im Anhang befindet sich die lauffähige EXE.
Delphi-Quellcode:
unit ZahlenPaareRaten.Forms.MainForm;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, stateless; // => https://github.com/SirRufo/stateless type TForm1 = class( TForm ) CardPanel: TGridPanel; TriggerTimer: TTimer; Label1: TLabel; procedure TriggerTimerTimer( Sender: TObject ); procedure FormShow( Sender: TObject ); procedure Label1Click( Sender: TObject ); private type {$SCOPEDENUMS ON} TState = ( Start, Memoize, Running, FirstDrawn, SecondDrawn, NoMatch, Match, Finished ); TTrigger = ( StartGame, Run, DrawCard, DrawNext ); TCardState = ( Bottom, Up, Hidden ); {$SCOPEDENUMS OFF} TStateMachine = TStateMachine<TState, TTrigger>; private FCardStates : array [ 0 .. 15 ] of TCardState; FCards : array [ 0 .. 15 ] of Integer; FState : TStateMachine; FDrawCardTrigger : TStateMachine.TTriggerWithParameters<Integer>; FTriggerTimerTrigger: TTrigger; procedure ConfigureStateMachine( State: TStateMachine ); procedure ResetGame; procedure PresentCards; procedure BuildCardControls; procedure StartTriggerTimer( Trigger: TTrigger; Interval: Cardinal ); public procedure AfterConstruction; override; procedure BeforeDestruction; override; published procedure CardClick( Sender: TObject ); end; var Form1: TForm1; implementation uses Enumerables; // nicht enthalten {$R *.dfm} { TForm1 } procedure TForm1.AfterConstruction; begin inherited; FState := TStateMachine.Create( TState.Start ); FDrawCardTrigger := FState.SetTriggerParameters<Integer>( TTrigger.DrawCard ); ConfigureStateMachine( FState ); BuildCardControls; ResetGame; end; procedure TForm1.BeforeDestruction; begin FState.Free; inherited; end; procedure TForm1.BuildCardControls; var Row : Integer; Col : Integer; Control: TButton; begin for Row := 0 to CardPanel.RowCollection.Count - 1 do for Col := 0 to CardPanel.ColumnCollection.Count - 1 do begin Control := TButton.Create( Self ); Control.Parent := CardPanel; Control.Margins.SetBounds( 3, 3, 3, 3 ); Control.AlignWithMargins := True; Control.Align := alClient; Control.OnClick := CardClick; end; end; procedure TForm1.CardClick( Sender: TObject ); var Control : TControl absolute Sender; CardIndex: Integer; begin if not( Sender is TControl ) then Exit; CardIndex := CardPanel.ControlCollection.IndexOf( Control ); if ( CardIndex >= 0 ) and FState.CanFire( TTrigger.DrawCard ) then FState.Fire<Integer>( FDrawCardTrigger, CardIndex ); end; procedure TForm1.ConfigureStateMachine( State: TStateMachine ); var firstCard, secondCard, matchCount: Integer; begin State.Configure( TState.Start ) {} .OnEntry( procedure begin matchCount := 0; ResetGame; PresentCards; end ) {} .Permit( TTrigger.StartGame, TState.Memoize ) {end}; State.Configure( TState.Memoize ) {} .OnEntry( procedure var I: Integer; begin Label1.Caption := 'Merke dir jetzt die Karten'; for I := 0 to 15 do FCardStates[ I ] := TCardState.Up; PresentCards; StartTriggerTimer( TTrigger.Run, 6000 ); end ) {} .OnExit( procedure var I: Integer; begin for I := 0 to 15 do FCardStates[ I ] := TCardState.Bottom; PresentCards; end ) {} .Permit( TTrigger.Run, TState.Running ) {end}; State.Configure( TState.Running ) {} .OnEntry( procedure begin Label1.Caption := 'Wähle die erste Karte'; PresentCards; end ) {} .PermitDynamic<Integer>( FDrawCardTrigger, function( const c: Integer ): TState begin if FCardStates[ c ] = TCardState.Bottom then Result := TState.FirstDrawn else Result := TState.Running; end ) {end}; State.Configure( TState.FirstDrawn ) {} .OnEntry( procedure begin Label1.Caption := 'Wähle die zweite Karte'; end ) {} .OnEntryFrom<Integer>( FDrawCardTrigger, procedure( const c: Integer ) begin firstCard := c; FCardStates[ c ] := TCardState.Up; PresentCards; end ) {} .PermitDynamic<Integer>( FDrawCardTrigger, function( const c: Integer ): TState begin if FCardStates[ c ] = TCardState.Bottom then begin if FCards[ firstCard ] = FCards[ c ] then Result := TState.Match else Result := TState.NoMatch; end else Result := TState.FirstDrawn; end ) {end}; State.Configure( TState.SecondDrawn ) {} .OnEntryFrom<Integer>( FDrawCardTrigger, procedure( const c: Integer ) begin secondCard := c; FCardStates[ c ] := TCardState.Up; PresentCards; end ) {} .PermitDynamic( TTrigger.DrawNext, function( ): TState begin if matchCount = 8 then Result := TState.Finished else Result := TState.Running; end ) {end}; State.Configure( TState.NoMatch ) {} .SubstateOf( TState.SecondDrawn ) {} .OnEntry( procedure begin Label1.Caption := 'Schade, die Karten passen nicht'; StartTriggerTimer( TTrigger.DrawNext, 2000 ); end ) {} .OnExit( procedure begin FCardStates[ firstCard ] := TCardState.Bottom; FCardStates[ secondCard ] := TCardState.Bottom; end ) {end}; State.Configure( TState.Match ) {} .SubstateOf( TState.SecondDrawn ) {} .OnEntry( procedure begin Label1.Caption := 'Karten passen zusammen'; Inc( matchCount ); StartTriggerTimer( TTrigger.DrawNext, 500 ); end ) {} .OnExit( procedure begin FCardStates[ firstCard ] := TCardState.Hidden; FCardStates[ secondCard ] := TCardState.Hidden; end ) {end}; State.Configure( TState.Finished ) {} .OnEntry( procedure begin Label1.Caption := 'Spiel beendet. Klicke hier um nochmal zu spielen'; PresentCards; end ) {} .Permit( TTrigger.StartGame, TState.Start ) {end}; end; procedure TForm1.FormShow( Sender: TObject ); begin PresentCards; end; procedure TForm1.Label1Click( Sender: TObject ); begin if FState.CanFire( TTrigger.StartGame ) then FState.Fire( TTrigger.StartGame ); end; procedure TForm1.PresentCards; var Item : TCollectionItem; Button: TButton; begin for Item in CardPanel.ControlCollection do begin Button := TButton( TControlItem( Item ).Control ); case FCardStates[ Item.Index ] of TCardState.Bottom: begin Button.Visible := True; Button.Caption := '?'; end; TCardState.Up: begin Button.Visible := True; Button.Caption := IntToStr( FCards[ Item.Index ] ); end; TCardState.Hidden: begin Button.Visible := False; end; end; end; end; procedure TForm1.ResetGame; var I : Integer; lcards: TArray<Integer>; begin lcards := Enumerable {} .Range( 1, 99 ) // Zahlen von 1 bis 99 {} .Shuffle( ) // mischen {} .Take( 8 ) // 8 nehmen {} .ToArray( ) // in ein Array {end}; lcards := Enumerable {} .From<Integer>( lcards ) // die 8 Zahlen von eben {} .Concat( lcards ) // mit den 8 Zahlen von eben verbinden (jetzt haben wir die Paare) {} .Shuffle( ) // mischen {} .ToArray( ) // in ein Array {end}; for I := 0 to 15 do begin FCardStates[ I ] := TCardState.Bottom; FCards[ I ] := lcards[ I ]; end; Label1.Caption := 'Zum Starten hier drücken'; end; procedure TForm1.StartTriggerTimer( Trigger: TTrigger; Interval: Cardinal ); begin TriggerTimer.Enabled := False; TriggerTimer.Interval := Interval; FTriggerTimerTrigger := Trigger; TriggerTimer.Enabled := True; end; procedure TForm1.TriggerTimerTimer( Sender: TObject ); begin TriggerTimer.Enabled := False; if FState.CanFire( FTriggerTimerTrigger ) then begin FState.Fire( FTriggerTimerTrigger ); end; end; end. |
AW: Memory-Spiel: Ideen
Zitat:
Delphi-Quellcode:
Und dokumentiere es mit DocInside. Somit hab ich es nicht vergessen, es kommt ins Repo usw...
TWirdnochwas = Class
Procedure Machwas; end; Meine Gekritzel finden nur den Weg in die digitale Welt, wenn ich es für andere brauche... |
AW: Memory-Spiel: Ideen
Hatte mit letztens auch ein paar Gedanken gemacht. Voraussetzung wäre aber daß ihr euch etwas mit Klassen beschäftigt (ist nicht sooooo schwer). Was nämlich ein schönes Schmankerl wäre, wenn man die Karten so anordnen könnte, wie man es beim Memoryspiel auch macht (kreuz und quer, auch schräg, Stichworte: tagXFORM, SetGraphicsMode und SetWorldTransform). Wäre aber etwas Programmieraufwand (Prüfen ob die Karten sich überlappen und auf welche Karte geklickt wurde). Zeichnen würde man das Ganze dann in eine Paintbox.
Mal so ins Blaue getippt:
Delphi-Quellcode:
type
TMemoryCardStatus = (mcsNone, mcsOpen, mcsClosed, mcsPlayer1, mcsPlayer2, ..); TMemoryCard = class private FX: integer; FY: integer; FWidth: integer; FHeight: integer; FAlpha: integer; FFrontBitmap: TBitmap; FBackBitmap: TBitmap; FStatus: TMemoryCardStatus; public property X: integer read FX write FX; property Y: integer read FY write FY; property Width: integer read FWidth write FWidth; property Height: integer read FHeight write FHeight; property Alpha: integer read FAlpha write FAlpha; property FrontBitmap: TBitmap read FFrontBitmap; property BackBitmap: TBitmap read FBackBitmap; property Status: TMemoryCardStatus read FStatus write FStatus; function Intersect(Value: TMemoryCard): boolean; function PtIn(X, Y: integer): boolean; procedure Draw(Canvas: TCanvas); constructor Create; destructor Destroy; override; end; TMemoryCards = class(TObjectList) private function GetItems(Index: integer): TMemoryCard; function Intersect: boolean; public procedure Start(CanvasWidth, CanvasHeight: integer); procedure Draw(Canvas: TCanvas); function IndexOfPtIn(X, Y, CanvasWidth, CanvasHeight: integer): integer; property Items[Index: integer]: TMemoryCard read GetItems; default; end; |
AW: Memory-Spiel: Ideen
Zitat:
![]() Oder wirklich per Hand? |
AW: Memory-Spiel: Ideen
Nett. ;)
|
AW: Memory-Spiel: Ideen
Jo nice :D
Wir sollen nur ein Programm machen, es muss gut aussehen und laufen. Ob die Technik, also der Quellcode im Hintergrund optimiert ist oder nicht ist erstmal egal. Bei uns in der Abschlussprüfung gibt es 2 Wahlaufgaben am Ende. 1) Mit Diagrammen arbeiten und anschließendem Klassen- programmieren. 2) Anbindung einer Datenbank an Delphi (Access), arbeiten OHNE Klassen, arbeiten mit Textdateien Mehr gibt es bei uns nicht. Dann noch Theorie wie Rechnerarchitektur, Ablaufpläne, GANNT-Diagramme, Wirtschaftsinformatik, Logikpläne, Schaltpläne. Daraus besteht die Prüfung. 60 Punkte sind Theorie- Fragen und 30 Punkte sind Programmieren. Mittlerweile komme ich ganz gut voran, und schreibe sogar manchmal was auf einen Zettel :P |
AW: Memory-Spiel: Ideen
Liste der Anhänge anzeigen (Anzahl: 1)
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:49 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz