C++實(shí)現(xiàn)基于控制臺(tái)界面的吃豆子游戲
更新時(shí)間:2015年04月20日 12:14:59 作者:司青
這篇文章主要介紹了C++實(shí)現(xiàn)基于控制臺(tái)界面的吃豆子游戲,實(shí)例分析了吃豆子游戲的原理與C++實(shí)現(xiàn)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
本文實(shí)例講述了C++實(shí)現(xiàn)基于控制臺(tái)界面的吃豆子游戲。分享給大家供大家參考。具體分析如下:
程序運(yùn)行界面如下所示:

ESC鍵可退出游戲。
main.cpp源文件如下:
#include "lib.h"
#pragma once
extern int level;
int main()
{
FOOD food;
WALL wall;
BODY CurPos;
HALL hall;
int iExit = 0;
while(1)
{
if(iExit)
break;
Init(&food,&wall,&CurPos,&hall);
MakeWall(&wall);
while(1)
{
Sleep(200);
int res = Move(&food,&wall,&CurPos);
if(1 == res) //重新開局
break;
else if(-1 == res) //用戶退出
{
iExit = 1;
break;
}
ShowScore(&CurPos,&food);
}
}
return 0;
}
lib.h頭文件如下:
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <time.h>
//標(biāo)識(shí)用戶按下的方向鍵
#define KEY_UP WM_USER + 1
#define KEY_DOWN WM_USER + 2
#define KEY_LEFT WM_USER + 3
#define KEY_RIGHT WM_USER + 4
//標(biāo)識(shí)用戶當(dāng)前運(yùn)動(dòng)方向
#define DIRECTION_UP WM_USER + 5
#define DIRECTION_DOWN WM_USER + 6
#define DIRECTION_LEFT WM_USER + 7
#define DIRECTION_RIGHT WM_USER + 8
//標(biāo)識(shí)要打印的元素類型
#define PRINT_WALL WM_USER + 9
#define PRINT_FOOD WM_USER + 10
#define PRINT_BODY WM_USER + 11
#define PRINT_CLEAN WM_USER + 12
#define KNOCK_WALL WM_USER + 13
#define KNOCK_FOOD WM_USER + 14
struct POS
{
int x;
int y;
};
struct WALL
{
POS pos[9999];
int len;
};
struct FOOD
{
POS pos[8];
int len;
int IsHidden;
};
struct BODY
{
POS pos;
int Direction;
};
struct HALL{
POS pos[200];
int len;
};
void Init(FOOD *pFood,WALL *pWall,BODY *pBody,HALL *pHall);
//進(jìn)行一些初始化操作
void Print(POS *pos,int TYPE,int ix = 0);
//完成打印功能
void MakeWall(WALL *pWall);
//生成墻
void MakeFood(HALL *pHall,FOOD *pFood);
//生成食物
int Move(FOOD *pFood,WALL *pWall,BODY *pBody);
//用戶移動(dòng)
void ShowScore(BODY *pBody,FOOD *pFood);
//顯示等級(jí) 和剩余豆子數(shù)
int IsOver(POS pos1,POS pos2,int TYPE);
//判斷2點(diǎn)是否重合
int IsKnock(WALL *pWall,BODY *pBody,FOOD *pFood,int TYPE);
//判斷是否撞墻、吃到豆子
int GetKey();
//得到用戶按鍵
lib.cpp源文件如下:
#include "lib.h"
#pragma once
HANDLE hMain_Out;
HANDLE hMain_In;
CONSOLE_CURSOR_INFO info;
int iBeans = 0;
int level = 1;
//extern short wall[17][24];
short wall[17][24] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,-1,0,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,
0,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,-1,0,0,0,0,0,-1,-1,-1,0,0,
0,-1,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,-1,0,0,0,0,
0,-1,-1,-1,-1,-1,0,-1,-1,-1,-1,-1,0,-1,0,-1,-1,-1,-1,-1,-1,-1,0,0,
0,-1,0,0,-1,0,-1,0,0,0,0,-1,0,-1,-1,-1,0,0,0,0,0,0,0,0,
0,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0,0,-1,0,0,0,0,0,0,0,0,
0,-1,0,0,0,0,0,0,0,0,0,-1,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,0,
0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,-1,0,0,-1,0,0,0,0,
0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,0,0,-1,0,0,0,0,
0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,-1,-1,-1,-1,0,-1,-1,0,
0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,-1,0,0,
0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,-1,0,0,
0,0,-1,-1,-1,-1,0,0,0,0,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,
0,-1,-1,0,0,0,0,0,0,0,0,0,0,-1,0,0,0,0,0,0,0,0,0,0,
0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
/**********************************
* 功能:
* 判斷用戶與墻相撞或吃到食物
***********************************/
int IsKnock(WALL *pWall,BODY *pBody,FOOD *pFood,int TYPE)
{
if(KNOCK_WALL == TYPE)
{
int i;
for(i = 0 ; i < pWall->len ; ++i)
{
if(IsOver(pBody->pos,pWall->pos[i],KNOCK_WALL))
return 1; //與墻相撞
}
}
else if(KNOCK_FOOD == TYPE)
{
int i;
for(i = 1 ; i <= pFood->len ; ++i)
{
if(IsOver(pFood->pos[i],pBody->pos,KNOCK_WALL))
return i; //與食物相撞
}
}
return 0;
}
/**********************************
* 功能:
* 用戶移動(dòng)
***********************************/
int Move(FOOD *pFood,WALL *pWall,BODY *pBody)
{
BODY prePos = *pBody;
// POS prePos = pBody->pos;
int iKey = GetKey();
if(-1 == iKey) //用戶退出
return -1;
if(iKey)
{
pBody->Direction = iKey + 4;
iKey = 0;
}
if(0 == iKey)
{
if(DIRECTION_UP == pBody->Direction)
--pBody->pos.y;
else if(DIRECTION_DOWN == pBody->Direction)
++pBody->pos.y;
else if(DIRECTION_LEFT == pBody->Direction)
--pBody->pos.x;
else if(DIRECTION_RIGHT == pBody->Direction)
++pBody->pos.x;
}
if(IsKnock(pWall,pBody,pFood,KNOCK_WALL))
{
*pBody = prePos;
return 0;
}
int ix = IsKnock(pWall,pBody,pFood,KNOCK_FOOD);
if(ix)
{
++iBeans;
//刪除初吃掉的食物
int i;
for(i = ix ; i <= (pFood->len - 1) ; ++i)
pFood->pos[i] = pFood->pos[i + 1];
--(pFood->len);
if(0 == pFood->len) //當(dāng)局完成
{
++level;
return 1;
}
}
Print(&prePos.pos,PRINT_CLEAN); //先刪除上一個(gè)輸出
Print(&pBody->pos,PRINT_BODY);
return 0;
}
/**********************************
* 功能:
* 判斷2點(diǎn)是否重合
***********************************/
int IsOver(POS pos1,POS pos2,int TYPE)
{
if(KNOCK_WALL == TYPE) //pos1,the body. pos2,the wall
if((pos1.x == pos2.x && pos1.y == pos2.y) || (pos2.x + 1 == pos1.x && pos2.y == pos1.y))
return 1;
return 0;
}
/**********************************
* 功能:
* 生成墻
***********************************/
void MakeWall(WALL *pWall)
{
int x,y;
int ix = 0;
for(x = 0 ; x <= 16 ; ++x)
{
for(y = 0 ; y <= 23 ; ++y)
{
if(0 == wall[x][y])
{
pWall->pos[ix].x = 2 * y;
pWall->pos[ix].y = x;
Print(&pWall->pos[ix++],PRINT_WALL);
}
}
}
pWall->len = ix; //更新墻的數(shù)量
}
/**********************************
* 功能:
* 完成初始化操作
***********************************/
void Init(FOOD *pFood,WALL *pWall,BODY *pBody,HALL *pHall)
{
//得到控制臺(tái)標(biāo)準(zhǔn)輸入輸出句柄
hMain_Out = GetStdHandle(STD_OUTPUT_HANDLE);
hMain_In = GetStdHandle(STD_INPUT_HANDLE);
//隱藏光標(biāo)
GetConsoleCursorInfo(hMain_Out,&info);
info.bVisible = FALSE;
SetConsoleCursorInfo(hMain_Out,&info);
//初始化結(jié)構(gòu)體
pFood->len = 0;
pWall->len = 0;
pHall->len = 0;
//改變控制臺(tái)大小
system("mode con cols=50 lines=21");
//走廊結(jié)構(gòu)體賦值
int x,y;
int ix = 0;
for(x = 0 ; x < 17 ; ++x)
{
for(y = 0 ; y < 24 ; ++y)
{
if(wall[x][y]) //非墻
{
pHall->pos[ix].x = 2 * y;
pHall->pos[ix++].y = x;
}
}
}
pHall->len = ix;
pBody->pos.x = 2;
pBody->pos.y = 1;
pBody->Direction = DIRECTION_DOWN;
printf("%d %d\n",pHall->pos[0].x,pHall->pos[0].y);
//輸出食物
int i;
MakeFood(pHall,pFood);
for(i = 1 ; i <= 7 ; ++i)
{
Print(&pFood->pos[i],PRINT_FOOD,i);
}
}
/**********************************
* 功能:
* 得到用戶按鍵
***********************************/
int GetKey()
{
if(GetAsyncKeyState(VK_UP))
return KEY_UP;
if(GetAsyncKeyState(VK_DOWN))
return KEY_DOWN;
if(GetAsyncKeyState(VK_LEFT))
return KEY_LEFT;
if(GetAsyncKeyState(VK_RIGHT))
return KEY_RIGHT;
if(GetAsyncKeyState(VK_ESCAPE))
return -1; //用戶退出
return 0;//用戶沒(méi)有有效按鍵
}
/**********************************
* 功能:
* 完成打印功能
***********************************/
void Print(POS *p,int TYPE,int ix)
{
COORD pos;
pos.X = p->x;
pos.Y = p->y;
SetConsoleCursorPosition(hMain_Out,pos);
if(PRINT_WALL == TYPE)
printf("■");
else if(PRINT_FOOD == TYPE)
printf("%d",ix);
else if(PRINT_BODY == TYPE)
printf("\1");
else if(PRINT_CLEAN == TYPE)
printf(" ");
}
/**********************************
* 功能:
* 顯示等級(jí) 和剩余豆子數(shù)
***********************************/
void ShowScore(BODY *pBody,FOOD *pFood)
{
COORD pos;
pos.X = 0;
pos.Y = 18;
SetConsoleCursorPosition(hMain_Out,pos);
printf("\tBeans left : %d | pos : x=%d,y=%d\n",pFood->len,pBody->pos.x,pBody->pos.y);
printf("\t\tLevel : %d",level);
// for(int i = 1 ; i <= pFood->len ; ++i)
// printf("(x=%d,y=%d)",pFood->pos[i].x,pFood->pos[i].y);
}
/**********************************
* 功能:
* 生成食物
***********************************/
void MakeFood(HALL *pHall,FOOD *pFood)
{
srand((unsigned)time(NULL));
int tot;
for(tot = 1 ; tot <= 7 ; ++tot)
{
int ixFood = rand() * pHall->len / RAND_MAX;
pFood->pos[tot].x = pHall->pos[ixFood].x;
pFood->pos[tot].y = pHall->pos[ixFood].y;
}
pFood->len = 7;
}
希望本文所述對(duì)大家的C++程序設(shè)計(jì)有所幫助。
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)飛機(jī)游戲(豪華版)的示例代碼
在前文中已經(jīng)實(shí)現(xiàn)了基礎(chǔ)版和進(jìn)階版的飛機(jī)游戲,但是存在的問(wèn)題很明顯:已經(jīng)發(fā)射出去的子彈會(huì)隨著飛機(jī)位置的實(shí)時(shí)改變而改變,并且不能實(shí)現(xiàn)連發(fā)。本篇文章將利用數(shù)組進(jìn)一步改進(jìn)空戰(zhàn)游戲,感興趣的可以了解一下2022-10-10
C語(yǔ)言中獲取文件狀態(tài)的相關(guān)函數(shù)小結(jié)
這篇文章主要介紹了C語(yǔ)言中獲取文件狀態(tài)的相關(guān)函數(shù)小結(jié),包括stat()函數(shù)和fstat()函數(shù)以及l(fā)stat()函數(shù)的使用,需要的朋友可以參考下2015-09-09
C實(shí)現(xiàn)與 uint64_t 相同功能的類
本文給大家分享的是筆者實(shí)現(xiàn)的仿uint64_t的類,可以用在不支持uint64_t的平臺(tái)上,雖然現(xiàn)在功能還不完善,但是還是分享給大家,也算是給大家一個(gè)思路吧。2015-12-12
C++string中的insert()插入函數(shù)詳解
這篇文章主要介紹了C++string中的insert()插入函數(shù),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03

