win 32プログラミングの食いしん坊蛇(瑕疵あり)
今日はおよそ8時間かけてヘビを食べて、主な時間はやはりどのようにするのがもっと流暢な上に費やして、前の方法は毎回整数の単位を移動して、自分の感じにあまり流暢ではありませんて、だから後で毎回移動する配置に変えてdoubleのタイプになって、しかし潜在的な問題があって、判断は正確ではありませんて、大まかな判断しかありません.私のレベルが足りないのか、しばらくはできないので、指摘してほしいです.
UIと実際のデータを別々に計算する考えがあります.UIのリフレッシュ時間を実際に走る時間の1/5に設定することができますが、まだ問題があります.
総合的に
1)整数を移動するたびに
2)doubleを移動するたびに
3)UI分離
一時的なソースコードを貼って、このバージョンは上で言った第2種で、第1種は流暢度がまだもう少しで使わなくなるところだったためです
UIと実際のデータを別々に計算する考えがあります.UIのリフレッシュ時間を実際に走る時間の1/5に設定することができますが、まだ問題があります.
総合的に
1)整数を移動するたびに
2)doubleを移動するたびに
3)UI分離
一時的なソースコードを貼って、このバージョンは上で言った第2種で、第1種は流暢度がまだもう少しで使わなくなるところだったためです
#pragma once
#include "resource.h"
const int BORDER = 10;
const int SCREEN_WIDTH = 640;
const RECT rc_top = {BORDER,BORDER,SCREEN_WIDTH-BORDER,BORDER+20};
const RECT rc_bottom = {BORDER,BORDER+30,SCREEN_WIDTH-BORDER,SCREEN_WIDTH-BORDER};
const RECT rc_main = {0,0,SCREEN_WIDTH,SCREEN_WIDTH};
int BLOCK_SIZE = 15;
int curX=0,curY=0;
int curDir[4] = {1,0};
int g_blocked[100][100];
int NUM_X = 40;
int NUM_Y = 40;
typedef struct aaa{
double curX;
double curY;
double curDir[2];
struct aaa *pre;
struct aaa *next;
}body;
body *head;
int g_speed = 50;
int g_seed = 1995421;
int SNAKE_STATE = 0;
int SNAKE_SCORE = 0;
int SNAKE_DIFF = 1;
void MoveWindowToCenter(HWND hWnd);
void DrawBackground(HDC hdc);
void DrawBody(HDC hdc);
VOID outPutBoxInt(int num);
VOID outPutBoxString(TCHAR str[1024]);
int CalculatePosition();
void StartTimer(HWND hWnd);
void CALLBACK MoveSnake( HWND hWnd,UINT uMsg,UINT idEvent,DWORD dwTime );
void CALLBACK ShowMove( HWND hWnd,UINT uMsg,UINT idEvent,DWORD dwTime );
int CheckValidate();
void InitGameData();
void DrawBlocked(HDC hdc);
int GenerateFood();
int RandomInt(int _min,int _max);
int CheckForFood(int x,int y);
int GetSnakeLength();
body* GetLast();
void InsertAfterLast(body *newbody);
void SetChildMove();
int SelectDifficulty(int diff);
double GetAbs(double num);
void DrawScore(HDC hdc);
// Snake.cpp : 。
//
#include "stdafx.h"
#include "Snake.h"
#define MAX_LOADSTRING 100
// :
HINSTANCE hInst; //
TCHAR szTitle[MAX_LOADSTRING]; //
TCHAR szWindowClass[MAX_LOADSTRING]; //
// :
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
InitGameData();
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: 。
MSG msg;
HACCEL hAccelTable;
//
LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadString(hInstance, IDC_SNAKE, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// :
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_SNAKE));
// :
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// : MyRegisterClass()
//
// : 。
//
// :
//
//
// Windows 95 “RegisterClassEx”
// Win32 , 。 ,
//
// “ ” 。
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_SNAKE));
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCE(IDC_SNAKE);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassEx(&wcex);
}
//
// : InitInstance(HINSTANCE, int)
//
// :
//
// :
//
// ,
// 。
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
HWND hWnd;
hInst = hInstance; //
hWnd = CreateWindow(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// : WndProc(HWND, UINT, WPARAM, LPARAM)
//
// : 。
//
// WM_COMMAND -
// WM_PAINT -
// WM_DESTROY -
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_CREATE:
MoveWindowToCenter(hWnd);
StartTimer(hWnd);
break;
case WM_KEYDOWN:
switch(wParam)
{
case 'W':
if (head->curDir[1]==0)
{
head->curDir[0] = 0;
head->curDir[1] = -1;
}
break;
case 'A':
if (head->curDir[0]==0)
{
head->curDir[0] = -1;
head->curDir[1] = 0;
}
break;
case 'S':
if (head->curDir[1]==0)
{
head->curDir[0] = 0;
head->curDir[1] = 1;
}
break;
case 'D':
if (head->curDir[0]==0)
{
head->curDir[0] = 1;
head->curDir[1] = 0;
}
break;
}
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// :
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case ID_dif1:
SelectDifficulty(1);
break;
case ID_dif2:
SelectDifficulty(2);
break;
case ID_dif3:
SelectDifficulty(3);
break;
case ID_dif4:
SelectDifficulty(4);
break;
case ID_PAUSE:
SNAKE_STATE = !SNAKE_STATE;
InvalidateRect(hWnd,&rc_top,false);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
DrawBackground(hdc);
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// “ ” 。
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
void MoveWindowToCenter(HWND hWnd)
{
RECT rect;
GetWindowRect(hWnd,&rect);
int posX = GetSystemMetrics(SM_CXSCREEN);
int posY = GetSystemMetrics(SM_CYSCREEN);
posX = (posX - SCREEN_WIDTH)>>1;
posY = (posY - SCREEN_WIDTH-70)>>1;
MoveWindow(hWnd,posX,posY,SCREEN_WIDTH,SCREEN_WIDTH+70,TRUE);
}
void DrawBackground(HDC hdc)
{
HDC mdc = CreateCompatibleDC(hdc);
HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
HBRUSH hWhitebrush = (HBRUSH)GetStockObject(WHITE_BRUSH);
HPEN hPen = (HPEN)CreatePen(PS_DOT,3,RGB(0,255,0));
HBITMAP hBitmap = (HBITMAP)CreateCompatibleBitmap(hdc,SCREEN_WIDTH,SCREEN_WIDTH);
SelectObject(mdc,hBitmap);
SelectObject(mdc,hBrush);
//SelectObject(mdc,hPen);
FillRect(mdc,&rc_main,hWhitebrush);
// Rectangle(mdc,rc_bottom.left,rc_bottom.top,rc_bottom.right,rc_bottom.bottom);
DrawBody(mdc);
DrawBlocked(mdc);
DrawScore(mdc);
::BitBlt(hdc,0,0,SCREEN_WIDTH,SCREEN_WIDTH,mdc,0,0,SRCCOPY);
DeleteDC(mdc);
DeleteObject(hBitmap);
DeleteObject(hPen);
DeleteObject(hBrush);
}
void DrawBody(HDC hdc)
{
HBRUSH hBrush = (HBRUSH)GetStockObject(BLACK_BRUSH);
SelectObject(hdc,hBrush);
if (head==NULL)
{
head->curX = 0;
head->curY = 0;
head->curDir[0] = 1;
head->curDir[1] = 0;
head->next = NULL;
head->pre = NULL;
}
body *temp = head;
//outPutBoxInt(temp->curX);
while(temp!=NULL)
{
Rectangle(hdc,
(temp->curX*BLOCK_SIZE+rc_bottom.left),
temp->curY*BLOCK_SIZE+rc_bottom.top,
((temp->curX+1)*BLOCK_SIZE+rc_bottom.left),
(temp->curY+1)*BLOCK_SIZE+rc_bottom.top);
temp = temp->next;
}
DeleteObject(hBrush);
}
int CalculatePosition()
{
curX += curDir[0];
curY += curDir[1];
if (g_blocked[curY][curX])
{
return -1;
}
return 1;
}
VOID outPutBoxInt(int num)
{
TCHAR szBuf[1024];
LPCTSTR str = TEXT("%d");
wsprintf(szBuf,str,num);
MessageBox(NULL,szBuf,L"Debug",MB_OK);
}
VOID outPutBoxString(TCHAR str[1024])
{
TCHAR szBuf[1024];
LPCTSTR cstr = TEXT("%s");
wsprintf(szBuf,cstr,str);
MessageBox(NULL,szBuf,L"Debug",MB_OK);
}
void DeleteLinkList(body *hl)
{
body *temp = hl;
body *last = GetLast();
while (last!=head)
{
last = last->pre;
delete(last->next);
}
}
void StartTimer(HWND hWnd)
{
SetTimer(hWnd,1001,20,MoveSnake);
//SetTimer(hWnd,1002,20,ShowMove);
GenerateFood();
}
void CALLBACK ShowMove(HWND hWnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
if (SNAKE_STATE)
{
body *temp = head;
SetChildMove();
head->curX += head->curDir[0]/(6-SNAKE_DIFF);
head->curY += head->curDir[1]/(6-SNAKE_DIFF);
}
}
void CALLBACK MoveSnake( HWND hWnd,UINT uMsg,UINT idEvent,DWORD dwTime)
{
if (SNAKE_STATE)
{
body *temp = head;
SetChildMove();
head->curX += head->curDir[0]/(5-SNAKE_DIFF);
head->curY += head->curDir[1]/(5-SNAKE_DIFF);
InvalidateRect(hWnd,&rc_bottom,false);
int flag = CheckValidate();
if (flag==-1)
{
KillTimer(hWnd,1002);
KillTimer(hWnd,1001);
if (MessageBox(hWnd,L" , ",L": ",MB_YESNO)==IDYES)
{
DeleteLinkList(head->next);
InitGameData();
SNAKE_STATE = 1;
StartTimer(hWnd);
InvalidateRect(hWnd,&rc_top,false);
}
else
{
PostQuitMessage(0);
}
}
else if(flag==2)
{
g_blocked[int(head->curY)][int(head->curX)] = 0;
body *newbody = new body;
InsertAfterLast(newbody);
GenerateFood();
SNAKE_SCORE++;
InvalidateRect(hWnd,&rc_top,false);
}
else if(flag==3)
{
g_blocked[int(head->curY)+1][int(head->curX)+1] = 0;
body *newbody = new body;
InsertAfterLast(newbody);
GenerateFood();
}
}
}
int CheckValidate()
{
if (g_blocked[int(head->curY)][int(head->curX)]==1)
{
return -1;
}
else if (g_blocked[int(head->curY)][int(head->curX)]==2)
{
return 2;
}
else if(g_blocked[int(head->curY)+1][int(head->curX)+1]==2)
{
return 3;
}
body *temp = head->next;
while (temp!=NULL)
{
if (GetAbs(temp->curX - head->curX)<0.03 && GetAbs(temp->curY - head->curY)<0.03)
{
return -1;
}
temp = temp->next;
}
return 1;
}
void InitGameData()
{
int i,j;
head = new body;
head->curDir[0] = 1;
head->curDir[1] = 0;
head->curX = 10;
head->curY = 10;
head->next = head->pre = NULL;
memset(g_blocked,0,sizeof(g_blocked));
for (j=0;j<40;j++)
{
g_blocked[0][j] = 1;
g_blocked[1][j] = 1;
g_blocked[38][j] = 1;
g_blocked[39][j] = 1;
}
for (i=1;i<39;i++)
{
g_blocked[i][0] = 1;
g_blocked[i][1] = 1;
g_blocked[i][38] = 1;
g_blocked[i][39] = 1;
}
SNAKE_STATE = 0;
SNAKE_SCORE = 0;
SNAKE_DIFF = 1;
}
void DrawBlocked(HDC hdc)
{
int i,j;
HBRUSH hBrush = (HBRUSH)GetStockObject(GRAY_BRUSH);
HBRUSH hYellowbrush = (HBRUSH)CreateSolidBrush(RGB(255,255,0));
for (i=0;i<NUM_Y;i++)
{
for (j=0;j<NUM_X;j++)
{
if (g_blocked[i][j]==1)
{
SelectObject(hdc,hBrush);
Rectangle(hdc,rc_bottom.left+j*BLOCK_SIZE,rc_bottom.top+i*BLOCK_SIZE,rc_bottom.left+(j+1)*BLOCK_SIZE,rc_bottom.top+(i+1)*BLOCK_SIZE);
}
else if (g_blocked[i][j]==2)
{
SelectObject(hdc,hYellowbrush);
Rectangle(hdc,rc_bottom.left+j*BLOCK_SIZE,rc_bottom.top+i*BLOCK_SIZE,rc_bottom.left+(j+1)*BLOCK_SIZE,rc_bottom.top+(i+1)*BLOCK_SIZE);
}
}
}
DeleteObject(hYellowbrush);
DeleteObject(hBrush);
}
int GenerateFood()
{
int x = RandomInt(0,35*35-GetSnakeLength());
int index = 0;
int i=2,j=2;
while(1)
{
if(j==37)
{
j=2;
i++;
}
else
{
j++;
}
if (CheckForFood(i,j)==1)
{
index++;
if(index>=x)
{
break;
}
}
}
g_blocked[i][j] = 2;
return 1;
}
int RandomInt(int _min,int _max)
{
srand((g_seed++)%65532+GetTickCount());
return _min+rand()%(_max-_min);
}
int CheckForFood(int x,int y)
{
if (g_blocked[y][x])
{
return -1;
}
body *temp = head;
while(temp!=NULL)
{
if (temp->curX==x&&temp->curY==y)
{
return -1;
}
temp = temp->next;
}
return 1;
}
int GetSnakeLength()
{
int count = 0;
body *temp = head;
while(temp!=NULL)
{
count++;
temp = temp->next;
}
return count;
}
void InsertAfterLast(body *newbody)
{
body *temp = head;
temp = temp->next;
// body *last = GetLast();
// last->next = newbody;
// newbody->pre = last;
// newbody->next = NULL;
// newbody->curDir[0] = last->curDir[0];
// newbody->curDir[1] = last->curDir[1];
// newbody->curX = last->curX ;
// newbody->curY = last->curY ;
newbody->pre = NULL;
newbody->next = head;
head->pre = newbody;
newbody->curDir[0] = head->curDir[0];
newbody->curDir[1] = head->curDir[1];
newbody->curX = head->curX+head->curDir[0];
newbody->curY = head->curY+head->curDir[1];
head = newbody;
}
body* GetLast()
{
body *ret;
body *temp = head;
while (temp!=NULL)
{
ret = temp;
temp = temp->next;
}
return ret;
}
void SetChildMove()
{
body *last = GetLast();
while(last!=head)
{
last->curX = last->pre->curX;
last->curY = last->pre->curY;
last = last->pre;
}
}
int SelectDifficulty(int diff)
{
g_speed = 300-diff*60;
InitGameData();
SNAKE_DIFF = diff;
SNAKE_STATE = 1;
HWND hWnd = GetActiveWindow();
StartTimer(hWnd);
InvalidateRect(hWnd,&rc_top,false);
return diff;
}
double GetAbs(double num)
{
return num>0?num:-num;
}
void DrawScore(HDC hdc)
{
HFONT hFont = CreateFont(20,0,0,0,FW_THIN,0,0,0,UNICODE,0,0,0,0,L" ");
SelectObject(hdc,hFont);
SetBkMode(hdc,TRANSPARENT);
SetBkColor(hdc,RGB(255,255,0));
RECT rect;
rect.left = rc_top.left;
rect.top = rc_top.top;
rect.right = rc_top.right/2;
rect.bottom = rc_top.bottom;
TCHAR szBuf[30];
LPCTSTR cstr = TEXT(" :%d");
wsprintf(szBuf,cstr,SNAKE_DIFF);
DrawTextW(hdc,szBuf,_tcslen(szBuf),&rect,DT_CENTER | DT_VCENTER);
RECT rect2;
rect2.left = rc_top.left+100;
rect2.top = rc_top.top;
rect2.right = rc_top.right;
rect2.bottom = rc_top.bottom;
TCHAR szBuf2[30];
LPCTSTR cstr2 = TEXT(" :%d");
wsprintf(szBuf2,cstr2,SNAKE_SCORE);
DrawTextW(hdc,szBuf2,_tcslen(szBuf2),&rect2,DT_CENTER | DT_VCENTER);
DeleteObject(hFont);
}
ご指導と交流を歓迎します