c语言利用二维数组做两条贪吃蛇,打造C语言版贪吃蛇(下)

/**********************************************************

*snake.c

*a snake game

*

*Created by penhison

*Copyright 2017 penhison@gmail.com

*All right reserved

*

**********************************************************/

/**********************************************************

*changelog:

*

*2017/12/19 initial release

*2017/12/20 make map partial refresh

*2017/12/21 add player rank

*2017/12/23 add cheat mode

*

**********************************************************/

#include

#include

#include

#include

#include

#define MAP_LENGTH 40

#define MAP_HIGHT 30

#define BLANK_CELL ' '

#define WALL_CELL '*'

#define INIT_SNAKE_LENGTH 3

#define SNAKE_HEAD 'H'

#define SNAKE_BODY 'X'

#define SNAKE_FOOD '$'

#define UP (input == 'W' || input == 'w' || input == 72)

#define DOWN (input == 'S' || input == 's' || input == 80)

#define LEFT (input == 'A' || input == 'a' || input == 75)

#define RIGHT (input == 'D' || input == 'd' || input == 77)

#define PAUSE (input == ' ')

#define CHEAT (input == 'C' || input == 'c')

void initSnake();

void initFood();

void printMap();

void printMode();

void initGame();

void printSnake();

void printFood();

void printLength();

void productFood();

void eatFood();

int inputValid(char input);

void snakeControlMove(char input);

void snakeAutoMove();

void snakeMove();

int snakeDie();

void startGame();

void selectMode();

void playGame();

void gamePause();

void gameOver();

void restart();

void locateCursor(int x, int y);

void switchCursorVisible();

void inputName();

void getTime();

void initRank();

void ranking(FILE * fp, struct Player player[]);

void printRank(FILE * fp, struct Player player[]);

void rank();

void switchCheatMode();

void snakeSmartMove();

struct Snake {

int x[MAP_LENGTH * MAP_HIGHT + 1];

int y[MAP_LENGTH * MAP_HIGHT + 1];

int length;

int speed;

};

struct Food {

int x;

int y;

int exist;

};

struct Player {

char name[20];

char date[20];

int score;

};

struct Snake snake;

struct Food food;

struct Player currentPlayer;

char mode[20];

int cheat;

int main() {

startGame();

while(1) {

selectMode();

playGame();

gameOver();

restart();

}

return 0;

}

void startGame() {

printf("贪吃蛇游戏\n\n");

printf("方向键或WASD控制\n");

printf("长按加速\n");

printf("按空格键暂停\n\n");

printf("按任意键开始游戏\n");

getch();

inputName();

}

void selectMode() {

system("cls");

printf("请选择游戏模式:\n");

printf("1. easy\n");

printf("2. normal\n");

printf("3. hard\n");

printf("4. very hard\n");

printf("5. crazy\n");

printf("6. go die\n");

char input = getch();

switch (input) {

case '1':

snake.speed = 600;

strcpy(mode, "easy");

break;

case '2':

snake.speed = 300;

strcpy(mode, "normal");

break;

case '3':

snake.speed = 100;

strcpy(mode, "hard");

break;

case '4':

snake.speed = 50;

strcpy(mode, "very hard");

break;

case '5':

snake.speed = 20;

strcpy(mode, "crazy");

break;

case '6':

snake.speed = 10;

strcpy(mode, "go die");

break;

default:

snake.speed = 300;

strcpy(mode, "normal");

break;

}

return;

}

void playGame() {

initGame();

while (!snakeDie()) {

printSnake();

printFood();

printLength();

locateCursor(0, 1);

putchar(WALL_CELL);

locateCursor(0, MAP_HIGHT + 3);

snakeMove();

eatFood();

productFood();

}

}

void gamePause() {

system("pause");

locateCursor(0, MAP_HIGHT + 3);

printf(" ");

}

void gameOver() {

system("cls");

printf("\n\n\n\n Game over\n\n\n\n");

printf("你的蛇长:%d\n", snake.length);

printf("按空格键重玩\n\n");

rank();

}

void restart() {

char ch = 0;

while(ch != ' ') {

ch = getch();

}

}

void initGame() {

cheat = 0;

system("cls");

initSnake();

initFood();

printMap();

}

