(转载请注明出处,菜鸟之处还望拍砖)
思路
-----------------------------------------------------------------------
两个指针(概念上的指针,不是int *p那个),一个指头一个指向尾巴。
用类似队列的方法,身体上每一块都标名其更前(靠进头部为前)一块的相对位置。比如, 身体上有一块被标识为“2”表示比他更靠前的一块的位置在其上方,以此类推。
——二维队列(O(∩_∩)O 自创名词。。)
头指针移动:
POINT head;
movehead(int 方向 )
{
//生成身体块
map[head.x][head.y]=方向;
//头指针迁移
head.x 更新(根据方向)
head.y 更新(根据方向)
}
尾指针移动:
POINT rear;
moverear(int 方向 )
{
//清楚身体块
map[head.x][head.y]=0;
//尾指针迁移
rear.x 更新(根据方向)
rear.y 更新(根据方向)
}
然后实现起来就很简单了。
移动:
执行movehead(int 方向 )和moverear(int 方向 )。
吃食物:
只执行movehead(int 方向 )。
GAME OVER:
经过判断头指针更新不能(撞墙、撞身体)。
代码基本实现后,数组MAP实时实值打印效果图:
收获
-----------------------------------------------------------------------
1.解决思考多年问题。。多线程才是王道。。
2.从DOS向窗口进步。。图形太2。。不过大体明白。。可备开始图形学。。FOR PLAY
3.足够多文件多函数,函数尽量简单。。。思路更适合我这种低智商人群。。。
4.蓄谋已久,构思(偶尔)1月,资料2天,程序3天,每天2-3小时。。
5.特此记录。。。。
6.的确老了。。。。
7.很少算法。。。。
8.多线程貌似没有KILL。。。太基础。。。太低级。
9.句柄调用。。int tmp_hwnd=(int)hwnd;。。function((HWND)tmp_hwnd);。。这样也可以。。
代码(Buliding by C-free)
---------------------------------DOS------------------------------
#include <windows.h>
#include <time.h>
int map[32][22],direction;
POINT head,rear;
//map[i][j]= 0 1 2 3 4 5 6 7
// 空 墙 上 下 左 右 食 头
int init()
{
int i,j;
for (i=0;i<32;i++)
for (j=0;j<22;j++)
{
if ((0==i) || (31==i) || (0==j) || (21==j))
{
map[i][j]=1;
} else {
map[i][j]=0;
}
}
map[23][14]=6;
map[15][23]=6;
//初始化蛇
map[1][1]=5;
rear.x=1;
rear.y=1;
map[2][1]=5;
map[3][1]=7;
head.x=3;
head.y=1;
}
int feed()
{
int i,j;
srand( (unsigned)time( NULL) );
do {
i=rand()%30+1;
j=rand()%20+1;
}while (0!=map[i][j]);
map[i][j]=6;
}
int over()
{
system("cls");
printf("/n/n/n/n/n/n/t/t/tGAME OVER/n");
getch();
exit(0);
}
int cango(int direction)
//0:dead. 1:can go. 2:can eat. 3:can't go.
{
switch(direction)
{
case 1: //上
if (3==map[head.x][head.y-1])
{
return 3;//判断"往下走的过程按上"的情况
}
if ((0==map[head.x][head.y-1])||(6==map[head.x][head.y-1]))
{
if (6==map[head.x][head.y-1])
{
return 2;
}
return 1;
}else{
return 0;
}
break;
case 2: //下
if (2==map[head.x][head.y+1])
{
return 3;
}
if ((0==map[head.x][head.y+1])||(6==map[head.x][head.y+1]))
{
if (6==map[head.x][head.y+1])
{
return 2;
}
return 1;
}else{
return 0;
}
break;
case 3: //左
if (5==map[head.x-1][head.y])
{
return 3;
}
if ((0==map[head.x-1][head.y])||(6==map[head.x-1][head.y]))
{
if (6==map[head.x-1][head.y])
{
return 2;
}
return 1;
}else {
return 0;
}
break;
case 4: //右
if (4==map[head.x+1][head.y])
{
return 3;
}
if ((0==map[head.x+1][head.y])||(6==map[head.x+1][head.y]))
{
if (6==map[head.x+1][head.y])
{
return 2;
}
return 1;
}else {
return 0;
}
break;
}
}
int movehead(int direction)
{
switch(direction)
{
case 1: //上
map[head.x][head.y]=2;
head.y--;
map[head.x][head.y]=7;
break;
case 2: //下
map[head.x][head.y]=3;
head.y++;
map[head.x][head.y]=7;
break;
case 3: //左
map[head.x][head.y]=4;
head.x--;
map[head.x][head.y]=7;
break;
case 4: //右
map[head.x][head.y]=5;
head.x++;
map[head.x][head.y]=7;
break;
}
}
int moverear()
{
switch(map[rear.x][rear.y])
{
case 2: //上
map[rear.x][rear.y]=0;
rear.y--;
break;
case 3: //下
map[rear.x][rear.y]=0;
rear.y++;
break;
case 4: //左
map[rear.x][rear.y]=0;
rear.x--;
break;
case 5: //右
map[rear.x][rear.y]=0;
rear.x++;
break;
}
}
int move(int direction)
//direction= 1 2 3 4
// 上下左右
{
switch(cango(direction))
{
case 1:
movehead(direction);
moverear();
break;
case 2:
movehead(direction);
feed();
break;
case 0:
over();
break;
default:
break;
}
}
long WINAPI Thread( LPVOID pParam )
{
int i,j;
while(1)
{
Sleep(100);
move(direction);
system("cls");
printf("--------------/n");
for (j=0;j<22;j++)
{
for (i=0;i<32;i++)
{
if (map[i][j]==0)
printf(" ");
else
printf("%2d",map[i][j]);
}
printf("|/n");
}
printf("--------------");
}
return 1;
}
int main()
{
init();
direction=0;
char ch;
unsigned long * p=NULL;
CreateThread(0,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,p);
while (1)
{
ch=getch();
switch(ch)
{
case 'w':
direction=1;
break;
case 's':
direction=2;
break;
case 'a':
direction=3;
break;
case 'd':
direction=4;
break;
}
}
}
--------------------------------------windows-----------------------------
-----main.c----
#include <windows.h>
extern score,speed;
/* Declare Windows procedure */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
/* Make the class name into a global variable */
char szClassName[ ] = "WindowsApp";
int direction=100;//控制方向的量
int tmp_hwnd=0;//临时存储窗口句柄
int WINAPI
WinMain (HINSTANCE hThisInstance,
HINSTANCE hPrevInstance,
LPSTR lpszArgument,
int nFunsterStil)
{
HWND hwnd; /* This is the handle for our window */
MSG messages; /* Here messages to the application are saved */
WNDCLASSEX wincl; /* Data structure for the windowclass */
/* The Window structure */
wincl.hInstance = hThisInstance;
wincl.lpszClassName = szClassName;
wincl.lpfnWndProc = WindowProcedure; /* This function is called by windows */
wincl.style = CS_DBLCLKS; /* Catch double-clicks */
wincl.cbSize = sizeof (WNDCLASSEX);
/* Use default icon and mouse-pointer */
wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
wincl.lpszMenuName = NULL; /* No menu */
wincl.cbClsExtra = 0; /* No extra bytes after the window class */
wincl.cbWndExtra = 0; /* structure or the window instance */
/* Use Windows's default color as the background of the window */
wincl.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
/* Register the window class, and if it fails quit the program */
if (!RegisterClassEx (&wincl))
return 0;
/* The class is registered, let's create the program*/
hwnd = CreateWindowEx (
0, /* Extended possibilites for variation */
szClassName, /* Classname */
"pictcs", /* Title Text */
WS_OVERLAPPEDWINDOW, /* default window */
CW_USEDEFAULT, /* Windows decides the position */
CW_USEDEFAULT, /* where the window ends up on the screen */
710, /* The programs width */
580, /* and height in pixels */
HWND_DESKTOP, /* The window is a child-window to desktop */
NULL, /* No menu */
hThisInstance, /* Program Instance handler */
NULL /* No Window Creation data */
);
/* Make the window visible on the screen */
ShowWindow (hwnd, nFunsterStil);
/* Run the message loop. It will run until GetMessage() returns 0 */
while (GetMessage (&messages, NULL, 0, 0))
{
/* Translate virtual-key messages into character messages */
TranslateMessage(&messages);
/* Send message to WindowProcedure */
DispatchMessage(&messages);
}
/* The program return-value is 0 - The value that PostQuitMessage() gave */
return messages.wParam;
}
long WINAPI Thread( LPVOID pParam )
{
SYSTEMTIME nowtime;
int tmp_time;
int timedelay;
while(0!=tmp_hwnd)//取句柄。。若临时句柄被复制工作
{
switch(speed)
{
case 10:timedelay= 50;break;
case 9:timedelay= 100;break;
case 8:timedelay= 150;break;
case 7:timedelay= 200;break;
case 6:timedelay= 300;break;
case 5:timedelay= 400;break;
case 4:timedelay= 500;break;
case 3:timedelay= 600;break;
case 2:timedelay= 800;break;
case 1:timedelay= 1000;break;
default:timedelay=50 ;break;
}
Sleep(timedelay);
tmp_time=nowtime.wSecond ;
draw_text((HWND)tmp_hwnd,score,speed);
move((HWND)tmp_hwnd,direction);
}
return 1;
}
/* This function is called by the Windows function DispatchMessage() */
LRESULT CALLBACK
WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
RECT rt;
switch (message) /* handle the messages */
{
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
/* TODO: Add any drawing code here... */
Rectangle (hdc,10,10,690,540);
Rectangle (hdc,40,40,660,510);
Rectangle (hdc,50,50,650,95);
Rectangle (hdc,50,100,650,500);
EndPaint(hwnd, &ps);
drawmap(hwnd);
if (0==tmp_hwnd)//若已有线程 则不再重新开
{
init(hwnd);
tmp_hwnd=(int)hwnd;//存临时句柄 以便线程寻找
unsigned long * p=NULL;
CreateThread(0,0,(LPTHREAD_START_ROUTINE)Thread,NULL,0,p);
}
// test(hwnd);
break;
case WM_KEYDOWN:
switch(wParam)
{
case VK_UP:
direction=1;
//move(hwnd,1);
break;
case VK_DOWN:
direction=2;
//move(hwnd,2);
break;
case VK_LEFT:
direction=3;
//move(hwnd,3);
break;
case VK_RIGHT:
direction=4;
//move(hwnd,4);
break;
case VK_SPACE:
init(hwnd);
break;
}
break;
case WM_DESTROY:
PostQuitMessage (0); /* send a WM_QUIT to the message queue */
break;
default: /* for messages that we don't deal with */
return DefWindowProc (hwnd, message, wParam, lParam);
}
return 0;
}
------draw.c-------
#include<windows.h>
int draw_bodyUP(HWND hwnd,POINT place)
{
HDC hdc;
hdc=GetDC(hwnd);
Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
ReleaseDC(hwnd,hdc);
}
int draw_bodyDOWN(HWND hwnd,POINT place)
{
HDC hdc;
hdc=GetDC(hwnd);
Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
ReleaseDC(hwnd,hdc);
}
int draw_bodyLEFT(HWND hwnd,POINT place)
{
HDC hdc;
hdc=GetDC(hwnd);
Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
ReleaseDC(hwnd,hdc);
}
int draw_bodyRIGHT(HWND hwnd,POINT place)
{
HDC hdc;
hdc=GetDC(hwnd);
Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
ReleaseDC(hwnd,hdc);
}
int draw_head(HWND hwnd,POINT place)
{
HDC hdc;
hdc=GetDC(hwnd);
Rectangle (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
ReleaseDC(hwnd,hdc);
}
int draw_food(HWND hwnd,POINT place)
{
HDC hdc;
hdc=GetDC(hwnd);
Ellipse (hdc,place.x+1,place.y+1,place.x+19,place.y+19);
ReleaseDC(hwnd,hdc);
}
int draw_space(HWND hwnd,POINT place)
{
HDC hdc;
RECT rtc;
hdc=GetDC(hwnd);
rtc.left=place.x+1;
rtc.top=place.y+1;
rtc.right=place.x+19;
rtc.bottom=place.y+19;
FillRect(hdc,&rtc,(HBRUSH)(0));
ReleaseDC(hwnd,hdc);
}
int draw(HWND hwnd,POINT where,int func)
{
POINT place;
place.x=50+(where.x-1)*20;
place.y=100+(where.y-1)*20;
switch(func)
{
case 0://空
draw_space(hwnd,place);
break;
case 7://头 此处为了和MAP数组对应
draw_head(hwnd,place);
break;
case 2://上
draw_bodyUP(hwnd,place);
break;
case 3://下
draw_bodyDOWN(hwnd,place);
break;
case 4://左
draw_bodyLEFT(hwnd,place);
break;
case 5://右
draw_bodyRIGHT(hwnd,place);
break;
case 6://食
draw_food(hwnd,place);
break;
default:
break;
}
}
int draw_text(HWND hwnd,int score,int speed)
{
HDC hdc;
TCHAR out_text[100],*outer;
RECT rt;
rt.left=50;
rt.top=70;
rt.right=650;
rt.bottom=95;
hdc=GetDC(hwnd);
wsprintf(out_text,TEXT("分数:%d 级别:%d RESET:[空格] /0"),
score,speed);
outer=out_text;
DrawText(hdc, outer, strlen(outer)-1, &rt, DT_CENTER);
ReleaseDC(hwnd,hdc);
}
--------brain.c----
#include <windows.h>
int map[32][22],direction,speed=1,score=0,speed_tmp=0;
POINT head,rear;
//map[i][j]= 0 1 2 3 4 5 6 7
// 空 墙 上 下 左 右 食 头
int drawmap(HWND hwnd)
{
POINT here;
for (here.x=1;here.x<=30;here.x++)
{
for (here.y=1;here.y<=20;here.y++)
{
draw(hwnd,here,map[here.x][here.y]);
}
}
}
int init(HWND hwnd)
{
int i,j;
for (i=0;i<32;i++)
for (j=0;j<22;j++)
{
if ((0==i) || (31==i) || (0==j) || (21==j))
{
map[i][j]=1;
} else {
map[i][j]=0;
}
}
map[23][14]=6;
map[15][23]=6;
//初始化蛇
map[1][1]=5;
rear.x=1;
rear.y=1;
map[2][1]=5;
map[3][1]=7;
head.x=3;
head.y=1;
drawmap(hwnd);
}
int feed(HWND hwnd)
{
POINT foods;
srand( (unsigned)time( NULL) );
do {
foods.x=rand()%30+1;
foods.y=rand()%20+1;
}while (0!=map[foods.x][foods.y]);
map[foods.x][foods.y]=6;
draw(hwnd,foods,6);
score++;//计分
speed_tmp++;
if (speed_tmp>=20) {speed_tmp=0;speed++;}
}
int over(HWND hwnd)
{
HDC hdc;
hdc=GetDC(hwnd);
RECT rt;
GetClientRect(hwnd, &rt);
rt.top=300;
DrawText(hdc, TEXT("Game Over!...Over!...ver!...er!...r!...!..."), 43, &rt, DT_CENTER);
ReleaseDC(hwnd,hdc);
}
int cango(int direction)
//0:dead. 1:can go. 2:can eat. 3:can't go.
{
switch(direction)
{
case 1: //上
if (3==map[head.x][head.y-1])
{
return 3;//判断"往下走的过程按上"的情况
}
if ((0==map[head.x][head.y-1])||(6==map[head.x][head.y-1]))
{
if (6==map[head.x][head.y-1])
{
return 2;
}
return 1;
}else{
return 0;
}
break;
case 2: //下
if (2==map[head.x][head.y+1])
{
return 3;
}
if ((0==map[head.x][head.y+1])||(6==map[head.x][head.y+1]))
{
if (6==map[head.x][head.y+1])
{
return 2;
}
return 1;
}else{
return 0;
}
break;
case 3: //左
if (5==map[head.x-1][head.y])
{
return 3;
}
if ((0==map[head.x-1][head.y])||(6==map[head.x-1][head.y]))
{
if (6==map[head.x-1][head.y])
{
return 2;
}
return 1;
}else {
return 0;
}
break;
case 4: //右
if (4==map[head.x+1][head.y])
{
return 3;
}
if ((0==map[head.x+1][head.y])||(6==map[head.x+1][head.y]))
{
if (6==map[head.x+1][head.y])
{
return 2;
}
return 1;
}else {
return 0;
}
break;
}
}
int movehead(HWND hwnd,int direction)
{
switch(direction)
{
case 1: //上
map[head.x][head.y]=2;
draw(hwnd,head,2);
head.y--;
map[head.x][head.y]=7;
draw(hwnd,head,7);
break;
case 2: //下
map[head.x][head.y]=3;
draw(hwnd,head,3);
head.y++;
map[head.x][head.y]=7;
draw(hwnd,head,7);
break;
case 3: //左
map[head.x][head.y]=4;
draw(hwnd,head,4);
head.x--;
map[head.x][head.y]=7;
draw(hwnd,head,7);
break;
case 4: //右
map[head.x][head.y]=5;
draw(hwnd,head,5);
head.x++;
map[head.x][head.y]=7;
draw(hwnd,head,7);
break;
}
}
int moverear(HWND hwnd)
{
switch(map[rear.x][rear.y])
{
case 2: //上
map[rear.x][rear.y]=0;
draw(hwnd,rear,0);
rear.y--;
break;
case 3: //下
map[rear.x][rear.y]=0;
draw(hwnd,rear,0);
rear.y++;
break;
case 4: //左
map[rear.x][rear.y]=0;
draw(hwnd,rear,0);
rear.x--;
break;
case 5: //右
map[rear.x][rear.y]=0;
draw(hwnd,rear,0);
rear.x++;
break;
}
}
int move(HWND hwnd,int direction)
//direction= 1 2 3 4
// 上下左右
{
if (100==direction) return 0;//若还未开始 移动无效
switch(cango(direction))
{
case 1:
movehead(hwnd,direction);
moverear(hwnd);
break;
case 2:
movehead(hwnd,direction);
feed(hwnd);
break;
case 0:
over(hwnd);
break;
default:
break;
}
}
/*int test(hwnd)
{
init(hwnd);
POINT here;
for (here.x=1;here.x<=30;here.x++)
for (here.y=1;here.y<=20;here.y++)
{
draw(hwnd,here,map[here.x][here.y]);
}
Sleep(1000);
feed(hwnd);
Sleep(1000);
feed(hwnd);
Sleep(1000);
feed(hwnd);
Sleep(1000);
feed(hwnd);
Sleep(1000);
move(hwnd,2);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,1);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);Sleep(1000);
move(hwnd,4);
Sleep(1000);
move(hwnd,1);
}*/