用c++寫控制臺貪吃蛇游戲完整步驟
效果圖

要使用的東西。
1.鏈表,2.結(jié)構(gòu)體,3.系統(tǒng)操作。
創(chuàng)建界面
了解界面的生成和輸入
先本地化環(huán)境用于在控制臺輸出中文setlocale(LC_ALL, "");要包含#include <locale.h>
要使用 system函數(shù),要包括頭文件windows.h。
void cj() {
setlocale(LC_ALL, ""); // 設(shè)置本地化環(huán)境
system("mode con cols=100 lines=40"); // 調(diào)整控制臺窗口尺寸
system("pause"); // 防止窗口自動關(guān)閉
}

查看光標發(fā)現(xiàn)光標的長寬不匹配,調(diào)整cols和lines,來判斷那個是長的。

發(fā)現(xiàn)調(diào)整cols后長變了所以cols是窗口的長。
調(diào)整后發(fā)現(xiàn)2個長等于一個寬,所以我們設(shè)置時要設(shè)置2的倍數(shù)長
設(shè)置我們的游戲界面為25*25,加上邊框長乘2,54*27,再加上提示,36長。湊個整
100*30.

發(fā)現(xiàn)輸出都從左上角開始,所以需要定位光標位置來輸出,后續(xù)的內(nèi)容也要運用光標的定位,所以我們要定義一個函數(shù)來表示光標定位。
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
// 獲取控制臺輸出句柄
// 使用GetStdHandle(STD_OUTPUT_HANDLE)獲取標準輸出設(shè)備句柄
COORD pos = {x, y}; // 定義光標位置坐標(左上角為原點(0,0))
SetConsoleCursorPosition(houtput, pos); // 將光標定位到指定坐標
void dw(int x, int y) {
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = {x, y};
SetConsoleCursorPosition(houtput, pos);
}

構(gòu)建歡迎界面,(簡介版)
dw(40, 15);
wprintf(L"歡迎來到貪吃蛇游戲");//用wprintf來輸出寬字符,L表示后面的是寬字符,如中文等。
dw(40, 16);
system("pause");
到下一個界面我們要清空當前界面。
system("cls");來清空界面
system("cls"); // 清屏操作
dw(40, 16); // 調(diào)用dw函數(shù),參數(shù)為40和16
system("pause");// 暫停程序執(zhí)行
下一步設(shè)置我們的提示
按W.S.A.D移動,F(xiàn)4加速,F(xiàn)5減速,space暫停,Esc退出。
定位要的位置輸出數(shù)據(jù),調(diào)整位置讓它 看起居中。
dw(24, 15);
wprintf(L"按W.S.A.D移動,F(xiàn)4加速,F(xiàn)5減速,space暫停,Esc退出。");
dw(40, 16);
printf("加速能得到更高的分數(shù)");
dw(40, 17);
system("pause");
構(gòu)建游戲界面
構(gòu)建蛇的活動范圍墻
發(fā)現(xiàn)高度不夠擴高一點到40;下移墻,在頂上標識提示詞表明游戲界面。

system("cls");
int i = 0, j = 0;
for (i = 3; i < 30; i++)
{
dw(0, i);
for (j = 0; j < 27; j++) {
if (i == 3 || i == 29 || j == 0 || j == 26)
wprintf(L"墻");
else
wprintf(L" ");
}
printf("\n");
}
dw(14, 1);
wprintf(L"游戲界面");
dw(0, 32);
system("pause");
右邊加入提示詞
dw(60, 6); wprintf(L"時間:%.2f", sj); dw(60, 10); wprintf(L"不能撞墻,不能碰到自己"); dw(60, 11); wprintf(L"按W.S.A.D移動\n"); dw(60, 12); wprintf(L"F4加速,F5減速\n"); dw(60, 13); wprintf(L"space暫停,Esc退出"); dw(60, 14); wprintf(L"fish_xk制作");