void initSnake() {

snake.length = INIT_SNAKE_LENGTH;

for (int i = 0; i <= snake.length; ++ i) {

snake.x[i] = snake.length + 1 - i;

snake.y[i] = 5;

}

}

void initFood() {

food.exist = 0;

productFood();

}

void printMap() {

printf("length:%d", snake.length);

printMode();

char map[MAP_HIGHT + 2][MAP_LENGTH + 2];

for (int i = 0; i < MAP_HIGHT + 2; ++ i) {

for (int j = 0; j < MAP_LENGTH + 2; ++ j) {

if (i == 0 || i == MAP_HIGHT + 1 || j == 0 || j == MAP_LENGTH + 1)

map[i][j] = WALL_CELL;

else map[i][j] = BLANK_CELL;

putchar(map[i][j]);

}

putchar('\n');

}

}

void printMode() {

int modeLength;

modeLength = strlen(mode);

for (int i = 0; i < 34 - modeLength; ++ i) {

putchar(' ');

}

printf("%s\n", mode);

}

void printSnake() {

locateCursor(snake.x[snake.length], snake.y[snake.length] + 1);

putchar(BLANK_CELL);

locateCursor(snake.x[0], snake.y[0] + 1);

putchar(SNAKE_HEAD);

locateCursor(snake.x[1], snake.y[1] + 1);

putchar(SNAKE_BODY);

}

void printFood() {

locateCursor(food.x, food.y + 1);

putchar(SNAKE_FOOD);

}

void printLength() {

locateCursor(7, 0);

printf("%d", snake.length);

}

void productFood() {

srand( (unsigned)time(NULL) );

while (!food.exist) {

food.x = rand() % MAP_LENGTH + 1;

food.y = rand() % MAP_HIGHT + 1;

food.exist = 1;

for (int i = 0; i < snake.length; ++ i) {

if (snake.x[i] == food.x && snake.y[i] == food.y) {

food.exist = 0;

break;

}

}

}

}

void eatFood() {

if (snake.x[0] == food.x && snake.y[0] == food.y) {

food.exist = 0;

snake.length += 1;

}

}

int inputValid(char input) {

if UP

if (snake.y[0] > snake.y[2]) return 0;

if DOWN

if (snake.y[0] < snake.y[2]) return 0;

if LEFT

if (snake.x[0] > snake.x[2]) return 0;

if RIGHT

if (snake.x[0] < snake.x[2]) return 0;

return 1;

}

void snakeControlMove(char input) {

if UP snake.y[0] -= 1;

if DOWN snake.y[0] += 1;

if LEFT snake.x[0] -= 1;

if RIGHT snake.x[0] += 1;

return;

}

void snakeAutoMove() {

if (cheat == 1) {

snakeSmartMove();

return;

}

if (snake.x[0] > snake.x[2]) snake.x[0] += 1;

if (snake.x[0] < snake.x[2]) snake.x[0] -= 1;

if (snake.y[0] > snake.y[2]) snake.y[0] += 1;

if (snake.y[0] < snake.y[2]) snake.y[0] -= 1;

}

void snakeMove() {

for (int i = snake.length; i > 0; -- i) {

snake.x[i] = snake.x[i - 1];

snake.y[i] = snake.y[i - 1];

}

char input = 0;

int start = clock();

while (clock() - start < snake.speed) {

if (!kbhit()) continue;

input = getch();

if (!UP && !DOWN && !LEFT && !RIGHT && !PAUSE && !CHEAT)

continue;

if PAUSE {

gamePause();

continue;

}

if CHEAT {

switchCheatMode();

continue;

}

if (!inputValid(input)) {

continue;

}

snakeControlMove(input);

return;

}

snakeAutoMove();

}

int snakeDie() {

if (snake.x[0] == 0 || snake.x[0] == MAP_LENGTH + 1

|| snake.y[0] == 0 || snake.y[0] == MAP_HIGHT + 1)

return 1;

for(int i = 1; i < snake.length; ++ i) {

if( (snake.x[0] == snake.x[i]) && (snake.y[0] == snake.y[i]) )

return 1;

}

return 0;

}

