数字雨-贪吃蛇
数字雨
#include "windows.h" #include "stdlib.h" #include "stdio.h" #include "time.h" #include "string.h" #define ID_TIMER 1 #define STRMAXLEN 25 #define STRMINLEN 8 LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM); typedef struct tagCharChain { struct tagCharChain*prev; TCHAR ch; struct tagCharChain*next; }CharChain,*pCharChain; typedef struct tagCharColumn { CharChain *head,*current,*point; int x,y,iStrLen; int iStopTimes,iMustStopTimes; }CharColumn,*pCharColumn; int main(HINSTANCE hInstance, HINSTANCE hPrevInstance,PSTR szCmdLine, int iCmdShow) { static TCHAR szAppName[] = TEXT ("matrix") ; HWND hwnd; MSG msg; WNDCLASS wndclass; wndclass.style = CS_HREDRAW | CS_VREDRAW; wndclass.lpfnWndProc =WndProc; wndclass.cbClsExtra = 0 ; wndclass.cbWndExtra = 0 ; wndclass.hInstance= hInstance ; wndclass.hIcon =LoadIcon(NULL,IDI_APPLICATION); wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ; wndclass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH) ; wndclass.lpszMenuName = NULL ; wndclass.lpszClassName =szAppName; if(!RegisterClass(&wndclass)) { MessageBox (NULL,TEXT ("此程序必须运行在NT下!"),szAppName,MB_ICONERROR); return 0;} hwnd =CreateWindow(szAppName,NULL,WS_DLGFRAME| WS_THICKFRAME|WS_POPUP,0,0,GetSystemMetrics(SM_CXSCREEN),GetSystemMetrics(SM_CYSCREEN),NULL,NULL,hInstance,NULL); ShowWindow(hwnd,SW_SHOWMAXIMIZED); UpdateWindow (hwnd); ShowCursor(FALSE); srand ((int )GetCurrentTime()); while(GetMessage (&msg,NULL,0,0)){ TranslateMessage(&msg); DispatchMessage (&msg); } ShowCursor(TRUE); return msg.wParam; } TCHAR randomChar(){ return (TCHAR)(rand()%(126-33)+33); } int init(CharColumn *cc,int cyScreen,int x){ int j; cc->iStrLen=rand()%(STRMAXLEN-STRMINLEN)+STRMINLEN; cc->x=x+3; cc->y=rand()%3?rand()%cyScreen:0; cc->iMustStopTimes=rand()%6; cc->iStopTimes=0; cc->head=cc->current=(pCharChain)calloc(cc->iStrLen,sizeof(CharChain)); for(j=0;j<cc->iStrLen-1;j++) { cc->current->prev = cc->point;//cc->current->prev = cc->point; cc->current->ch = '\0'; cc->current->next = cc->current+1; cc->point = cc->current++; } cc->current->prev = cc->point; cc->current->ch = '\0'; cc->current->next = cc->head; cc->head->prev = cc->current; cc->current = cc->point = cc->head; cc->head->ch=randomChar(); return 0; } LRESULT CALLBACK WndProc (HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam) { HDC hdc; int i,j,temp,ctn; static HDC hdcMem; HFONT hFont; static HBITMAP hBitmap; static int cxScreen,cyScreen; static int iFontWidth=10,iFontHeight=15,iColumnCount; static CharColumn *ccChain; switch(message) { case WM_CREATE: cxScreen=GetSystemMetrics(SM_CXSCREEN); cyScreen=GetSystemMetrics(SM_CYSCREEN); SetTimer (hwnd,ID_TIMER,10,NULL); hdc=GetDC(hwnd); hdcMem=CreateCompatibleDC(hdc); hBitmap=CreateCompatibleBitmap(hdc,cxScreen,cyScreen); SelectObject(hdcMem,hBitmap); ReleaseDC(hwnd,hdc); hFont=CreateFont(iFontHeight,iFontWidth-5,0,0,FW_BOLD,0,0,0,DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DRAFT_QUALITY,FIXED_PITCH | FF_SWISS,TEXT("Fixedays")); SelectObject(hdcMem,hFont); DeleteObject(hFont); SetBkMode(hdcMem,TRANSPARENT); iColumnCount=cxScreen/(iFontWidth*3/2); ccChain=(pCharColumn)calloc(iColumnCount,sizeof(CharColumn)); for(i=0;i<iColumnCount;i++) { init(ccChain+i,cyScreen,cyScreen,(iFontWidth*3/2)*i); } return 0 ; case WM_TIMER: hdc=GetDC(hwnd); PatBlt(hdcMem,0,0,cxScreen,cyScreen,BLACKNESS); for(i=0;i<iColumnCount;i++){ ctn=(ccChain+i)->iStopTimes++>(ccChain+i)->iMustStopTimes; (ccChain+i)->point=(ccChain+i)->head; SetTextColor(hdcMem,RGB(255,255,255)); TextOut(hdcMem,(ccChain+i)->x,(ccChain+i)->y,&((ccChain+i)->point->ch),1); j=(ccChain+i)->y; (ccChain+i)->point=(ccChain+i)->point->next; temp=0; while((ccChain+i)->point !=(ccChain+i)->head &&(ccChain+i)->point->ch) { SetTextColor(hdcMem,RGB(0,255-(255*(temp++)/(ccChain+i)->iStrLen),0)); TextOut(hdcMem,(ccChain+i)->x,j-=iFontHeight,&((ccChain+i)->point->ch),1); (ccChain+i)->point=(ccChain+i)->point->next; } if(ctn) (ccChain+i)->iStopTimes=0; else continue; (ccChain+i)->y+=iFontHeight; if((ccChain+i)->y-(ccChain+i)->iStrLen*iFontHeight>cyScreen) { free((ccChain+i)->current); init(ccChain+i,cyScreen,(iFontWidth*3/2)*i); } (ccChain+i)->head=(ccChain+i)->head->prev; (ccChain+i)->head->ch=randomChar(); } BitBlt(hdc,0,0,cxScreen,cyScreen,hdcMem,0,0,SRCCOPY); ReleaseDC(hwnd,hdc); return 0; case WM_RBUTTONDOWN: KillTimer(hwnd,ID_TIMER); return 0; case WM_KEYDOWN: case WM_LBUTTONDOWN: case WM_DESTROY: KillTimer (hwnd,ID_TIMER); DeleteObject(hBitmap); DeleteDC(hdcMem); for(i=0;i<iColumnCount;i++) { free((ccChain+i)->current); } free(ccChain); PostQuitMessage(0); return 0; } return DefWindowProc (hwnd,message,wParam,lParam); }
贪吃蛇
#include "string.h" #include "stdio.h" #include "stdlib.h" #include "time.h" #include "conio.h" #include "windows.h" const int H = 16; //地图的高 const int L = 30; //地图的长 char GameMap[16][30]; //游戏地图 int key; //按键保存 int sum = 1, over = 0; //蛇的长度, 游戏结束(自吃或碰墙) int dx[4] = {0, 0, -1, 1}; //左、右、上、下的方向 int dy[4] = {-1, 1, 0, 0}; int arr=15; struct Snake //蛇的每个节点的数据类型 { int x, y; //左边位置 int now; //保存当前节点的方向, 0,1,2,3分别为左右上下 }Snake[16*30]; const char Shead = '@'; //蛇头 const char Sbody = '#'; //蛇身 const char Sfood = '*'; //食物 const char Snode = '.'; //'.'在地图上标示为空 void Initial(); //地图的初始化 void Create_Food(); //在地图上随机产生食物 void Show(); //刷新显示地图 void Button(); //取出按键,并判断方向 void Move(); //蛇的移动 void Check_Border(); //检查蛇头是否越界 void Check_Head(int x, int y); //检查蛇头移动后的位置情况 int color(int c) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),c); return 0; } int main() { Initial(); Show(); return 0; } void Initial() //地图的初始化 { int i, j; int hx, hy; system("title 贪吃蛇"); //控制台的标题 memset(GameMap, '.', sizeof(GameMap)); //初始化地图全部为空'.' system("cls"); srand(time(0)); //随机种子 hx = rand()%16; //产生蛇头 hy = rand()%30; GameMap[hx][hy] = Shead; Snake[0].x = hx; Snake[0].y = hy; Snake[0].now = -1; Create_Food(); //随机产生食物 for(i = 0; i < 16; i++) //地图显示 { for(j = 0; j < 30; j++) printf(" %c", GameMap[i][j]); printf("\n"); } printf("\n\t\t\t小小C语言贪吃蛇\n"); printf("\t\t 按任意方向键开始游戏\n"); getch(); //先接受一个按键,使蛇开始往该方向走 Button(); //取出按键,并判断方向 } void Create_Food() //在地图上随机产生食物 { int fx, fy; while(1) { fx = rand()%16; fy = rand()%30; if(GameMap[fx][fy] == '.') //不能出现在蛇所占有的位置 { GameMap[fx][fy] = Sfood; break; } } } void Show() //刷新显示地图 { int i, j; while(1) { _sleep(250); //延迟半秒(1000为1s),即每半秒刷新一次地图 Button(); //先判断按键在移动 Move(); if(over) //自吃或碰墙即游戏结束 { printf("\n**游戏结束**\n"); printf("\t\t\t>_<\n"); getchar(); break; } system("cls"); //清空地图再显示刷新吼的地图 for(i = 0; i < 16; i++) { for(j = 0; j < 30; j++) printf(" %c", GameMap[i][j]); printf("\n"); } printf("\n小小C语言贪吃蛇\n"); printf("按任意方向键开始游戏\n"); } } void Button() //取出按键,并判断方向 { if(kbhit() != 0) //检查当前是否有键盘输入,若有则返回一个非0值,否则返回0 { while(kbhit() != 0) //可能存在多个按键,要全部取完,以最后一个为主 key = getch(); //将按键从控制台中取出并保存到key中 switch(key) { //左 case 75: Snake[0].now = 0; break; //右 case 77: Snake[0].now = 1; break; //上 case 72: Snake[0].now = 2; break; //下 case 80: Snake[0].now = 3; break; } } } void Move() //蛇的移动 { int i, x, y; int t = sum; //保存当前蛇的长度 //记录当前蛇头的位置,并设置为空,蛇头先移动 x = Snake[0].x; y = Snake[0].y; GameMap[x][y] = '.'; Snake[0].x = Snake[0].x + dx[ Snake[0].now ]; Snake[0].y = Snake[0].y + dy[ Snake[0].now ]; Check_Border(); //蛇头是否越界 Check_Head(x, y); //蛇头移动后的位置情况,参数为: 蛇头的开始位置 if(sum == t) //未吃到食物即蛇身移动哦 for(i = 1; i < sum; i++) //要从蛇尾节点向前移动哦,前一个节点作为参照 { if(i == 1) //尾节点设置为空再移动 GameMap[ Snake[i].x ][ Snake[i].y ] = '.'; if(i == sum-1) //为蛇头后面的蛇身节点,特殊处理 { Snake[i].x = x; Snake[i].y = y; Snake[i].now = Snake[0].now; } else //其他蛇身即走到前一个蛇身位置 { Snake[i].x = Snake[i+1].x; Snake[i].y = Snake[i+1].y; Snake[i].now = Snake[i+1].now; } GameMap[ Snake[i].x ][ Snake[i].y ] = '#'; //移动后要置为'#'蛇身 } } void Check_Border() //检查蛇头是否越界 { if(Snake[0].x < 0 || Snake[0].x >= 16 || Snake[0].y < 0 || Snake[0].y >= 30) over = 1; } void Check_Head(int x, int y) //检查蛇头移动后的位置情况 { if(GameMap[ Snake[0].x ][ Snake[0].y ] == '.') //为空 GameMap[ Snake[0].x ][ Snake[0].y ] = '@'; else if(GameMap[ Snake[0].x ][ Snake[0].y ] == '*') //为食物 { color(arr); GameMap[ Snake[0].x ][ Snake[0].y ] = '@'; Snake[sum].x = x; //新增加的蛇身为蛇头后面的那个 Snake[sum].y = y; Snake[sum].now = Snake[0].now; GameMap[ Snake[sum].x ][ Snake[sum].y ] = '#'; sum++; Create_Food(); //食物吃完了马上再产生一个食物 } else over = 1; }