Snake: Eure Meinung...



  • Ich hätte gerne eure Meinung zum Aufbau von meinem Snake-Spiel. Mir geht es einfach darum ob ich was verändern sollte, oder ob ich meinen programmierstil grundsätzlich ändern sollte.
    Der Code ist doch ziemlich umfangreich geworden:

    #include <windows.h>
    #include <stdio.h>
    
    #define ID_BUTTON_START    1
    #define ID_BUTTON_PAUSE    2
    #define ID_BUTTON_ENDE     3
    #define ID_EDIT_ZEIT       4
    #define ID_EDIT_VERLAENGERN 5
    #define ID_BUTTON_WAND     6
    
    //Richtung der Schlange
    #define RT_HOCH         1
    #define RT_RECHTS       2
    #define RT_RUNTER       3
    #define RT_LINKS        4
    
    //Timer
    #define Timer_ID        1
    
    //Richtung der Schlangenteile
    #define WAAGRECHT       1
    #define SENKRECHT       2
    #define PUNKT           3
    #define BG_LINKS        4
    #define BG_HOCH         5
    #define BG_RECHTS       6
    #define BG_RUNTER       7
    
    #define MAX             4000 //MaxSchlangenlänge
    
    //TCHAR = char
    //PSTR = LPSTR = *char; 
    int  status, aktiv = 0, befehl = 0, iPunkt[3], iPunkte = 0, iPproPunkt = 0, iZeit, iVerlaengerung; //iPunkte = Anzahl der Erreichten Punkte, berechnet mit iPproPunkt
    int  iPosition[MAX][4] = {0}; //0 = xKoordinate, 1 = yKoordinate, 2 = Ausrichtung
    int  iRichtung, xFelder, yFelder, iSchlLaenge;
    int  iPrevRichtung;
    static HWND hwndHauptFenster, PrevWndProcEditZeit, PrevWndProcEditVerlaengerung, hwndEditZeit, hwndEditVerlaengerung, hwndButtonWand;
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT CALLBACK ChildWndProcEditZeit(HWND, UINT, WPARAM, LPARAM);
    VOID             Thread(PVOID);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int iCmdShow)
    {
    	static TCHAR szAppName[] = TEXT("Snake");
    	HWND         hwnd;
    	MSG          msg;
    	WNDCLASS     wndclass;
    
    	wndclass.style = CS_HREDRAW | CS_VREDRAW;
    	wndclass.lpfnWndProc   = WndProc;
    	wndclass.cbClsExtra    = 0;
    	wndclass.cbWndExtra    = 0;
    	wndclass.hIcon         = LoadIcon(NULL, IDI_APPLICATION);
    	wndclass.hCursor       = LoadCursor(NULL, IDC_ARROW);
    	wndclass.hInstance     = hInstance;
    	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    	wndclass.lpszMenuName  = 0;
    	wndclass.lpszClassName = szAppName;
    
    	RegisterClass(&wndclass);
    
    	hwnd = CreateWindow(szAppName, TEXT("Snake"),
    						WS_OVERLAPPEDWINDOW,
    						CW_USEDEFAULT, CW_USEDEFAULT,
    						CW_USEDEFAULT, CW_USEDEFAULT,
    						NULL, NULL, hInstance, NULL);
    
    	ShowWindow(hwnd, iCmdShow);
    	UpdateWindow(hwnd);
    
    	while(GetMessage(&msg, NULL, 0, 0))
    	{
    		TranslateMessage(&msg);
    		DispatchMessage(&msg);
    	}
    	return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	static HWND        hwndButtonStart, hwndButtonEnde, hwndButtonPause;
    	static int         cyChar, cxChar, cyClient, cxClient;  
    	PAINTSTRUCT        ps;
    	HDC                hdc;
    	static RECT        rect, rectUpdate;
    	static HBRUSH      hBrush;
    	int                i;
    	static BOOL        bPause;
    	TCHAR              cBuffer[20];
    	static HMENU       SysMenu;
    	HRGN hRgnTemp[6];
    	HPEN hPen1;
    
    	switch(message)
    	{
    	case WM_PAINT:
    
    		hdc = BeginPaint(hwnd, &ps);
    
    		MoveToEx(hdc, cxChar * 2, cyChar * 6, NULL);
    		LineTo(hdc, cxChar * 2, cyChar * 6 + 11 * yFelder);
    		LineTo(hdc, cxChar * 2 + 11 * xFelder, cyChar * 6 + 11 * yFelder);
    		LineTo(hdc, cxChar * 2 + 11 * xFelder, cyChar * 6);
    		LineTo(hdc, cxChar * 2, cyChar * 6);
    		SelectObject(hdc, CreateSolidBrush(RGB(0, 0, 0)));
    		if(aktiv == 1)
    		{
    
    			Ellipse(hdc, cxChar * 2 + 1 + iPosition[0][0] * 11 - 1 - 5 - 3, 
    					     cyChar * 6 + 1 + iPosition[0][1] * 11 - 1 - 5 - 3, 
    						 cxChar * 2 + 1 + iPosition[0][0] * 11 - 1 - 5 + 2, 
    						 cyChar * 6 + 1 + iPosition[0][1] * 11 - 1 - 5 + 2);
    
    			for(i = 1; i < iSchlLaenge + 1; i++)
    			{
    
    				switch(iPosition[i][2])
    				{
    				case SENKRECHT:
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 5,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 5); //5 breit, 10 hoch
    					FillRect(hdc, &rect, hBrush);
    					break;
    
    				case WAAGRECHT:
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 5, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 5, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2); //10 breit, 5 hoch
    					FillRect(hdc, &rect, hBrush);
    					break;
    
    				case PUNKT:
    					SelectObject(hdc, CreateSolidBrush(RGB(0, 0, 0)));
    
    					Ellipse(hdc, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3,
    						         cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								 cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2,
    								 cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2);
    
    					break;
    
    				case BG_RUNTER:
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 5, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2); //10 breit, 5 hoch
    					FillRect(hdc, &rect, hBrush);
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 5); //5 breit, 10 hoch
    					FillRect(hdc, &rect, hBrush);
    					break;
    
    				case BG_RECHTS:
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 5, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2); //10 breit, 5 hoch
    					FillRect(hdc, &rect, hBrush);
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 5,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2); //5 breit, 10 hoch
    					FillRect(hdc, &rect, hBrush);
    					break;
    
    				case BG_HOCH:
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 5, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2); //10 breit, 5 hoch
    					FillRect(hdc, &rect, hBrush);
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 5,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2); //5 breit, 10 hoch
    					FillRect(hdc, &rect, hBrush);
    					break;
    
    				case BG_LINKS:
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 5, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 2); //10 breit, 5 hoch
    					FillRect(hdc, &rect, hBrush);
    					SetRect(&rect, cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 - 3, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 - 3,
    								   cxChar * 2 + 1 + iPosition[i][0] * 11 - 1 - 5 + 2, 
    								   cyChar * 6 + 1 + iPosition[i][1] * 11 - 1 - 5 + 5); //5 breit, 10 hoch
    					FillRect(hdc, &rect, hBrush);
    
    					break;
    				}
    			}
    			if(iPunkt[2] == 1)
    				Ellipse(hdc, cxChar * 2 + 1 + iPunkt[0] * 11 - 1 - 5 - 2,
    							 cyChar * 6 + 1 + iPunkt[1] * 11 - 1 - 5 - 2,
    							 cxChar * 2 + 1 + iPunkt[0] * 11 - 1 - 5 + 2,
    							 cyChar * 6 + 1 + iPunkt[1] * 11 - 1 - 5 + 2);
    		}
    		TextOut(hdc, cxClient - cxChar * 8 - cxChar * 20, cyChar + 10,     "Dauer pro Schritt(ms):", 22);
    		TextOut(hdc, cxClient - cxChar * 8 - cxChar * 20, cyChar * 2 + 15, "+Länge:", 7);
    		TextOut(hdc, cxClient - cxChar * 8 - cxChar * 20, cyChar * 3 + 20, "Wand durchgängig:", 17);
    		TextOut(hdc, cxChar * 2, cyChar + 10, TEXT("Punkte pro Treffer:"), 19);
    		TextOut(hdc, cxChar * 2, cyChar * 2 + 15, TEXT("Gesamtpunkte:"), 13);
    		SetTextAlign(hdc, TA_RIGHT);
    		TextOut(hdc, cxChar	* 20, cyChar + 10, cBuffer, wsprintf(cBuffer, TEXT("%d"), iPproPunkt));
    		TextOut(hdc, cxChar	* 20, cyChar * 2 + 15, cBuffer, wsprintf(cBuffer, TEXT("%d"), iPunkte));
    		EndPaint(hwnd, &ps);
    		return 0;
    
    	case WM_SIZE:
    		cxClient = LOWORD(lParam);
    		cyClient = HIWORD(lParam);
    		SetWindowPos(hwndButtonStart, HWND_TOP, cxClient / 4 - cxChar * 10, cyChar * 2, cxChar * 20, cyChar * 3, SWP_SHOWWINDOW);
    		SetWindowPos(hwndButtonPause, HWND_TOP, cxClient / 2 - cxChar * 10, cyChar * 2, cxChar * 20, cyChar * 3, SWP_SHOWWINDOW);
    		SetWindowPos(hwndButtonEnde, HWND_TOP, cxClient / 4 * 3 - cxChar * 10, cyChar * 2, cxChar * 20, cyChar * 3, SWP_SHOWWINDOW);
    		SetWindowPos(hwndEditZeit, HWND_TOP, cxClient - cxChar * 8, cyChar + 10, cxChar * 5, cyChar, SWP_SHOWWINDOW);
    		SetWindowPos(hwndEditVerlaengerung, HWND_TOP, cxClient - cxChar * 8, cyChar * 2 + 15, cxChar * 4, cyChar, SWP_SHOWWINDOW);
    		SetWindowPos(hwndButtonWand, HWND_TOP, cxClient - cxChar * 8, cyChar * 3 + 20, cyChar, cyChar, SWP_SHOWWINDOW);
    		//Abstand zum Rand = 2 * cxChar
    		//1 Feld = 10 x 10 + 1 Abstand zum nächsten Feld
    		xFelder = ((cxClient - 4 * cxChar) - 1) / 11;
    		yFelder = (cyClient - 6 * cyChar - 2 * cxChar - 1) / 11;
    		SetRect(&rectUpdate, cxChar * 2, cyChar * 6, cxChar * 2 + 11 * xFelder, cyChar * 6 + 11 * yFelder);
    		return 0;
    
    	case WM_CREATE:
    		hBrush = CreateSolidBrush(RGB(0, 0, 0));
    		cxChar = LOWORD(GetDialogBaseUnits());
    		cyChar = HIWORD(GetDialogBaseUnits());
    
    		hwndHauptFenster = hwnd;
    
    		hwndEditZeit    = CreateWindow(TEXT("edit"), NULL,
    						WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_WANTRETURN,
    						0, 0, 0, 0, //Wird bei WM_SIZE verändert
    						hwnd, (HMENU) ID_EDIT_ZEIT,
    						(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    						NULL);
    		PrevWndProcEditZeit = SetWindowLongPtr(hwndEditZeit, GWLP_WNDPROC, (LONG_PTR) ChildWndProcEditZeit);
    		SetFocus(hwndEditZeit);
    
    		hwndButtonWand  = CreateWindow(TEXT("button"), NULL,
    						WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
    						0, 0, 0, 0, //Wird bei WM_SIZE verändert
    						hwnd, (HMENU) ID_BUTTON_WAND,
    						(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    						NULL);
    
    		hwndEditVerlaengerung = CreateWindow(TEXT("edit"), NULL,
    						WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_WANTRETURN,
    						0, 0, 0, 0, //Wird bei WM_SIZE verändert
    						hwnd, (HMENU) ID_EDIT_VERLAENGERN,
    						(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    						NULL);
    
    		PrevWndProcEditVerlaengerung = SetWindowLongPtr(hwndEditVerlaengerung, GWLP_WNDPROC, (LONG_PTR) ChildWndProcEditZeit);
    
    		hwndButtonStart = CreateWindow(TEXT("button"), "Start",
    						WS_CHILD | WS_VISIBLE | BS_CENTER,
    						0, 0, 0, 0,//Wird bei WM_SIZE verändert
    						//cxClient / 4 - cxChar * 10, cyChar * 2,
    						//cxChar * 20,
    						//cyChar * 3,
    						hwnd, (HMENU) ID_BUTTON_START,
    						(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    						NULL);
    
    		hwndButtonPause = CreateWindow(TEXT("button"), "Pause",
    						WS_CHILD | WS_VISIBLE | BS_CENTER,
    						0, 0, 0, 0,//Wird bei WM_SIZE verändert
    						//cxClient / 2 - cxChar * 10, cyChar * 2,
    						//cxChar * 20,
    						//cyChar * 3,
    						hwnd, (HMENU) ID_BUTTON_PAUSE,
    						(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    						NULL);
    
    		EnableWindow(hwndButtonPause, FALSE);
    
    		hwndButtonEnde = CreateWindow(TEXT("button"), "Stop",
    						WS_CHILD | WS_VISIBLE | BS_CENTER,
    						0, 0, 0, 0,//Wird bei WM_SIZE verändert
    						//cxClient * 3 /4 - cxChar * 10, cyChar * 2,
    						//cxChar * 20,
    						//cyChar * 3,
    						hwnd, (HMENU) ID_BUTTON_ENDE,
    						(HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE),
    						NULL);
    
    		EnableWindow(hwndButtonEnde, FALSE);
    
    		return 0;
    
    	case WM_KEYDOWN:
    		if(befehl == 0) //Wurde letzte Richtungsangabe schon verarbeitet?
    		{
    			switch(wParam)
    			{
    			case VK_LEFT:
    				if(iPosition[0][2] != RT_RECHTS)
    				{
    					iPosition[0][2] = RT_LINKS;
    					befehl = 1; 									
    				}
    				break;
    
    			case VK_UP:
    				if(iPosition[0][2] != RT_RUNTER)
    				{
    					iPosition[0][2] = RT_HOCH;
    					befehl = 1;
    				}
    				break;
    
    			case VK_RIGHT:
    				if(iPosition[0][2] != RT_LINKS)
    				{
    					iPosition[0][2] = RT_RECHTS;
    					befehl = 1;
    				}
    				break;
    
    			case VK_DOWN:
    				if(iPosition[0][2] != RT_HOCH)
    				{
    					iPosition[0][2] = RT_RUNTER;
    					befehl = 1;
    				}
    				break;
    			}
    		}
    
    	case WM_COMMAND:
    		if(HIWORD(wParam) == BN_CLICKED)
    		{
    			switch(LOWORD(wParam))
    			{
    			case ID_BUTTON_START:
    				//////////////////////////////
    				//Zeitabstände für Timer abfragen aus Edit
    				GetWindowText(hwndEditZeit, cBuffer, 19);
    				if(cBuffer[0] == '\0')
    				{
    					MessageBox(hwnd, "Bitte eine Zeit angeben!", "Fehler", MB_OK | MB_ICONINFORMATION);
    					SetFocus(hwndEditZeit);
    					return 0;
    				}
    				sscanf(cBuffer, "%d", &iZeit);
    
    				if(iZeit > 0)
    					SetTimer(hwnd, Timer_ID, iZeit, 0);
    				else
    				{
    					MessageBox(hwnd, "Zeiteingabe zu klein!", "Fehler", MB_OK | MB_ICONINFORMATION);
    					SetFocus(hwndEditZeit);
    					return 0;
    				}
    				//////////////////////////////////////
    				//Wert, um den die Schlange wachsen soll aus Edit abfragen
    				GetWindowText(hwndEditVerlaengerung, cBuffer, 19);
    				if(cBuffer[0] == '\0')
    				{
    					MessageBox(hwnd, "Bitte einen Wert eingeben!", "Fehler", MB_OK | MB_ICONINFORMATION);
    					SetFocus(hwndEditVerlaengerung);
    					return 0;
    				}
    				sscanf(cBuffer, "%d", &iVerlaengerung);
    
    				if(iVerlaengerung < 0 || iVerlaengerung > 100)
    				{
    					MessageBox(hwnd, "Die Zahl sollte >0 und <100 sein!", "Fehler", MB_OK | MB_ICONINFORMATION);
    					SetFocus(hwndEditVerlaengerung);
    					return 0;
    				}
    				///////////////////////////////////////////////
    				Init_Schlange(20); //Anfangslänge der Schlange
    				aktiv = 1;
    				bPause = FALSE;
    				SetFocus(hwnd);
    
    				SysMenu = GetSystemMenu(hwnd, 0);
    				if(!SysMenu) return 0;
    				RemoveMenu(SysMenu, SC_SIZE, MF_BYCOMMAND);
    
    				EnableWindow(hwndButtonStart, FALSE);
    				EnableWindow(hwndButtonPause, TRUE);
    				EnableWindow(hwndButtonEnde, TRUE);
    				EnableWindow(hwndButtonWand, FALSE);
    				EnableWindow(hwndEditZeit, FALSE);
    				EnableWindow(hwndEditVerlaengerung, FALSE);
    				return 0;
    
    			case ID_BUTTON_ENDE:
    				KillTimer(hwnd, Timer_ID);
    				aktiv = 0;
    				iPunkte = 0;
    				AppendMenu(SysMenu, MF_MENUBREAK, SC_SIZE, NULL); //SC_SIZE wieder in Menü einfügen
    
    				InvalidateRect(hwnd, NULL, TRUE);
    				EnableWindow(hwndButtonStart, TRUE);
    				EnableWindow(hwndButtonPause, FALSE);
    				EnableWindow(hwndButtonEnde, FALSE);
    				EnableWindow(hwndButtonWand, TRUE);
    				EnableWindow(hwndEditZeit, TRUE);
    				EnableWindow(hwndEditVerlaengerung, TRUE);
    				return 0;
    			case ID_BUTTON_PAUSE:
    				if(bPause == TRUE)
    				{
    					//////////////////////////////
    					//Zeitabstände für Timer abfragen aus Edit
    					GetWindowText(hwndEditZeit, cBuffer, 19);
    					if(cBuffer[0] == '\0')
    					{
    						MessageBox(hwnd, "Bitte eine Zeit angeben!", "Fehler", MB_OK | MB_ICONINFORMATION);
    						SetFocus(hwndEditZeit);
    						return 0;
    					}
    					sscanf(cBuffer, "%d", &iZeit);
    
    					if(iZeit > 0)
    						SetTimer(hwnd, Timer_ID, iZeit, 0);
    					else
    					{
    						MessageBox(hwnd, "Zeiteingabe zu klein!", "Fehler", MB_OK | MB_ICONINFORMATION);
    						SetFocus(hwndEditZeit);
    						return 0;
    					}
    					//////////////////////////////////////
    					//Wert, um den die Schlange wachsen soll aus Edit abfragen
    					GetWindowText(hwndEditVerlaengerung, cBuffer, 19);
    					if(cBuffer[0] == '\0')
    					{
    						MessageBox(hwnd, "Bitte einen Wert eingeben!", "Fehler", MB_OK | MB_ICONINFORMATION);
    						SetFocus(hwndEditVerlaengerung);
    						return 0;
    					}
    					sscanf(cBuffer, "%d", &iVerlaengerung);
    
    					if(iVerlaengerung < 0 || iVerlaengerung > 100)
    					{
    						MessageBox(hwnd, "Die Zahl sollte >0 und <100 sein!", "Fehler", MB_OK | MB_ICONINFORMATION);
    						SetFocus(hwndEditVerlaengerung);
    						return 0;
    					}
    					///////////////////////////////////////////
    					SetTimer(hwnd, Timer_ID, iZeit, 0);
    					bPause = FALSE;
    
    					//Wird bei Start in Init_Schlage() gesetzt
    					iPproPunkt = ((iVerlaengerung * 100) / iZeit) / ((xFelder * yFelder) / 100);//muss noch verbessert werden
    					if(iPproPunkt < 1) iPproPunkt = 1;
    
    					InvalidateRect(hwnd, NULL, TRUE);
    					SetFocus(hwnd);
    					EnableWindow(hwndButtonWand, FALSE);
    					EnableWindow(hwndEditZeit, FALSE);
    					EnableWindow(hwndEditVerlaengerung, FALSE);
    				}
    				else
    				{
    					KillTimer(hwnd, Timer_ID);
    					bPause = TRUE;
    					EnableWindow(hwndButtonWand, TRUE);
    					EnableWindow(hwndEditZeit, TRUE);
    					EnableWindow(hwndEditVerlaengerung, TRUE);
    
    				}
    				return 0;
    
    			}
    		}
    		return 0;
    
    	case WM_TIMER:
    		befehl = 0; 
    
    		if(iPunkt[2] == 0)//Fresspunkt erstellen
    		{
    			iPunkt[0] = rand() % xFelder;
    			iPunkt[1] = rand() % yFelder;
    			iPunkt[2] = 1;
    
    			for(i = 0; i <=iSchlLaenge + 1; i++)//Zusammenstoß mit Schlange verhindern
    				if(iPosition[i][0] == iPunkt[0] && iPosition[i][1] == iPunkt[1] && iPosition[i][2] != 0)
    				{
    					i = 0;
    					iPunkt[0] = rand() % xFelder;
    					iPunkt[1] = rand() % yFelder;
    				}
    		}
    
    		for(i = iSchlLaenge; i > 0; i--) //Nachrutschen der Schlangenteile
    		{
    			iPosition[i][0] = iPosition[i - 1][0];
    			iPosition[i][1] = iPosition[i - 1][1];
    			iPosition[i][2] = iPosition[i - 1][2];
    		}
    
    		switch(iPosition[0][2])
    		{
    		case RT_HOCH:
    
    			if(SendMessage(hwndButtonWand, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
    			{
    				if((iPosition[0][1] - 1) <= 0) //Außenbegrenzung oben
    				{
    					KillTimer(hwnd, Timer_ID);
    					MessageBox(hwnd, "Ende", "Ende", MB_OK);
    					EnableWindow(hwndButtonStart, TRUE);
    					EnableWindow(hwndButtonPause, FALSE);
    					EnableWindow(hwndButtonEnde, FALSE);
    					EnableWindow(hwndButtonWand, TRUE);
    					EnableWindow(hwndEditZeit, TRUE);
    					EnableWindow(hwndEditVerlaengerung, TRUE);
    					AppendMenu(SysMenu, MF_MENUBREAK, SC_SIZE, NULL); //SC_SIZE wieder in Menü einfügen
    					aktiv = 0;
    					return 0;
    				}
    				iPosition[0][1] -= 1; //Neue Position des Schlangenkopfs
    
    			}
    			else
    			{
    				if((iPosition[0][1] - 1) <= 0)
    					iPosition[0][1] = yFelder;
    				else
    					iPosition[0][1] -= 1;
    			}
    
    			if(iPrevRichtung != RT_HOCH)
    				if(iPrevRichtung == RT_LINKS)
    					iPosition[1][2] = BG_RECHTS;
    				else
    					iPosition[1][2] = BG_HOCH;
    			else
    				iPosition[1][2] = SENKRECHT;
    			iPrevRichtung = RT_HOCH;
    			break;
    
    		case RT_RECHTS:
    			if(SendMessage(hwndButtonWand, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
    			{
    				if((iPosition[0][0] + 1) > xFelder)//Außenbegrenzung rechts
    				{
    					KillTimer(hwnd, Timer_ID);
    					MessageBox(hwnd, "Ende", "Ende", MB_OK);
    					EnableWindow(hwndButtonStart, TRUE);
    					EnableWindow(hwndButtonPause, FALSE);
    					EnableWindow(hwndButtonEnde, FALSE);
    					EnableWindow(hwndButtonWand, TRUE);
    					EnableWindow(hwndEditZeit, TRUE);
    					EnableWindow(hwndEditVerlaengerung, TRUE);
    					AppendMenu(SysMenu, MF_MENUBREAK, SC_SIZE, NULL); //SC_SIZE wieder in Menü einfügen
    					aktiv = 0;
    					return 0;
    				}
    				iPosition[0][0] += 1; //Neue Position des Schlangenkopfs
    			}
    			else
    			{
    				if((iPosition[0][0] + 1) > xFelder)
    					iPosition[0][0] = 1;
    				else
    					iPosition[0][0] += 1;
    			}
    			if(iPrevRichtung != RT_RECHTS)
    				if(iPrevRichtung == RT_HOCH)
    					iPosition[1][2] = BG_RUNTER;
    				else
    					iPosition[1][2] = BG_RECHTS;
    			else
    				iPosition[1][2] = WAAGRECHT;
    			iPrevRichtung = RT_RECHTS;
    			break;
    
    		case RT_RUNTER:
    			if(SendMessage(hwndButtonWand, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
    			{
    				if((iPosition[0][1] + 1) > yFelder) //Außenbegenzung unten
    				{
    					KillTimer(hwnd, Timer_ID);
    					MessageBox(hwnd, "Ende", "Ende", MB_OK);
    					EnableWindow(hwndButtonStart, TRUE);
    					EnableWindow(hwndButtonPause, FALSE);
    					EnableWindow(hwndButtonEnde, FALSE);
    					EnableWindow(hwndButtonWand, TRUE);
    					EnableWindow(hwndEditZeit, TRUE);
    					EnableWindow(hwndEditVerlaengerung, TRUE);
    					AppendMenu(SysMenu, MF_MENUBREAK, SC_SIZE, NULL); //SC_SIZE wieder in Menü einfügen
    					aktiv = 0;
    					return 0;
    				}
    				iPosition[0][1] += 1; //Neue Position des Schlangenkopfs
    			}
    			else
    			{
    				if((iPosition[0][1] + 1) > yFelder)
    					iPosition[0][1] = 1;
    				else
    					iPosition[0][1] += 1;
    			}
    			if(iPrevRichtung != RT_RUNTER)
    				if(iPrevRichtung == RT_LINKS)
    					iPosition[1][2] = BG_RUNTER;
    				else
    					iPosition[1][2] = BG_LINKS;
    
    			else
    				iPosition[1][2] = SENKRECHT;
    			iPrevRichtung = RT_RUNTER;
    			break;
    
    		case RT_LINKS:
    			if(SendMessage(hwndButtonWand, BM_GETCHECK, 0, 0) == BST_UNCHECKED)
    			{
    				if((iPosition[0][0] - 1) <= 0) //Außenbegrenzung links
    				{
    					KillTimer(hwnd, Timer_ID);
    					MessageBox(hwnd, "Ende", "Ende", MB_OK);
    					EnableWindow(hwndButtonStart, TRUE);
    					EnableWindow(hwndButtonPause, FALSE);
    					EnableWindow(hwndButtonEnde, FALSE);
    					EnableWindow(hwndButtonWand, TRUE);
    					EnableWindow(hwndEditZeit, TRUE);
    					EnableWindow(hwndEditVerlaengerung, TRUE);
    					AppendMenu(SysMenu, MF_MENUBREAK, SC_SIZE, NULL); //SC_SIZE wieder in Menü einfügen
    					aktiv = 0;
    					return 0;
    				}
    				iPosition[0][0] -= 1; //Neue Position des Schlangenkopfs
    			}
    			else
    			{
    				if((iPosition[0][0] - 1) <= 0)
    					iPosition[0][0] = xFelder;
    				else
    					iPosition[0][0] -= 1;
    			}
    			if(iPrevRichtung != RT_LINKS)
    				if(iPrevRichtung == RT_HOCH)
    					iPosition[1][2] = BG_LINKS;
    				else
    					iPosition[1][2] = BG_HOCH;
    
    			else
    				iPosition[1][2] = WAAGRECHT;
    			iPrevRichtung = RT_LINKS;
    			break;
    		}
    		for(i = 1; i <=iSchlLaenge + 1; i++) //Damit sich Schlange nicht selbst beist
    			if(iPosition[i][0] == iPosition[0][0] && iPosition[i][1] == iPosition[0][1] && iPosition[i][2] != 0)
    			{
    				KillTimer(hwnd, Timer_ID);
    				MessageBox(hwnd, TEXT("Ende"), TEXT("Ende"), MB_OK);
    				EnableWindow(hwndButtonStart, TRUE);
    				EnableWindow(hwndButtonPause, FALSE);
    				EnableWindow(hwndButtonEnde, FALSE);
    				EnableWindow(hwndButtonWand, TRUE);
    				EnableWindow(hwndEditZeit, TRUE);
    				EnableWindow(hwndEditVerlaengerung, TRUE);
    				AppendMenu(SysMenu, MF_MENUBREAK, SC_SIZE, NULL); //SC_SIZE wieder in Menü einfügen
    				aktiv = 0;
    				return 0;
    			}
    
    		if(iPunkt[0] == iPosition[0][0] && iPunkt[1] == iPosition[0][1]) //Schlange wird länger
    		{
    			iPunkt[2] = 0; //Punkt wird nicht mehr angezeigt, da gefressen
    			iSchlLaenge += iVerlaengerung; //Wert um den die Schlange länger wird
    			iPunkte += iPproPunkt;
    			InvalidateRect(hwnd, NULL, TRUE);
    
    		}
    		else 		
    			InvalidateRect(hwnd, &rectUpdate, TRUE);
    
    		return 0;
    
    	case WM_DESTROY:
    		DeleteObject(hBrush);
    		PostQuitMessage(0);
    		return 0;
    	}
    
    	return DefWindowProc(hwnd, message, wParam, lParam);
    }
    
    int Init_Schlange(int anzahl) //anzahl = Länge der Schlange am Anfang
    {
    	int i;
    	iPunkt[0] = iPunkt[1] = iPunkt[2] = 0; //Kein Punkt zum auffressen 0 = xKoordinaten, 1 = yKo., 2 = status
    	iPrevRichtung = RT_HOCH; //Anfangsrichtung
    	befehl = 0; //Keine Eingabe vorhanden
    	iSchlLaenge = anzahl; //Anfangs-Schlangenlänge auf 20 setzten
    	iPunkte = 0; //Startpunktzahl festlegen
    
    	iPproPunkt = ((iVerlaengerung * 100) / iZeit) / ((xFelder * yFelder) / 100);//muss noch verbessert werden
    	if(iPproPunkt < 1) iPproPunkt = 1;
    
    	for(i = 0; i < MAX - 1; i++)
    		iPosition[i][0] = iPosition[i][1] = iPosition[i][2] = 0;
    
    	//Startwerte festlegen, Schlange steht Senkrecht, Kopf ist oben
    	//Kopf
    	iPosition[0][0] = xFelder / 2;
    	iPosition[0][1] = yFelder / 2;
    	iPosition[0][2] = RT_HOCH; //Richtung nächstes Feld
    	//Rest der Schlange
    	for(i = 1; i < anzahl + 1; i++)
    	{
    		iPosition[i][0] = xFelder / 2;
    		iPosition[i][1] = yFelder / 2 + i;
    		iPosition[i][2] = SENKRECHT; //Ausrichtung des Schlangteils
    	}
    
    	InvalidateRect(hwndHauptFenster, NULL, TRUE);
    	return 1;
    }
    
    LRESULT CALLBACK ChildWndProcEditZeit(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    {
    	HWND hhwnd;
    	hhwnd = GetFocus();
    
    	switch(message)
    	{
    	case WM_KEYDOWN:
    		switch(wParam)
    		{
    		case VK_TAB:
    			if(hhwnd == hwndEditZeit)
    			{
    				SetFocus(hwndEditVerlaengerung);
    				SetWindowText(hwndEditVerlaengerung, TEXT(""));
    				return 0;
    			}
    			if(hhwnd == hwndEditVerlaengerung)
    			{
    				SetFocus(hwndEditZeit);
    				SetWindowText(hwndEditZeit, TEXT(""));
    				return 0;
    			}
    			break;
    		}
    	}
    	if(hwnd == hwndEditZeit)
    		return CallWindowProc((WNDPROC) PrevWndProcEditZeit, hwnd, message, wParam, lParam);
    	if(hwnd == hwndEditVerlaengerung)
    		return CallWindowProc((WNDPROC) PrevWndProcEditVerlaengerung, hwnd, message, wParam, lParam);
    }
    


  • Also ich habe mir das jetzt nicht ganz durchgelesen, aber ich glaube das wird sich auch niemand antun. Naja, ich habs mal in den Compiler geschmissen und geguckt was passiert. Du scheinst Compiler-Warnungs resistent zu sein? Denn bevor das Ganze überhaupt lief, musste ich erstmal zwei Casts einfügen und eine Funktion vorwärtsdeklarieren..

    Auch danach fallen dem Compiler(!) noch Sachen auf:

    (105): warning C4101: 'hPen1': Unreferenzierte lokale Variable
    (104): warning C4101: 'hRgnTemp': Unreferenzierte lokale Variable
    (779): warning C4715: "ChildWndProcEditZeit": Nicht alle Steuerelementpfade geben einen Wert zurück.

    Und warum nimmt man sscanf() für eine String->Int konvertierung??^^

    Zu deutschen Variablennamen sage ich jetzt einfach mal nichts..

    Was noch auffällt, sind endlose Code-Wiederholungen.
    Ich habe vor etwas längerer Zeit man etwas vergleichbares geschrieben, nur hat das auf ca. 200 Zeilen gepasst. Und ich achte noch darauf 80 Zeichen in einer Zeile nicht zu überschreiten 😉
    Das Ganze "EnableWindow" Zeug kann man doch in eine kleine Funktion packen, damit wären wahrscheinlich schon mal 100 Zeilen weg.

    Zudem finde ich das mit dem "befehl" bei der Eingabeverarbeitung unglücklich gelöst, es sollte doch immer die letzte Eingabe vor der "Runde" zählen. Besser wäre eine Art "direction" und "cur_direction". Damit kann man immer korrekt vergleichen, und trotzdem zählt die letzte Eingabe. (Bei jeder Runde wird cur_direction dann zu direction).

    #define MAX 4000
    Ist auch wieder mal ein gutes Beispiel für eine viel zu kurze, nichtssagende Konstanten.
    Rückgabewert von RegisterClass wird nicht geprüft.
    Rückgabewert von CreateWindow wird nicht nie geprüft.

    Die Buttons/Editfelder/etc. sind bei mir im übrigen alle übereinander, war gar nicht so einfach das Spiel überhaupt zu starten 😃

    Als generellen Tipp kann ich dir vielleicht mitgeben dass Du wirklich versuchen solltest gleichen oder ähnlichen Code irgendwie in Funktionen zu packen damit das ganze übersichtlicher wird. Sich wiederholender Code sollte möglichst vermieden werden, dafür gibts schießlich Funktionen.

    So, das wars was mir bei kurzen überfliegen aufgefallen ist, ich hoffe ich habe nicht zu viel kritisiert, keine sorge, man kann sich natürlich noch verbessern 😉

    PS:
    Zudem gehören "Code-Reviews" etc. wohl eher ins Projekte Forum.



  • erstmal thx für deinen (den einzigen 😉 ) beitrag,

    ich hoffe ich habe nicht zu viel kritisiert

    das war ja der Sinn der Sache 😉 , je mehr desto besser

    zu

    Du scheinst Compiler-Warnungs resistent zu sein?

    auf die Warnungen hab ich echt nicht geachtet

    und

    Denn bevor das Ganze überhaupt lief, musste ich erstmal zwei Casts einfügen und eine Funktion vorwärtsdeklarieren..

    also bei mir läuft das ohne Probleme und die Buttons sind auch nebeneinander. wo musstest du denn was einfügen?

    was wäre denn eine alternative zu sscanf, in den Beispielen mit denen ich c-gelernt hab, wurde das immer benutzt



  • Nutzt Du den GCC Compiler? Dann compiler mal mit -Wall (hoffe ich erinnere mich da richtig) und geh ALLE Warnungen durch und versuche nachzuvollziehen warum diese ausgegeben werden.

    Alternative zu sscanf wäre atoi 😉



  • Nein, ich nutze VS2010. Ich hab meinen Code jetzt verbessert und fast alle warnungen weg. Ich bekomm noch für die Zeile

    PrevWndProcEditZeit = SetWindowLong(hwndEditZeit, GWLP_WNDPROC,  (LONG_PTR) ChildWndProcEditZeit);
    

    die meldung

    warning C4047: '=': Anzahl der Dereferenzierungen bei 'HWND' und 'LONG' unterschiedlich

    was stimmt da nicht?
    Außdem schmiert das Programm irgendwann ab, wenn die Schlange immer länger wird. Zuerst werden die Punkte nicht mehr gefüllt (sonst läuft alles weiter) bis ich irgendwo anstoß. Dann geht gar nichts mehr. Könnte das an den vielen Teilen sein die pro Schritt immer wieder gezeichnet werden?



  • Der Returnwert von SetWindowLong muss ebenfalls gecastet werden. Besser wäre es auch, gleich SetWindowLongPtr zu verwenden.

    Außerdem:

    SelectObject(hdc, CreateSolidBrush(RGB(0, 0, 0)));
    

    Bei jedem Neuzeichnen des Fensters wird ein neuer Brush erstellt, der nicht wieder freigegeben wird. Irgendwann ist die maximale Anzahl an GDI-Handles erreicht und es passiert, wie beschrieben, nichts mehr.
    Einen schwarzen Brush braucht man auch nicht selber erstellen, GetStockObject (BLACK_BRUSH) liefert so einen (auch hier ist ein Cast nötig).



  • Dieser Thread wurde von Moderator/in Martin Richter aus dem Forum WinAPI in das Forum Projekte verschoben.

    Im Zweifelsfall bitte auch folgende Hinweise beachten:
    C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?

    Dieses Posting wurde automatisch erzeugt.



  • neo47 schrieb:

    Könnte das an den vielen Teilen sein die pro Schritt immer wieder gezeichnet werden?

    Im übrigen musst Du eigentlich immer nur den Kopf und das letzte Teil neu zeichnen..



  • Snake ist eine Schlange, die gefährlich beissen kann. Dein Code wohl auch. Also, was willst du machen? 😕



  • @_FALKE: thx, alle warnungen weg und der Fehler taucht auch nicht mehr auf.

    @coody451: Ja, sowas hatte ich im Kopf, werd das gleich mal so machen.


Anmelden zum Antworten