void locateCursor(int x, int y) {

COORD cor;

cor.X = x;

cor.Y = y;

HANDLE hout = GetStdHandle(STD_OUTPUT_HANDLE);

SetConsoleCursorPosition(hout, cor);

}

void switchCursorVisible() {

HANDLE hout;

hout = GetStdHandle(STD_OUTPUT_HANDLE);

CONSOLE_CURSOR_INFO cci;

GetConsoleCursorInfo(hout, &cci);

cci.bVisible = 0;

SetConsoleCursorInfo(hout, &cci);

}

void rank() {

currentPlayer.score = snake.length;

getTime();

struct Player player[5];

FILE * fp;

fp = fopen(mode, "r");

if (fp == NULL) {

fclose(fp);

initRank();

fp = fopen(mode, "r");

}

ranking(fp, player);

printRank(fp, player);

fclose(fp);

}

void inputName() {

system("cls");

printf("Please input you name\n");

scanf("%s", currentPlayer.name);

switchCursorVisible();

}

void getTime() {

struct tm * date;

time_t currentTime;

time(&currentTime);

date = localtime(&currentTime);

strftime(currentPlayer.date, 20, "%Y/%m/%d %H:%M:%S", date);

}

void initRank() {

FILE * fp;

fp = fopen(mode, "w");

for (int i = 0; i < 5; ++ i) {

fprintf(fp, "%s\t%d\t", "anonymous", 0);

fprintf(fp, "%s %s\n", "2017/12/22", "00:00:00");

}

fclose(fp);

}

void ranking(FILE * fp, struct Player player[]) {

for (int i = 0; i < 5; ++ i) {

fscanf(fp, "%s\t%d\t", player[i].name, &player[i].score);

fgets(player[i].date, 20, fp);

}

for (int i = 0; i < 5; ++ i) {

if (currentPlayer.score >= player[i].score) {

for (int j = 4; j > i; -- j) {

strcpy(player[j].name, player[j - 1].name);

strcpy(player[j].date, player[j - 1].date);

player[j].score = player[j - 1].score;

}

strcpy(player[i].name, currentPlayer.name);

strcpy(player[i].date, currentPlayer.date);

player[i].score = currentPlayer.score;

break;

}

}

}

void printRank(FILE * fp, struct Player player[]) {

printf("\nrank:\n\n");

printf("%-10s %s\n\n", "player", "score");

for (int i = 0; i < 5; ++ i) {

printf("%-10s %5d %s\n", player[i].name, player[i].score,

player[i].date);

}

fclose(fp);

fp = fopen(mode, "w");

for (int i = 0; i < 5; ++ i) {

fprintf(fp, "%s\t%d\t%s\n", player[i].name, player[i].score,

player[i].date);

}

}

void switchCheatMode() {

cheat = !cheat;

if (cheat) {

locateCursor(16, 0);

printf("cheat mode");

}

else {

locateCursor(16, 0);

printf(" ");

}

return;

}

const int direction[4][2] = {{1, 0}, {0, 1}, {0, -1}, {-1, 0}};

#define f(x) (x->g + x->h)

#define abs(number) number > 0 ? number : -number

struct node {

char x;

char y;

char g;

char h;

char isBlock;

char inOpenTable;

char inCloseTable;

struct node * parent;

};

struct Result {

int x;

int y;

int found;

};

struct node mapNode[MAP_LENGTH + 2][MAP_HIGHT + 2];

struct node * openTable[1200];

struct node * closeTable[1200];

int openTableCount;

int closeTableCount;

void initMapNode() {

for (int i = 0; i < MAP_LENGTH + 2; ++ i) {

for (int j = 0; j < MAP_HIGHT + 2; ++ j) {

mapNode[i][j].x = i;

mapNode[i][j].y = j;

mapNode[i][j].g = 0;

mapNode[i][j].h = 0;

mapNode[i][j].inOpenTable = 0;

mapNode[i][j].inCloseTable = 0;

mapNode[i][j].parent = NULL;

if (i == 0 || i == MAP_LENGTH + 1 || j == 0 || j == MAP_HIGHT + 1)

mapNode[i][j].isBlock = 1;

else mapNode[i][j].isBlock = 0;

}

}

for (int i = 1; i < snake.length; ++ i) {

mapNode[snake.x[i]][snake.y[i]].isBlock = 1;

}

}