發(fā)現(xiàn)函數(shù)太長了,分別封裝成函數(shù)。
float sj = 0;
void dw(int x, int y) {
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x,y };
SetConsoleCursorPosition(houtput, pos);
}
void help() {
dw(60, 6);
wprintf(L"時間:%.2f", sj);
dw(60, 10);
wprintf(L"不能撞墻,不能碰到自己");
dw(60, 11);
wprintf(L"按W.S.A.D移動\n");
dw(60, 12);
wprintf(L"F4加速,F5減速\n");
dw(60, 13);
wprintf(L"space暫停,Esc退出");
dw(60, 14);
wprintf(L"fish_xk制作");
system("pause");
}
void ks() {
setlocale(LC_ALL, "");
system("mode con cols=100 lines=40");
dw(40, 15);
wprintf(L"歡迎來到貪吃蛇游戲");
dw(40, 16);
system("pause");
system("cls");
}
void zj() {
dw(24, 15);
wprintf(L"按W.S.A.D移動,F(xiàn)4加速,F(xiàn)5減速,space暫停,Esc退出。");
dw(40, 16);
printf("加速能得到更高的分數(shù)");
dw(40, 17);
system("pause");
system("cls");
}
void yxjm() {
int i = 0, j = 0;
for (i = 3; i < 30; i++)
{
dw(0, i);
for (j = 0; j < 27; j++) {
if (i == 3 || i == 29 || j == 0 || j == 26)
wprintf(L"墻");
else
wprintf(L" ");
}
printf("\n");
}
dw(22, 1);
wprintf(L"游戲界面");
dw(0, 32);
}
void cj() {
ks();
zj();
yxjm();
help();
}這樣就完成了所有的界面的制作。
游戲本體
創(chuàng)建蛇
蛇由一個個節(jié)點組成,用鏈表來創(chuàng)建。重命名一下方便使用
typedef struct snakebody {
struct tcs* next;
int x;
int y;
}snake,st;有蛇,有果子,有速度。用一個結(jié)構(gòu)體來表示。
蛇可以用頭節(jié)點來表示。
果可以看作一個在外的蛇身。
typedef struct tcs{
snake* head;
int v;
snake* guo;
}tcs;還要有狀態(tài),方向,總分數(shù),單個果子的權(quán)重。
typedef struct snakebody{
struct tcs* next;
int x;
int y;
}snake;
enum gamezt {
OK=1,
FAIL,
DIE_BYWALL,
DIE_BYSELF
};
enum snakefx {
UP = 1,
DOWN,
LEFT,
RIGHT
};
typedef struct tcs{
snake* head;//蛇
snake* guo;//果
int v;//速度
enum gamezt zt;//狀態(tài)
enum snakefx fx;//方向
int food_weight;//單個分數(shù)
int score;//總分數(shù)
}tcs;初始化一下蛇的身體。
尾插鏈表來初始蛇身
void push(snake**ps,int x,int y) {//插入蛇的節(jié)點
snake* news = (snake*)malloc(sizeof(snake));//開辟節(jié)點
news->next = NULL;
news->x = x;
news->y = y;
if (*ps == NULL) {
*ps = news;
}
else
{
snake* pos = *ps;
while (pos->next) {//鏈接到末尾
pos = pos->next;
}
pos->next = news;
}
}
snake* body = (snake*)malloc(sizeof(snake));
body = NULL;
int i;
for (i = 22; i < 27; i = i + 1) {
push(&body,22+(i-22)*2, 16);
}
ps->head = body;
print(ps);
void print(snake*ps) {//打印蛇
assert(ps);
snake* cur = ps;
while (cur) {//遍歷鏈表
dw(cur->x, cur->y);
wprintf(L"蛇");
cur = cur->next;
}
}
tcs* cjsnake() {//返回蛇的頭位置
tcs*ps = (tcs*)malloc(sizeof(tcs));
snake* body = (snake*)malloc(sizeof(snake));
body = NULL;
int i;
for (i = 22; i < 27; i = i + 1) {//循環(huán)添加5個節(jié)點
push(&body,22+(i-22)*2, 16);
}
ps->head = body;
print(ps->head);//打印開始的蛇身
cjguo(ps);
ps->v = 200;
ps->zt = OK;
ps->fx = LEFE;
ps->score = 0;
ps->food_weight = 10;
return ps;
}下一步生成果子,要有隨機數(shù)要包含#include<time.h>
設(shè)置隨機數(shù)
srand(time(NULL))
void cjguo(tcs* ps) {
snake* news = (snake*)malloc(sizeof(snake));
news->next = NULL;
snake* cur = ps->head;
ag:
news->x = (rand()%25+1+1)*2;//第一個+1是保證1到25,后一個+1,是不能是墻
news->y = (rand() % 25 + 1+4 );
cur = ps->head;
while (cur){
if (cur->x == news->x && cur->y == news->y)//如果和蛇重疊重新生成。
goto ag;
cur = cur->next;
}
ps->guo = news;
dw(news->x, news->y);
wprintf(L"果");//打印果的位置
}
設(shè)置其他數(shù)據(jù)
ps->v = 200;//速度
ps->zt = OK;//狀態(tài)
ps->fx = LEFT;//方向
ps->score = 0;//成績
ps->food_weight = 10;//每個果子的分數(shù)創(chuàng)建完畢
蛇的行走
while (cur->zt == OK) {
dw(60, 6);
wprintf(L"時間:%.2f秒", sj);
dw(60, 8);
printf("得分:%d", cur->score);
dw(60, 9);
printf("食物分值:%d", cur->food_weight);
snakedong(cur);//行動的函數(shù)
sj+=cur->v/1000.0;//行動時間
Sleep(cur->v);//行動間隔
}設(shè)置循環(huán)判斷游戲狀態(tài)??梢栽偌尤霑r間
設(shè)置程序的休息時間,來實現(xiàn)運動間隔。
要控制程序,需要讀取輸入信息,所以定義一個讀取的宏
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk)&1)?1:0)
讀取一個虛擬鍵盤值,判斷是否按過。
if (KEY_PRESS(0x53) && snake->fx != UP) {//識別W
snake->fx = DOWN;
}
else if (KEY_PRESS(0x57) && snake->fx != DOWN) {//識別S
snake->fx = UP;
}
else if (KEY_PRESS(0x41) && snake->fx != RIGHT) {//識別A
snake->fx = LEFE;
}
else if (KEY_PRESS(0x44) && snake->fx != LEFE) {//識別B
snake->fx = RIGHT;
}
else if (KEY_PRESS(VK_SPACE)) {//識別空格
while (1) {
Sleep(200);
if (KEY_PRESS(VK_SPACE)) {//循環(huán)停止游戲
break;
}
}
}
else if (KEY_PRESS(VK_ESCAPE)) {//識別ESC
snake->zt = END_NORMAL;
}
else if (KEY_PRESS(VK_F4)) {//識別F4
snake->v = snake->v - 10;
snake->food_weight = snake->food_weight + 5;
}
else if (KEY_PRESS(VK_F5)) {//識別F5
snake->v = snake->v + 10;
snake->food_weight = snake->food_weight - 5;
}加入一個全局變量防止加速過頭
根據(jù)蛇的方向來改變蛇的身體坐標
snake* toupush(snake*ps,int x,int y) {//插入頭部,到達的節(jié)點
snake* news = (snake*)malloc(sizeof(snake));
news->next = ps;
news->x = x;
news->y = y;
dw(news->x, news->y);
wprintf(L"蛇");
ps = news;
return ps;
}
snake* pop(snake* ps) {//沒吃到果子,刪除多出來的節(jié)點
snake* tail = ps;
while (tail->next->next) {
tail = tail->next;
}
dw(tail->next->x, tail->next->y);
wprintf(L" ");
free(tail->next);
tail->next = NULL;
return ps;
}
if (snake->fx == UP) {//向上
snake->head=toupush(snake->head, snake->head->x, snake->head->y - 1);
}
else if (snake->fx == DOWN) {//向下
snake->head=toupush(snake->head, snake->head->x, snake->head->y + 1);
}
else if (snake->fx == LEFE) {//向左
snake->head=toupush(snake->head, snake->head->x-2, snake->head->y );
}
else if (snake->fx == RIGHT) {//向右
snake->head=toupush(snake->head, snake->head->x+2, snake->head->y );
}
if (snake->head->x != snake->guo->x || snake->head->y != snake->guo->y)//是否吃到果子
snake->head=pop(snake->head);//沒吃到,刪除尾節(jié)點
else {
free(snake->guo);//釋放果子的節(jié)點
snake->guo = NULL;
cjguo(snake);//重新生成果子
snake->score += snake->food_weight;//加分
}吃到果子就不刪尾,分數(shù)加權(quán)重,沒吃到就刪尾。
編寫失敗條件。
if (snake->head->x == 0 || snake->head->x == 52 || snake->head->y == 4 || snake->head->y == 29)//到達墻體
snake->zt = DIE_BYWALL;//改變狀態(tài)
st* self = snake->head->next;
while (self) {//遍歷自身,看是否相交
if (snake->head->x == self->x && snake->head->y == self->y)
snake->zt = DIE_BYSELF;//如相交更新狀態(tài)
self = self->next;
}結(jié)束后輸出分數(shù)
system("cls");
dw(40, 15);
if (cur->zt == DIE_BYSELF)
wprintf(L"失敗于撞到自己");
if (cur->zt == DIE_BYWALL)
wprintf(L"失敗于撞墻");
if (cur->zt == END_NORMAL)
wprintf(L"正常退出");
dw(40, 16);
wprintf(L"你堅持的時間是%.2f秒", sj);
dw(40, 17);
wprintf(L"你的得分是%d",cur->score);隱藏光標
void gbyc() {
//獲取標準輸出設(shè)備的句柄;
HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);
//定義一個光標結(jié)構(gòu)體
CONSOLE_CURSOR_INFO cursor_info = { 0 };
//獲取houtput句柄相關(guān)的控制臺上的光標信息,存放cursor_info
GetConsoleCursorInfo(houtput, &cursor_info);
//設(shè)置吧光標的占比
cursor_info.bVisible = false;//光標消失
//設(shè)置和houtput句柄相關(guān)的控制臺的光標信息
SetConsoleCursorInfo(houtput, &cursor_info);
}
void ck() {
//創(chuàng)建窗口
setlocale(LC_ALL, "");
COORD pos = { 0,0 };
system("mode con cols=100 lines=40");
system("title.貪吃蛇");
gbyc();
//打印開始界面
}到這里已經(jīng)全部完成了。
總結(jié)
到此這篇關(guān)于用c++寫控制臺貪吃蛇游戲完整步驟的文章就介紹到這了,更多相關(guān)c++寫控制臺貪吃蛇內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++使用CriticalSection實現(xiàn)線程同步實例
這篇文章主要介紹了C++使用CriticalSection實現(xiàn)線程同步實例,是使用CriticalSection對前文實例的擴展,具有一定的參考借鑒價值,需要的朋友可以參考下2014-10-10
在C++17中實現(xiàn)無鎖數(shù)據(jù)結(jié)構(gòu)的方法詳解
在探索?C++17?中的無鎖數(shù)據(jù)結(jié)構(gòu)之前,我們首先需要理解無鎖編程的基本概念及其在現(xiàn)代軟件開發(fā)中的重要性,在這個章節(jié)中,我們將深入探討無鎖編程的概念,以及它如何滿足人類對于更高效、更可靠軟件的本能需求,文中通過代碼示例介紹的非常詳細,感興趣的朋友可以參考下2023-12-12

