一、項目介紹
目前通過控制台終端實作一個貪吃蛇小遊戲,實作遊戲的繪制、更新、控制等功能。
二、實作效果
三、完整代碼
下面貼出的代碼在Windows系統上編譯運作,需要使用conio.h頭檔案中的getch()函數來擷取鍵盤輸入,用于控制蛇的移動。可以通過按下'w'、's'、'a'、'd'四個鍵來分别控制蛇的向上、向下、向左、向右移動。同時還有一個暫停函數Pause(),用于控制蛇的移動速度,可以根據需要調整暫停時間。
設計思路:
程式定義了一些常量,包括遊戲界面的寬度和高度、不同狀态下的符号表示等,并在全局變量中定義了蛇頭、蛇身、食物等的位置、得分、長度、行進方向等參數。同時還定義了一個二維字元數組board,用于表示整個遊戲界面。
在InitGame()函數中進行遊戲初始化,設定遊戲界面的邊框、蛇頭、蛇身、随機生成食物等操作。
DrawGame()函數用于繪制遊戲畫面,将board數組中的字元逐行輸出,并在末尾輸出得分。UpdateGame()函數用于更新遊戲狀态,包括蛇的移動、遊戲結束判斷等。CheckGameOver()函數用于檢查遊戲是否結束,包括牆壁碰撞、蛇身碰撞、得分達到上限等情況。GenerateFood()函數用于随機生成食物位置,調用rand()函數擷取随機數并進行判斷。Move()函數用于蛇的移動,根據目前行進方向進行移動。Control()函數用于使用者操作,讀取鍵盤輸入并更新蛇的行進方向。Pause()函數用于控制遊戲速度,通過調用Sleep()函數控制暫停時間。GameOver()函數用于輸出最終得分和遊戲結束資訊,并直接退出程式。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h> //需要使用getch()函數
#include <time.h> //需要使用time()函數
#include <Windows.h>
#define WIDTH 40 //遊戲界面寬度
#define HEIGHT 20 //遊戲界面高度
//定義符号常量,表示各種不同的狀态
#define BLANK ' ' //空白
#define WALL '*' //牆壁
#define SNAKEHEAD '@' //蛇頭
#define SNAKEBODY 'o' //蛇身
#define FOOD '#39; //食物
//定義坐标結構體
struct Position
{
int x; //橫坐标
int y; //縱坐标
};
//定義枚舉類型,表示遊戲狀态
enum GameState
{
Over = -1, //遊戲結束
Running = 0, //遊戲進行中
Win = 1 //遊戲勝利
};
int score = 0; //得分
struct Position head; //蛇頭位置
struct Position body[WIDTH * HEIGHT]; //蛇身位置
struct Position food; //食物位置
char board[WIDTH][HEIGHT]; //遊戲界面
int length = 3; //蛇身長度,初始為3
int direction = 0; //蛇的行進方向,0表示向右,1表示向下,2表示向左,3表示向上
//函數聲明
void InitGame(); //初始化遊戲界面和蛇的初始位置
void DrawGame(); //繪制遊戲畫面
void UpdateGame(); //更新遊戲狀态
enum GameState CheckGameOver(); //檢查遊戲是否結束
void GenerateFood(); //生成随機食物
void Move(); //蛇的移動
void Control(); //使用者操作,控制蛇的移動
void Pause(); //遊戲暫停
void GameOver(); //遊戲結束
int main()
{
srand(time(NULL)); //用目前時間作為随機數種子,使每次運作的随機食物位置不同
InitGame(); //初始化遊戲
DrawGame(); //繪制遊戲畫面
while (1)
{
UpdateGame(); //更新遊戲
DrawGame(); //繪制遊戲畫面
Control(); //使用者操作,控制蛇的移動
Pause(); //遊戲暫停
}
return 0;
}
//初始化遊戲界面和蛇的初始位置
void InitGame()
{
for (int i = 0; i < WIDTH; i++)
{
for (int j = 0; j < HEIGHT; j++)
{
if (i == 0 || j == 0 || i == WIDTH - 1 || j == HEIGHT - 1) //設定牆壁
board[i][j] = WALL;
else
board[i][j] = BLANK; //其他為空白
}
}
//初始化蛇的位置,由一個蛇頭和兩節身體組成,初始位置在遊戲界面的中心
head.x = WIDTH / 2;
head.y = HEIGHT / 2;
board[head.x][head.y] = SNAKEHEAD;
body[0].x = head.x - 1;
body[0].y = head.y;
board[body[0].x][body[0].y] = SNAKEBODY;
body[1].x = head.x - 2;
body[1].y = head.y;
board[body[1].x][body[1].y] = SNAKEBODY;
GenerateFood(); //生成随機食物
}
//繪制遊戲畫面
void DrawGame()
{
system("cls"); //清屏,避免前一幀的内容殘留
for (int i = 0; i < HEIGHT; i++)
{
for (int j = 0; j < WIDTH; j++)
{
printf("%c", board[j][i]); //輸出一個字元
}
printf("\n"); //每行輸出完後,換行
}
printf("Score: %d\n", score); //輸出得分
}
//更新遊戲狀态
void UpdateGame()
{
Move(); //蛇的移動
enum GameState state = CheckGameOver(); //檢查遊戲是否結束
if (state != Running) //如果遊戲結束,則進行相應操作
{
GameOver();
}
}
//檢查遊戲是否結束
enum GameState CheckGameOver()
{
//蛇頭碰到牆壁,遊戲結束
if (board[head.x][head.y] == WALL)
return Over;
//蛇頭碰到蛇身,遊戲結束
for (int i = 0; i < length; i++)
{
if (head.x == body[i].x && head.y == body[i].y)
return Over;
}
//吃到食物後,更新分數和蛇的長度,并生成新的食物
if (head.x == food.x && head.y == food.y)
{
score += 10;
length++;
GenerateFood();
}
//蛇的長度達到遊戲界面總格子數減去牆壁的個數,也就是蛇填滿遊戲界面,遊戲勝利
if (length == (WIDTH - 2) * (HEIGHT - 2) - 4)
return Win;
return Running; //遊戲繼續進行
}
//生成随機食物
void GenerateFood()
{
int x, y;
do
{
x = rand() % (WIDTH - 2) + 1; //随機x坐标,排除在邊框上的牆壁位置
y = rand() % (HEIGHT - 2) + 1; //随機y坐标,排除在邊框上的牆壁位置
} while (board[x][y] != BLANK); //如果随機到的位置不為空白,則重新随機
food.x = x;
food.y = y;
board[x][y] = FOOD; //在随機位置生成食物
}
//蛇的移動
void Move()
{
//更新蛇身的位置,從後往前移動
for (int i = length - 1; i > 0; i--)
{
body[i].x = body[i - 1].x;
body[i].y = body[i - 1].y;
board[body[i].x][body[i].y] = SNAKEBODY;
}
//更新蛇頭的位置
switch (direction) //根據蛇頭行進方向進行移動
{
case 0: //向右
head.x++;
break;
case 1: //向下
head.y++;
break;
case 2: //向左
head.x--;
break;
case 3: //向上
head.y--;
break;
}
board[head.x][head.y] = SNAKEHEAD; //更新蛇頭位置
board[body[length - 1].x][body[length - 1].y] = BLANK; //清除蛇尾
}
//使用者操作,控制蛇的移動
void Control()
{
if (kbhit()) //如果有按鍵按下
{
char ch = getch(); //擷取按鍵字元
switch (ch)
{
case 'w':
if (direction != 1) //避免蛇頭掉頭
direction = 3;
break;
case 's':
if (direction != 3)
direction = 1;
break;
case 'a':
if (direction != 0)
direction = 2;
break;
case 'd':
if (direction != 2)
direction = 0;
break;
case 'q':
GameOver(); //按下'q'鍵退出遊戲
break;
}
}
}
//遊戲暫停
void Pause()
{
Sleep(150); //每次循環暫停一段時間,控制蛇的移動速度
}
//遊戲結束
void GameOver()
{
system("cls"); //清屏,輸出最終得分和遊戲結束資訊
printf("Game over!\n");
printf("Your score: %d\n", score);
exit(0); //直接退出程式
}