void swap(int x1, int x2) {

struct node * temp = openTable[x1];

openTable[x1] = openTable[x2];

openTable[x2] = temp;

}

void heapSort(int nodeIndex) {

int current = nodeIndex;

int parent = (current - 1) / 2;

int child = current * 2 + 1;

while (child < openTableCount) {

if ( (child + 1 < openTableCount) && (f(openTable[child + 1]) < f(openTable[child])) )

child++;

if (f(openTable[current]) <= f(openTable[child])) break;

else {

swap(current, child);

current = child;

child = current * 2 + 1;

}

}

if (current != nodeIndex) return;

while (current != 0) {

if (f(openTable[current]) >= f(openTable[parent])) break;

else {

swap(current, parent);

current = parent;

parent = (current - 1) / 2;

}

}

}

void insertToOpenTable(int x, int y, struct node * currentNode, struct node * endNode) {

if (!mapNode[x][y].isBlock && !mapNode[x][y].inCloseTable) {

if (mapNode[x][y].inOpenTable) {

if (mapNode[x][y].g > currentNode->g + 1) {

mapNode[x][y].g = currentNode->g + 1;

mapNode[x][y].parent = currentNode;

int i;

for (i = 0; i < openTableCount; ++ i) {

if (openTable[i]->x == x && openTable[i]->y == y) break;

}

heapSort(i);

}

}

else {

mapNode[x][y].g = currentNode->g + 1;

mapNode[x][y].h = abs(endNode->x - x) + abs(endNode->y - y);

mapNode[x][y].parent = currentNode;

mapNode[x][y].inOpenTable = 1;

openTable[openTableCount++] = &(mapNode[x][y]);

heapSort(openTableCount - 1);

}

}

}

void getNeighbors(struct node * currentNode, struct node * endNode) {

for (int i = 0; i < 4; ++ i) {

int tempx = currentNode->x + direction[i][0];

int tempy = currentNode->y + direction[i][1];

insertToOpenTable(tempx, tempy, currentNode, endNode);

}

}

struct Result search(int startX, int startY, int goalX, int goalY) {

struct Result result;

initMapNode();

struct node * startNode;

struct node * endNode;

struct node * currentNode;

openTableCount = 0;

closeTableCount = 0;

startNode = &(mapNode[startX][startY]);

endNode = &(mapNode[goalX][goalY]);

endNode->isBlock = 0;

openTable[openTableCount++] = startNode;

startNode->h = abs(startNode->x - endNode->x) + abs(startNode->y - endNode->y);

startNode->inOpenTable = 1;

while(1) {

currentNode = openTable[0];

openTable[0] = openTable[--openTableCount];

heapSort(0);

closeTable[closeTableCount++] = currentNode;

currentNode->inCloseTable = 1;

if (currentNode->x == endNode->x && currentNode->y == endNode->y) {

result.x = currentNode->parent->x;

result.y = currentNode->parent->y;

result.found = 1;

break;

}

getNeighbors(currentNode, endNode);

if (openTableCount == 0) {

result.found = 0;

break;

}

}

return result;

}

void wander() {

int nextX;

int nextY;

for (int i= 0; i < 4; ++ i) {

nextX = snake.x[0] + direction[i][0];

nextY = snake.y[0] + direction[i][1];

initMapNode();

if (mapNode[nextX][nextY].isBlock) continue;

if (search(snake.x[snake.length - 1], snake.y[snake.length - 1], nextX, nextY).found) {

snake.x[0] = nextX;

snake.y[0] = nextY;

return;

}

}

}

void snakeSmartMove() {

struct Result findSnakeHead;

struct Result findSnakeTail;

findSnakeHead = search(food.x, food.y, snake.x[0], snake.y[0]);

if (findSnakeHead.found == 1) {

findSnakeTail = search(snake.x[snake.length - 1], snake.y[snake.length - 1], findSnakeHead.x, findSnakeHead.y);

if (findSnakeTail.found == 1) {

snake.x[0] = findSnakeHead.x;

snake.y[0] = findSnakeHead.y;

return;

}

}

wander();

return;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值