- 论坛徽章:
- 2
|
windows控制台版本。- /***snake.c***/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <time.h>
- #include <windows.h>
- #define SNAKE_INITX 5
- #define SNAKE_INITY 5
- #define SNAKE_SHAPE '*'
- #define SNAKE_INITLEN 8
- #define WIN_X1 0
- #define WIN_X2 79
- #define WIN_Y1 0
- #define WIN_Y2 24
- #define MAX_LEVEL 20
- #define MAX_INTER 200000
- #define MIN_INTER 0
- #define MAX_RICH 10
- #define DEVRATE 5
- #define OVER "Game Over!!!"
- struct stNode
- {
- int x;
- int y;
- char shape;
- struct stNode *next;
- };
- struct stFood
- {
- int x;
- int y;
- };
- struct stNode *gpstHead,*gpstTail;
- struct stFood gastFood[MAX_RICH];
- int giLevel=1;
- int giRich=1;
- int giScore=0;
- int giLen=0;
- int con_get_size(int *o_width, int *o_height)
- {
- CONSOLE_SCREEN_BUFFER_INFO info;
- HANDLE hStdOutput;
-
- hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- GetConsoleScreenBufferInfo(hStdOutput, &info);
- if (o_width != NULL) {
- *o_width = info.dwMaximumWindowSize.X;
- }
- if (o_height != NULL) {
- *o_height = info.dwMaximumWindowSize.Y;
- }
- return 0;
- }
- int con_rectangle(int x1, int y1, int x2, int y2, char c)
- {
- HANDLE hStdOutput;
- COORD coord;
- DWORD dwOutputlen;
- int len;
- int width, height;
-
- con_get_size(&width, &height);
- if (x1 < 0) {
- x1 = 0;
- }
- if (y1 < 0) {
- y1 = 0;
- }
- if (x2 >= width) {
- x2 = width - 1;
- }
- if (y2 >= height) {
- y2 = height - 1;
- }
- if (x1 <= x2 && y1 <= y2) {
- hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- len = x2 - x1 + 1;
- coord.X = x1;
- for (coord.Y = y1; coord.Y <= y2; ++coord.Y) {
- FillConsoleOutputCharacter(hStdOutput, c, len, coord, &dwOutputlen);
- }
- return 0;
- }
- return -1;
- }
- int con_init(void)
- {
- HANDLE hStdOutput;
- DWORD dwMode;
-
- hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- GetConsoleMode(hStdOutput, &dwMode);
- dwMode &= ~ENABLE_WRAP_AT_EOL_OUTPUT;
- SetConsoleMode(hStdOutput, dwMode);
- return 0;
- }
- int con_show_cursor(int yes)
- {
- HANDLE hStdOutput;
- CONSOLE_CURSOR_INFO info;
-
- hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- GetConsoleCursorInfo(hStdOutput, &info);
- info.bVisible = yes != 0;
- SetConsoleCursorInfo(hStdOutput, &info);
- return 0;
- }
- int con_setxy(int x, int y)
- {
- HANDLE hStdOutput;
- COORD coord;
-
- hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- coord.X = x;
- coord.Y = y;
- SetConsoleCursorPosition(hStdOutput, coord);
- return 0;
- }
- int con_putchar(int x, int y, char c)
- {
- int width, height;
-
- con_get_size(&width, &height);
- if (x >= 0 && x < width && y >= 0 && y < height) {
- con_setxy(x, y);
- putchar(c);
- return 0;
- }
- return -1;
- }
- int con_puttext(int x, int y, const char *text, int text_len)
- {
- int tx;
- int i;
- int width, height;
-
- con_get_size(&width, &height);
- tx = x;
- for (i = 0; i < text_len; ++i) {
- switch (text[i]) {
- case '\n':
- tx = x;
- ++y;
- break;
- case '\t':
- tx = (tx + 8 - 1) / 8;
- tx *= 8;
- break;
- case '\r':
- tx = x;
- break;
- case '\b':
- if (tx > x) {
- --tx;
- }
- break;
- default:
- if (tx >= 0 && tx < width && y >= 0 && y < height) {
- con_setxy(tx, y);
- putchar(text[i]);
- }
- ++tx;
- break;
- }
- }
- return 0;
- }
- int con_box(int x1, int y1, int x2, int y2)
- {
- int i;
-
- for (i = x1 + 1; i < x2; ++i) {
- con_puttext(i, y1, "-", 1);
- con_puttext(i, y2, "-", 1);
- }
- for (i = y1 + 1; i < y2; ++i) {
- con_puttext(x1, i, "|", 1);
- con_puttext(x2, i, "|", 1);
- }
- con_puttext(x1, y1, "+", 1);
- con_puttext(x2, y1, "+", 1);
- con_puttext(x1, y2, "+", 1);
- con_puttext(x2, y2, "+", 1);
- return 0;
- }
- int con_readkey(void)
- {
- HANDLE hStdInput;
- INPUT_RECORD buf;
- DWORD dwRead;
- int retval;
-
- hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- for (;;) {
- if (PeekConsoleInput(hStdInput, &buf, 1, &dwRead)) {
- if (dwRead == 1) {
- if (ReadConsoleInput(hStdInput, &buf, 1, &dwRead)) {
- if (buf.EventType == KEY_EVENT) {
- return buf.Event.KeyEvent.wVirtualScanCode;
- }else {
- continue;
- }
- }else {
- retval = -2; /* READ ERROR */
- }
- }else {
- retval = 0; /* NO KEY PRESSED */
- }
- }else {
- retval = -1; /* PEEK ERROR */
- }
- break;
- }
- return retval;
- }
- int con_delay(int ms)
- {
- Sleep(ms);
- return 0;
- }
- void vDrawOneNode(struct stNode *pstNode,int iFlag)
- {
- con_puttext(pstNode->x, pstNode->y, iFlag ? &pstNode->shape : " ", 1);
- }
- void vDrawOneFood(int x,int y)
- {
- con_puttext(x, y, "@", 1);
- }
- int iGetDir(int iOriDir)
- {
- switch (con_readkey()) {
- case 72 ://UP
- return 0;
- case 80 ://DOWN
- return 1;
- case 77 ://RIGHT
- return 2;
- case 75 ://LEFT
- return 3;
- default:
- return iOriDir;
- }
- }
- void vInitScreen()
- {
- con_init();
- con_show_cursor(0);
- con_rectangle(WIN_X1, WIN_Y1, WIN_X2, WIN_Y2, ' ');
- }
- void vRestoreScreen()
- {
- con_show_cursor(1);
- }
- void vDrawScope()
- {
- con_box(WIN_X1, WIN_Y1, WIN_X2, WIN_Y2);
- }
- void vCreateSnake()
- {
- struct stNode *pstNew;
- int i;
-
- gpstHead=(struct stNode*)malloc(sizeof(struct stNode));
- gpstHead->x=SNAKE_INITX;
- gpstHead->y=SNAKE_INITY;
- gpstHead->shape=SNAKE_SHAPE;
- gpstHead->next=NULL;
- vDrawOneNode(gpstHead,1);
- gpstTail=gpstHead;
- for(i=1;i<SNAKE_INITLEN;i++)
- {
- pstNew=(struct stNode*)malloc(sizeof(struct stNode));
- pstNew->x=gpstHead->x+1;
- pstNew->y=gpstHead->y;
- pstNew->shape=SNAKE_SHAPE;
- pstNew->next=NULL;
- vDrawOneNode(pstNew,1);
- gpstHead->next=pstNew;
- gpstHead=pstNew;
- }
- return;
- }
- void vKillSnake()
- {
- struct stNode *pstNode;
-
- for(pstNode=gpstTail;gpstTail!=NULL;)
- {
- gpstTail=pstNode->next;
- free(pstNode);
- pstNode=gpstTail;
- }
- }
- void vGenFood(int iIdx)
- {
- struct stNode *pstNode;
- int i,iFound=0;
-
- for(;!iFound;)
- {
- iFound=1;
- gastFood[iIdx].x=rand()%(WIN_X2-WIN_X1-1)+WIN_X1+1;
- gastFood[iIdx].y=rand()%(WIN_Y2-WIN_Y1-1)+WIN_Y1+1;
- for(i=0;i<giRich;i++)
- {
- if(i!=iIdx && gastFood[iIdx].x==gastFood[i].x &&
- gastFood[iIdx].y==gastFood[i].y)
- {
- iFound=0;
- break;
- }
- }
- if(!iFound) continue;
- for(pstNode=gpstTail;pstNode!=NULL;pstNode=pstNode->next)
- {
- if(gastFood[iIdx].x==pstNode->x &&
- gastFood[iIdx].y==pstNode->y)
- {
- iFound=0;
- break;
- }
- }
- if(!iFound) continue;
- }
- vDrawOneFood(gastFood[iIdx].x,gastFood[iIdx].y);
- }
- void vInitFood()
- {
- int i;
-
- srand(time(NULL));
- for(i=0;i<giRich;i++) vGenFood(i);
- }
- int iIsValid(int x,int y)
- {
- struct stNode *pstNode;
-
- if(x<=WIN_X1 || x>=WIN_X2 || y<=WIN_Y1 || y>=WIN_Y2)
- return(0);
- pstNode=gpstTail;
- for(;pstNode!=NULL;)
- {
- if(x==pstNode->x && y==pstNode->y)
- return(0);
- pstNode=pstNode->next;
- }
- return(1);
- }
- int iEat(int x,int y)
- {
- int i;
-
- for(i=0;i<giRich;i++)
- {
- if(x==gastFood[i].x && y==gastFood[i].y)
- {
- vGenFood(i);
- giScore+=giLevel*10;
- giLen++;
- if(giLevel<MAX_LEVEL)
- if(giLen%DEVRATE==0)
- giLevel++;
- return(1);
- }
- }
- return(0);
- }
- int main(void)
- {
- int iDir=2,iNextX,iNextY;
- struct stNode *pstNew;
- char sPrompt[80];
-
- vInitScreen();
- vDrawScope();
- vCreateSnake();
- vInitFood();
- for(;;) {
- iDir=iGetDir(iDir);
- iNextX=gpstHead->x+(iDir>>1)*(5-(iDir<<1));
- iNextY=gpstHead->y-(!(iDir>>1))*(1-(iDir<<1));
- if(!iIsValid(iNextX,iNextY)) {
- con_puttext((WIN_X1+WIN_X2)/2-strlen(OVER)/2, WIN_Y2-1,OVER, strlen(OVER));
- break;
- }
- pstNew=(struct stNode*)malloc(sizeof(struct stNode));
- pstNew->x=iNextX;
- pstNew->y=iNextY;
- pstNew->shape=SNAKE_SHAPE;
- pstNew->next=NULL;
- gpstHead->next=pstNew;
- gpstHead=pstNew;
- vDrawOneNode(gpstHead, 1);
- if(!iEat(iNextX,iNextY)) {
- vDrawOneNode(gpstTail, 0);
- pstNew = gpstTail;
- gpstTail = gpstTail->next;
- free(pstNew);
- }
- sprintf(sPrompt,"Score:%7d Level:%2d",giScore,giLevel);
- con_puttext((WIN_X1+WIN_X2)/2-strlen(sPrompt)/2, WIN_Y2, sPrompt, strlen(sPrompt));
- con_delay((MAX_INTER-(MAX_INTER-MIN_INTER)/MAX_LEVEL*giLevel)/1000);
- }
- vKillSnake();
- vRestoreScreen();
- return 0;
- }
复制代码 |
|