在這裏,我們主要使用C語言和數據結構鏈表來實現對貪喫蛇小遊戲的實現。
主函數
在主函數中,我們需要實現對貪喫蛇遊戲的整體流程的實現。
HideCursor();//隱藏光標顯示,調用一次
srand((unsigned)time(NULL));
Snake snake; //創建遊戲框架
GameStart(&snake); //遊戲開始
GameRun(&snake); //遊戲過程
GameEnd(&snake); //遊戲結束
遊戲信息定義
#define INIT_X 26 //初始位列
#define INIT_Y 12 //初始位行
enum Direction //蛇的運動方向
{
UP, //上
DOWN, //下
LEFT, //左
RIGHT //右
};
enum Gamestatus //遊戲狀態
{
OK, //正常狀態
NORMAL_END, //正常退出
KILL_BY_WALL, //撞牆死亡
KILL_EY_SELF //撞蛇死亡
};
typedef struct SnakeNode //結點位置
{
int x;
int y;
struct SnakeNode* next;
}SnakeNode, *pSnakeNode;
typedef struct Snake //遊戲框架
{
pSnakeNode _pSnake; //蛇頭指針
pSnakeNode _pFood; //食物位置指針
int _TotalScore; //得分
int _AddScore; //增加的分數
int _SleepTime; //休眠時間
enum Direction _Dir;//方向
enum Gamestatus _status;//遊戲狀態
}Snake, *pSnake;
遊戲信息設置
遊戲界面設置
實現對遊戲界面的初始化
void WecomeToGame()//打印歡迎界面
{
//設置窗口大小
system("mode con cols=100 lines=30");//設置DOS窗口的尺寸將會變爲100列30行的
/*
鍵入mode con cols = 100 lines = 30
則DOS窗口的尺寸將會變爲30行100列的,
cols(列)最小值爲13,lines(行)最小值爲1。
在C語言中也可以通過system函數調用這個dos命令來實現這個功能。
*/
//打印文字
SerPos(37, 12); //定位光標 列,行
printf("歡迎來到貪喫蛇小遊戲");
SerPos(37, 20);
system("pause");
system("cls");
SerPos(37, 12); //定位光標 列,行
printf("提示:↑ ↓ ← → 控制貪喫蛇方向");
SerPos(37, 13); //定位光標 列,行
printf("提示:F1:加速,F2,減速 加速可獲得更高的分數");
SerPos(37, 20);
system("pause");
system("cls");
}
創建地圖
通過一些特殊字符,來實現對地圖邊界的劃分.
void CreateMap()//創建地圖 60列 * 28行
{
int i = 0;
//上邊界
for (i = 0; i < 60; i = i + 2)
{
SerPos(i, 0); //定位光標 列,行
printf("%s", "▇");
}
//下邊界
for (i = 0; i < 60; i = i + 2)
{
SerPos(i, 27); //定位光標 列,行
printf("%s", "▇");
}
//左邊界
for (i = 1; i < 27; i++)
{
SerPos(0, i); //定位光標 列,行
printf("%s", "▇");
}
//右邊界
for (i = 1; i < 27; i++)
{
SerPos(58, i); //定位光標 列,行
printf("%s", "▇");
}
}
打印信息
void PrintInformation(pSnake ps)//打印信息
{
//打印得分
SerPos(70, 10);
printf("得分:%d ", ps->_TotalScore);
SerPos(70, 11);
printf("當前所加得分:%d ", ps->_AddScore);
//打印文字
SerPos(70, 12);
printf("↑ ↓ ← → 控制貪喫蛇方向");
SerPos(70, 13);
printf("提示:");
SerPos(70, 14);
printf("F1:加速,F2:減速");
SerPos(70, 15);
printf("空格:暫停");
SerPos(70, 16);
printf("Esc:退出");
}
遊戲流程
遊戲開始
void GameStart(pSnake ps) //遊戲開始
{
//打印歡迎界面
WecomeToGame();
//創建地圖
CreateMap();
//初始化蛇
InitSnake(ps);
//初始化食物
CreateFood(ps);
//初始化其他數據
ps->_TotalScore = 0; //得分
ps->_AddScore = 10; //增加的分數
ps->_SleepTime = 500; //休眠時間
ps->_Dir = RIGHT;//方向
ps->_status = OK;//遊戲狀態
}
遊戲過程
void GameRun(pSnake ps) //遊戲過程
{
do
{
DirectionOfDdtermination(ps);//鍵盤輸入操作
SnakeMovement(ps);//蛇移動
PrintInformation(ps);//打印信息
KillByWall(ps);//被牆撞死
KillBySelf(ps);//被蛇撞死
Sleep(ps->_SleepTime); //蛇睡眠
} while (OK == ps->_status);
}
遊戲結束
void GameEnd(pSnake ps)//遊戲結束
{
if(NORMAL_END == ps->_status)
{
SerPos(22, 13);
printf("遊戲結束!");
}
else if(KILL_BY_WALL == ps->_status)
{
SerPos(22, 13);
printf("撞牆,遊戲結束!");
}
else if (KILL_EY_SELF == ps->_status)
{
SerPos(22, 13);
printf("撞蛇身,遊戲結束!");
}
//釋放蛇
while (NULL != ps->_pSnake)
{
pSnakeNode del = ps->_pSnake;
ps->_pSnake = ps->_pSnake->next;
free(del);
del = NULL;
}
//釋放食物
free(ps->_pFood);
ps->_pFood = NULL;
}
初始化蛇與食物
蛇
void InitSnake(pSnake ps)//初始化蛇
{
//創建蛇身
//創建第一個結點
pSnakeNode first = BuyNode();
first->x = INIT_X;
first->y = INIT_Y;
//創建剩餘結點
pSnakeNode cur;
for (int i = 0; i < 4; i++)
{
//創建結點
cur = BuyNode();
cur->x = first->x + 2;
cur->y = first->y;
//插入節點(頭插)
cur->next = first;
first = cur;
}
ps->_pSnake = first; //蛇頭指針
//打印蛇
while (cur != NULL) //循環cur指向第一個結點
{
SerPos(cur->x, cur->y);
printf("%s", "■");
cur = cur->next;
}
printf("\n");
}
食物
void CreateFood(pSnake ps)//生成食物
{
pSnakeNode pfood = BuyNode(); //食物結點
again:
//隨機生成食物的位置
do //列
{
pfood->x = rand()%55 + 2; //2-56 0-54+2
} while (0 != pfood->x % 2); //x必須爲偶數,否則蛇喫不到
pfood->y = rand() % 26 + 1;//1-26 0-25+//行
pSnakeNode cur = ps->_pSnake; //蛇頭
while (NULL != cur) //遍歷蛇身,防止食物出現在蛇身上
{
if (cur->x == pfood->x && cur->y == pfood->y)
{
goto again; //跳轉至again處
}
cur = cur->next;
}
ps->_pFood = pfood;
SerPos(pfood->x, pfood->y);
printf("%s", "★");
}
喫食物
void EatFood(pSnake ps, pSnakeNode snewnode)//喫食物
{
//把新節點插入到蛇中
snewnode->next = ps->_pSnake;
ps->_pSnake = snewnode;
//打印新結點
SerPos(ps->_pSnake->x, ps->_pSnake->y);
printf("■");
//加分
ps->_TotalScore = ps->_TotalScore + ps->_AddScore;
//重新生成食物
CreateFood(ps);
}
無食物
void NoFood(pSnake ps, pSnakeNode snewnode)//無食物
{
//把新節點插入到蛇中
snewnode->next = ps->_pSnake;
ps->_pSnake = snewnode;
//打印新結點
SerPos(ps->_pSnake->x, ps->_pSnake->y);
printf("%s", "■");
//處理尾結點 需要把倒數第二個結點的next變成空
pSnakeNode cur = ps->_pSnake;
while (cur->next->next != NULL) //尾結點
{
cur = cur->next;
}
SerPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
}
控制蛇移動
鍵盤輸入
void DirectionOfDdtermination(pSnake ps)//鍵盤輸入操作
{
if (DOWN != ps->_Dir && GetAsyncKeyState(VK_UP))//向上,不能走回去
{
ps->_Dir = UP;
}
else if (UP != ps->_Dir && GetAsyncKeyState(VK_DOWN))//向下
{
ps->_Dir = DOWN;
}
else if (RIGHT != ps->_Dir && GetAsyncKeyState(VK_LEFT))//向左
{
ps->_Dir = LEFT;
}
else if (LEFT != ps->_Dir && GetAsyncKeyState(VK_RIGHT))//向右
{
ps->_Dir = RIGHT;
}
else if (GetAsyncKeyState(VK_SPACE))//暫停
{
Pause();//時間暫停,如果任意鍵爲空格,則會讀取一個空格
}
else if (GetAsyncKeyState(VK_ESCAPE))//退出
{
ps->_status = NORMAL_END;
}
else if (GetAsyncKeyState(VK_F1))//加速
{
//300
if (ps->_AddScore < 15)
{
ps->_AddScore = ps->_AddScore + 1; //增加的分數+1
ps->_SleepTime = ps->_SleepTime - 30; //休眠時間-30 min=150
}
}
else if (GetAsyncKeyState(VK_F2))//減速
{
if (ps->_AddScore > 5)
{
ps->_AddScore = ps->_AddScore - 1; //增加的分數-1
ps->_SleepTime = ps->_SleepTime + 30; //休眠時間-30 max = 450
}
}
}
蛇移動
void SnakeMovement(pSnake ps)//蛇移動
{
pSnakeNode snewnode = BuyNode(); //創捷新結點
switch (ps->_Dir)
{
case UP://向上
{
//新結點賦值
snewnode->x = ps->_pSnake->x;
snewnode->y = ps->_pSnake->y - 1;
//判斷是否爲食物
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物
{
EatFood(ps, snewnode);
}
else//不是食物
{
NoFood(ps, snewnode);
}
}
break;
case DOWN://向下
{
//新結點賦值
snewnode->x = ps->_pSnake->x;
snewnode->y = ps->_pSnake->y + 1;
//判斷是否爲食物
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物
{
EatFood(ps, snewnode);
}
else//不是食物
{
NoFood(ps, snewnode);
}
}
break;
case LEFT://向左
{
//新結點賦值
snewnode->x = ps->_pSnake->x - 2;
snewnode->y = ps->_pSnake->y;
//判斷是否爲食物
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物
{
EatFood(ps, snewnode);
}
else//不是食物
{
NoFood(ps, snewnode);
}
}
break;
case RIGHT://向右
{
//新結點賦值
snewnode->x = ps->_pSnake->x + 2;
snewnode->y = ps->_pSnake->y;
//判斷是否爲食物
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y) //是食物
{
EatFood(ps, snewnode);
}
else//不是食物
{
NoFood(ps, snewnode);
}
}
break;
}
}
判斷遊戲失敗
被牆撞死
void KillByWall(pSnake ps)//被牆撞死
{
//2-58 1-26
if (ps->_pSnake->x< 2 ||
ps->_pSnake->x > 56 ||
ps->_pSnake->y < 1 ||
ps->_pSnake->y > 26)
{
ps->_status = KILL_BY_WALL;
}
}
被蛇身撞死
void KillBySelf(pSnake ps)//被蛇身撞死
{
pSnakeNode cur = ps->_pSnake->next;
while (NULL != cur)
{
if (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y)
{
ps->_status = KILL_EY_SELF;
return;
}
cur = cur->next;
}
}
輔助函數
void HideCursor()//隱藏光標顯示,只需調用一次
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void SerPos(int x, int y) //定位光標,將光標調整到(x,y)的位置 列,行
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);//獲取標準輸出的句柄
COORD pos = { 0 };
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos); //設置標準輸出上光標的位置爲pos
}
void Pause()//時間暫停
{
while (1)
{
Sleep(100);
if (GetAsyncKeyState(VK_SPACE))
{
break;
}
}
}
源代碼
snake.h
#ifndef __SNAKE_H__
#define __SNAKE_H__
#include <stdio.h>
#include <windows.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#define INIT_X 26
#define INIT_Y 12
enum Direction //蛇的運動方向
{
UP,
DOWN,
LEFT,
RIGHT
};
enum Gamestatus //遊戲狀態
{
OK,
NORMAL_END,
KILL_BY_WALL,
KILL_EY_SELF
};
typedef struct SnakeNode //結點位置
{
int x;
int y;
struct SnakeNode* next;
}SnakeNode, *pSnakeNode;
typedef struct Snake //遊戲框架
{
pSnakeNode _pSnake;
pSnakeNode _pFood;
int _TotalScore;
int _AddScore;
int _SleepTime;
enum Direction _Dir;
enum Gamestatus _status;
}Snake, *pSnake;
void HideCursor();//隱藏光標顯示,調用一次
void SerPos(int x, int y);//定位光標
void WecomeToGame();//打印歡迎界面
void CreateMap();//創建地圖
pSnakeNode BuyNode(); //創捷新結點
void InitSnake(pSnake ps);//初始化蛇
void CreateFood(pSnake ps);//生成食物
void Pause();//時間暫停
void DirectionOfDdtermination(pSnake ps);//鍵盤輸入操作
void EatFood(pSnake ps, pSnakeNode snewnode);//喫食物
void NoFood(pSnake ps, pSnakeNode snewnode);//無食物
void SnakeMovement(pSnake ps);//蛇移動
void PrintInformation(pSnake ps);//打印信息
void KillByWall(pSnake ps);//被牆撞死
void KillBySelf(pSnake ps);//被蛇撞死
void GameStart(pSnake ps);//遊戲開始
void GameRun(pSnake ps); //遊戲過程
void GameEnd(pSnake ps);//遊戲結束
#endif __SNAKE_H__
snack.c
#include "snake.h"
void HideCursor()//隱藏光標顯示,調用一次
{
CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}
void SerPos(int x, int y) //定位光標,將光標調整到(x,y)的位置 列,行
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { 0 };
pos.X = x;
pos.Y = y;
SetConsoleCursorPosition(handle, pos);
}
void WecomeToGame()//打印歡迎界面
{
system("mode con cols=100 lines=30");
SerPos(37, 12);
printf("歡迎來到貪喫蛇小遊戲");
SerPos(37, 20);
system("pause");
system("cls");
SerPos(37, 12);
printf("提示:↑ ↓ ← → 控制貪喫蛇方向");
SerPos(37, 13);
printf("提示:F1:加速,F2,減速 加速可獲得更高的分數");
SerPos(37, 20);
system("pause");
system("cls");
}
void CreateMap()//創建地圖 60列 * 28行
{
int i = 0;
for (i = 0; i < 60; i = i + 2)
{
SerPos(i, 0);
printf("%s", "▇");
}
for (i = 0; i < 60; i = i + 2)
{
SerPos(i, 27);
printf("%s", "▇");
}
for (i = 1; i < 27; i++)
{
SerPos(0, i);
printf("%s", "▇");
}
for (i = 1; i < 27; i++)
{
SerPos(58, i);
printf("%s", "▇");
}
}
pSnakeNode BuyNode() //創捷新結點
{
pSnakeNode psnake = (pSnakeNode)malloc(sizeof(SnakeNode));
if (NULL == psnake)
{
perror(NULL);
exit(EXIT_FAILURE);
}
psnake->next = NULL;
return psnake;
}
void InitSnake(pSnake ps)//初始化蛇
{
pSnakeNode first = BuyNode();
first->x = INIT_X;
first->y = INIT_Y;
pSnakeNode cur;
for (int i = 0; i < 4; i++)
{
cur = BuyNode();
cur->x = first->x + 2;
cur->y = first->y;
cur->next = first;
first = cur;
}
ps->_pSnake = first;
while (cur != NULL)
{
SerPos(cur->x, cur->y);
printf("%s", "■");
cur = cur->next;
}
printf("\n");
}
void CreateFood(pSnake ps)//生成食物
{
pSnakeNode pfood = BuyNode();
again:
do
{
pfood->x = rand()%55 + 2;
} while (0 != pfood->x % 2);
pfood->y = rand() % 26 + 1;
pSnakeNode cur = ps->_pSnake;
while (NULL != cur)
{
if (cur->x == pfood->x && cur->y == pfood->y)
{
goto again;
}
cur = cur->next;
}
ps->_pFood = pfood;
SerPos(pfood->x, pfood->y);
printf("%s", "★");
}
void Pause()//時間暫停
{
while (1)
{
Sleep(100);
if (GetAsyncKeyState(VK_SPACE))
{
break;
}
}
}
void DirectionOfDdtermination(pSnake ps)//鍵盤輸入操作
{
if (DOWN != ps->_Dir && GetAsyncKeyState(VK_UP))
{
ps->_Dir = UP;
}
else if (UP != ps->_Dir && GetAsyncKeyState(VK_DOWN))
{
ps->_Dir = DOWN;
}
else if (RIGHT != ps->_Dir && GetAsyncKeyState(VK_LEFT))
{
ps->_Dir = LEFT;
}
else if (LEFT != ps->_Dir && GetAsyncKeyState(VK_RIGHT))
{
ps->_Dir = RIGHT;
}
else if (GetAsyncKeyState(VK_SPACE))
{
Pause();
}
else if (GetAsyncKeyState(VK_ESCAPE))
{
ps->_status = NORMAL_END;
}
else if (GetAsyncKeyState(VK_F1))
{
if (ps->_AddScore < 15)
{
ps->_AddScore = ps->_AddScore + 1;
ps->_SleepTime = ps->_SleepTime - 30;
}
}
else if (GetAsyncKeyState(VK_F2))
{
if (ps->_AddScore > 5)
{
ps->_AddScore = ps->_AddScore - 1;
ps->_SleepTime = ps->_SleepTime + 30;
}
}
}
void EatFood(pSnake ps, pSnakeNode snewnode)//喫食物
{
snewnode->next = ps->_pSnake;
ps->_pSnake = snewnode;
SerPos(ps->_pSnake->x, ps->_pSnake->y);
printf("■");
ps->_TotalScore = ps->_TotalScore + ps->_AddScore;
CreateFood(ps);
}
void NoFood(pSnake ps, pSnakeNode snewnode)//無食物
{
snewnode->next = ps->_pSnake;
ps->_pSnake = snewnode;
SerPos(ps->_pSnake->x, ps->_pSnake->y);
printf("%s", "■");
pSnakeNode cur = ps->_pSnake;
while (cur->next->next != NULL)
{
cur = cur->next;
}
SerPos(cur->next->x, cur->next->y);
printf(" ");
free(cur->next);
cur->next = NULL;
}
void SnakeMovement(pSnake ps)//蛇移動
{
pSnakeNode snewnode = BuyNode();
switch (ps->_Dir)
{
case UP:
{
snewnode->x = ps->_pSnake->x;
snewnode->y = ps->_pSnake->y - 1;
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y)
{
EatFood(ps, snewnode);
}
else
{
NoFood(ps, snewnode);
}
}
break;
case DOWN:
{
snewnode->x = ps->_pSnake->x;
snewnode->y = ps->_pSnake->y + 1;
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y)
{
EatFood(ps, snewnode);
}
else
{
NoFood(ps, snewnode);
}
}
break;
case LEFT:
{
snewnode->x = ps->_pSnake->x - 2;
snewnode->y = ps->_pSnake->y;
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y)
{
EatFood(ps, snewnode);
}
else
{
NoFood(ps, snewnode);
}
}
break;
case RIGHT:
{
snewnode->x = ps->_pSnake->x + 2;
snewnode->y = ps->_pSnake->y;
if (snewnode->x == ps->_pFood->x && snewnode->y == ps->_pFood->y)
{
EatFood(ps, snewnode);
}
else
{
NoFood(ps, snewnode);
}
}
break;
}
}
void PrintInformation(pSnake ps)//打印信息
{
SerPos(70, 10);
printf("得分:%d ", ps->_TotalScore);
SerPos(70, 11);
printf("當前所加得分:%d ", ps->_AddScore);
SerPos(70, 12);
printf("↑ ↓ ← → 控制貪喫蛇方向");
SerPos(70, 13);
printf("提示:");
SerPos(70, 14);
printf("F1:加速,F2:減速");
SerPos(70, 15);
printf("空格:暫停");
SerPos(70, 16);
printf("Esc:退出");
}
void KillByWall(pSnake ps)//被牆撞死
{
if (
ps->_pSnake->x< 2 ||
ps->_pSnake->x > 56 ||
ps->_pSnake->y < 1 ||
ps->_pSnake->y > 26
)
{
ps->_status = KILL_BY_WALL;
}
}
void KillBySelf(pSnake ps)//被蛇撞死
{
pSnakeNode cur = ps->_pSnake->next;
while (NULL != cur)
{
if (ps->_pSnake->x == cur->x && ps->_pSnake->y == cur->y)
{
ps->_status = KILL_EY_SELF;
return;
}
cur = cur->next;
}
}
void GameStart(pSnake ps) //遊戲開始
{
WecomeToGame();
CreateMap();
InitSnake(ps);
CreateFood(ps);
ps->_TotalScore = 0;
ps->_AddScore = 10;
ps->_SleepTime = 500;
ps->_Dir = RIGHT;
ps->_status = OK;
}
void GameRun(pSnake ps) //遊戲過程
{
do
{
DirectionOfDdtermination(ps);
SnakeMovement(ps);
PrintInformation(ps);
KillByWall(ps);
KillBySelf(ps);
Sleep(ps->_SleepTime);
} while (OK == ps->_status);
}
void GameEnd(pSnake ps)//遊戲結束
{
if(NORMAL_END == ps->_status)
{
SerPos(22, 13);
printf("遊戲結束!");
}
else if(KILL_BY_WALL == ps->_status)
{
SerPos(22, 13);
printf("撞牆,遊戲結束!");
}
else if (KILL_EY_SELF == ps->_status)
{
SerPos(22, 13);
printf("撞蛇身,遊戲結束!");
}
while (NULL != ps->_pSnake)
{
pSnakeNode del = ps->_pSnake;
ps->_pSnake = ps->_pSnake->next;
free(del);
del = NULL;
}
free(ps->_pFood);
ps->_pFood = NULL;
}
main.c
#include "snake.h"
void test()
{
HideCursor();
srand((unsigned)time(NULL));
Snake snake;
GameStart(&snake);
GameRun(&snake);
GameEnd(&snake);
}
int main()
{
test();
return 0;
}