貪喫蛇好像是學習C/C++進階的一個好項目,這裏轉載一篇可以正常運行的程序,源碼是VS2008編寫,用高版本亦可運行如我用的VS2013。程序運行沒有問題,但是不完美,整個窗口在重新繪製的時候會有閃爍,貪喫蛇對於方向鍵的響應滯後等,後面有時間我再在此基礎上完善吧。
原文地址:https://www.oschina.net/code/snippet_1265060_27744
程序分爲三個部分,一個Snake_Class.h 頭文件、一個Snake_Class.cpp源文件和一個main.cpp主程序,代碼如下。
Snake_Class.h頭文件程序:
#ifndef SNAKE
#define SNAKE
#include<windows.h>
#include<vector>
#include<string>
//標記界面和菜單項的ID
enum ID_ { ID_1 = 1, ID_2, ID_3, ID_4, ID_5, ID_6, ID_7 };
//標記初級,中級,高級三種遊戲等級
enum Rank_ { first = 150, middle = 100, high = 50 };
//貪喫蛇結構
struct Snake_data{
bool state; //標記蛇狀態
UINT Snake_size; //標記蛇長度
std::vector<COORD> Snake_coord; //蛇的當前座標
COORD food_coord; //食物座標
UINT rank; //標記等級
UINT mark; //分數
UINT key; //記錄按鍵方向
ID_ ID_interface; //標記當前停留界面ID
short ID_option; //標記被選中菜單的ID
bool Flag; //標記刷新
};
//貪喫蛇類
class Snake_class{
public:
Snake_class(){}
Snake_class(Snake_data *data) : pSnake(data){}
void ShowMenu(); //顯示菜單
void StartGame(); //開始遊戲
void ShowPause(); //顯示暫停界面
void SaveRecord(); //保存記錄
void ShowRank(); //顯示等級
void ShowRecord(); //顯示存檔記錄列表
bool Read(size_t); //讀取記錄
void ShowArmory(); //顯示英雄榜
void Die(); //死亡界面
size_t Create_file(); //存儲文件
private:
void JudgeDie(); //判斷死亡
bool Jesus(); //上榜判斷
void ShowSnake(COORD&); //顯示蛇
void ShowPointer(COORD, std::string); //顯示指針
void Show_not(); //顯示無數據
Snake_data *pSnake;
};
#endif;
Snake_Class.cpp程序:
#include"Snake_Class.h"
#include<iostream>
#include<fstream>
#include<ctime>
#include<cstdlib>
//獲取緩衝區句柄
static const HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
static CONSOLE_SCREEN_BUFFER_INFO info;
//保存蛇的記錄數據文件
static const char *Snake_Record[] = { "d://SnakeRecord//Snake1.txt",
"d://SnakeRecord//Snake2.txt",
"d://SnakeRecord//Snake3.txt",
"d://SnakeRecord//Snake4.txt",
"d://SnakeRecord//Snake5.txt" };
static const char *S_Armory[] = { "d://SnakeRecord//Armory1.txt",
"d://SnakeRecord//Armory2.txt",
"d://SnakeRecord//Armory3.txt" };
//顯示主菜單(完成已測試)
void Snake_class::ShowMenu(){
//獲取緩衝區相關信息
GetConsoleScreenBufferInfo(handle, &info);
char *str[] = { "開 始 遊 戲",
"難 度 等 級",
"讀 取 存 檔",
"英 雄 榜",
"退 出 遊 戲" };
//輸出菜單選項
short y = 3;
COORD cd = { info.srWindow.Right / 2 - 5, y };
for (size_t n = 0; n<sizeof(str) / sizeof(*str); ++n){
SetConsoleCursorPosition(handle, cd);
std::cout << *(str + n);
cd.Y += 2;
}
//判斷指針指向哪個菜單選項
cd.X -= 2;
cd.Y = y;
switch (pSnake->ID_option){
case ID_1:
break;
case ID_2:
cd.Y = y + 2; break;
case ID_3:
cd.Y = y + 4; break;
case ID_4:
cd.Y = y + 6; break;
case ID_5:
cd.Y = y + 8; break;
}
ShowPointer(cd, pSnake->Flag ? std::string(" ") : std::string("><"));
}
//開始遊戲(完成待測試)
void Snake_class::StartGame(){
COORD cd;
//判斷是否已有食物
if (!pSnake->food_coord.X){
srand((unsigned int)time(NULL));
while (1){
//限制食物出現的座標不與圍牆相同
++(cd.X = rand() % 78);
++(cd.Y = rand() % 18);
//判斷食物座標是否與蛇身吻合
std::vector<COORD>::iterator ite;
for (ite = pSnake->Snake_coord.begin(); ite != pSnake->Snake_coord.end(); ++ite){
if (ite->X == cd.X && ite->Y == cd.Y)
break;
}
if (ite == pSnake->Snake_coord.end()){
pSnake->food_coord.X = cd.X;
pSnake->food_coord.Y = cd.Y;
break;
}
}
}
SetConsoleCursorPosition(handle, pSnake->food_coord);
std::cout << "*";
//判定按鍵方向
cd.X = pSnake->Snake_coord.begin()->X;
cd.Y = pSnake->Snake_coord.begin()->Y;
switch (pSnake->key){
case VK_UP:
--cd.Y; break;
case VK_DOWN:
++cd.Y; break;
case VK_LEFT:
--cd.X; break;
case VK_RIGHT:
++cd.X; break;
}
ShowSnake(cd);
JudgeDie();
}
//顯示暫停界面(完成已測試)
void Snake_class::ShowPause(){
COORD cd = { info.srWindow.Right / 2 - 10, info.srWindow.Bottom / 5 };
SetConsoleCursorPosition(handle, cd);
std::cout << "遊 戲 暫 停 中 ......";
char *str[] = { "繼 續 遊 戲",
"保 存 遊 戲",
"退 出 遊 戲" };
//輸出菜單選項
short X = info.srWindow.Right / 3;
cd.X = X / 2 - 5;
cd.Y = info.srWindow.Bottom / 3 * 2 - 4;
for (size_t i = 0; i<sizeof(str) / sizeof(*str); ++i){
SetConsoleCursorPosition(handle, cd);
std::cout << *(str + i);
cd.X += X;
}
//判斷指針應指向的菜單選項
switch (pSnake->ID_option){
case ID_1:
cd.X = X / 2 - 7; break;
case ID_2:
cd.X = X / 2 + X - 7; break;
case ID_3:
cd.X = X / 2 + 2 * X - 7; break;
}
ShowPointer(cd, pSnake->Flag ? std::string(" ") : std::string("><"));
}
//保存記錄(完成未測試)
void Snake_class::SaveRecord(){
std::ofstream outopen;
outopen.open(*(Snake_Record + Create_file()));
if (!outopen){
std::cerr << "\n打開文件失敗!\n";
exit(0);
}
//保存記錄到文件中,前面加"0"是爲了後面檢測是否文件爲空使用
outopen << "0 " << pSnake->Snake_size << " ";
for (std::vector<COORD>::iterator ite = pSnake->Snake_coord.begin();
ite != pSnake->Snake_coord.end(); ++ite)
outopen << ite->X << " " << ite->Y << " ";
outopen << pSnake->rank << " " << pSnake->mark << " " << pSnake->key;
outopen.close();
//輸出保存成功
COORD cd = { info.srWindow.Right / 2 - 4, info.srWindow.Bottom / 3 * 2 - 1 };
SetConsoleCursorPosition(handle, cd);
std::cout << "保存成功!\a";
}
//顯示等級(已測試)
void Snake_class::ShowRank(){
COORD cd = { info.srWindow.Right / 2 - 6, info.srWindow.Bottom / 3 + 2 };
char *str[] = { "初 級",
"中 級",
"高 級" };
for (size_t i = 0; i<sizeof(str) / sizeof(*str); ++i){
SetConsoleCursorPosition(handle, cd);
std::cout << *(str + i);
cd.Y += 2;
}
//判斷指針所停留的選項
cd.X -= 2;
cd.Y = info.srWindow.Bottom / 3 + 2;
switch (pSnake->ID_option){
case ID_1:
break;
case ID_2:
cd.Y += 2; break;
case ID_3:
cd.Y += 4; break;
}
ShowPointer(cd, pSnake->Flag ? std::string(" ") : std::string("><"));
}
//顯示存檔記錄(已測試)
void Snake_class::ShowRecord(){
COORD cd = { info.srWindow.Right / 2 - 12, 8 };
//輸出記錄
std::ifstream inopen;
SetConsoleCursorPosition(handle, cd);
for (size_t i = 0; i<sizeof(Snake_Record) / sizeof(*Snake_Record); ++i){
inopen.open(*(Snake_Record + i));
if (!inopen || (inopen.get() == EOF && i == 0)){
Show_not();
pSnake->ID_option = ID_7;//第7個選項標記,在按回車時檢測下
return;
}
if (inopen.get() != EOF){
UINT _rank, _mark;
inopen >> _mark;
++(_mark *= 2);
while (_mark--)
inopen >> _rank;
inopen >> _mark;
switch (_rank){
case first:
std::cout << "初級"; break;
case middle:
std::cout << "中級"; break;
case high:
std::cout << "高級"; break;
}
std::cout << "\t\t\t " << _mark;
}
else
std::cout << " ---\t\t\t ---";
cd.Y += 2;
SetConsoleCursorPosition(handle, cd);
inopen.close();
inopen.clear();//重置流狀態
}
std::cout << "\t 返 回 菜 單";
cd.X = info.srWindow.Right / 2 - 4;
cd.Y = 4;
SetConsoleCursorPosition(handle, cd);
std::cout << "存 檔 記 錄";
cd.X -= 10;
cd.Y += 2;
SetConsoleCursorPosition(handle, cd);
std::cout << "遊戲等級\t\t當前分數";
//輸出指針
cd.X = info.srWindow.Right / 2 - 14;
cd.Y = 8;
switch (pSnake->ID_option){
case ID_1:
break;
case ID_2:
cd.Y += 2; break;
case ID_3:
cd.Y += 4; break;
case ID_4:
cd.Y += 6; break;
case ID_5:
cd.Y += 8; break;
case ID_6:
cd.Y += 10; break;
}
ShowPointer(cd, pSnake->Flag ? std::string(" ") : std::string("><"));
}
//讀取記錄
bool Snake_class::Read(size_t i){
std::ifstream inopen(*(Snake_Record + i));
if (inopen.get() == EOF){
std::cout << "\a";
inopen.close();
return false;
}
inopen >> pSnake->Snake_size;
COORD cd;
pSnake->Snake_coord.clear();
for (int n = 1; n <= pSnake->Snake_size; ++n){
inopen >> cd.X >> cd.Y;
pSnake->Snake_coord.push_back(cd);
}
inopen >> pSnake->rank >> pSnake->mark >> pSnake->key;
inopen.close();
inopen.clear();
return true;
}
//顯示英雄榜(未測試)
void Snake_class::ShowArmory(){
short nt = 0;
COORD cd = { info.srWindow.Right / 3, info.srWindow.Bottom / 3 };
std::ifstream inopen;
for (size_t i = 0; i<sizeof(S_Armory) / sizeof(*S_Armory); ++i){
UINT _rank = 0, _mark = 0;
inopen.open(*(S_Armory + i));
if (!inopen){
++nt;
continue;
}
inopen >> _rank >> _mark;
switch (_rank){
case first:
SetConsoleCursorPosition(handle, cd);
std::cout << "小牛 :初級\t\t " << _mark;
break;
case middle:
cd.Y += 2;
SetConsoleCursorPosition(handle, cd);
std::cout << "中牛 :中級\t\t " << _mark;
break;
case high:
cd.Y += 2;
SetConsoleCursorPosition(handle, cd);
std::cout << "大牛 :高級\t\t " << _mark;
break;
}
inopen.close();
inopen.clear();
}
if (nt == 3){
Show_not();
return;
}
cd.X = info.srWindow.Right / 2 - 3;
cd.Y = 4;
SetConsoleCursorPosition(handle, cd);
std::cout << "英 雄 榜";
cd.X -= 10;
cd.Y += 2;
SetConsoleCursorPosition(handle, cd);
std::cout << "\t等 級\t\t分 數";
cd.Y = info.srWindow.Bottom - 7;
SetConsoleCursorPosition(handle, cd);
std::cout << "按回車返回主菜單........";
}
//死亡界面(未測試)
void Snake_class::Die(){
COORD cd = { info.srWindow.Right / 2 - 10, info.srWindow.Bottom / 5 };
SetConsoleCursorPosition(handle, cd);
std::cout << " 您 已 x_x 了 !";
char *str[] = { "返 回 菜 單",
"退 出 遊 戲" };
//輸出菜單選項
short X = info.srWindow.Right / 2;
cd.X = X / 2 - 5;
cd.Y = info.srWindow.Bottom / 3 * 2 - 4;
for (size_t i = 0; i<sizeof(str) / sizeof(*str); ++i){
SetConsoleCursorPosition(handle, cd);
std::cout << *(str + i);
cd.X += X;
}
//判斷指針應指向的菜單選項
switch (pSnake->ID_option){
case ID_1:
cd.X = X / 2 - 7; break;
case ID_2:
cd.X = X / 2 + X - 7; break;
}
ShowPointer(cd, pSnake->Flag ? std::string(" ") : std::string("><"));
if (Jesus()){
cd.X = X / 2;
cd.Y = info.srWindow.Bottom / 3;
SetConsoleCursorPosition(handle, cd);
std::cout << "喲...這分? ╮(╯▽╰)╭ 也能上榜。。。!";
cd.Y += 2;
SetConsoleCursorPosition(handle, cd);
std::cout << "上榜等級:";
switch (pSnake->rank){
case first:
std::cout << "初級"; break;
case middle:
std::cout << "中級"; break;
case high:
std::cout << "高級"; break;
}
std::cout << "\t上榜分數:" << pSnake->mark;
}
}
//存儲記錄文件(完成未測試)
size_t Snake_class::Create_file(){
std::ifstream inopen;
size_t fn = 0, fc = 0, iend = sizeof(Snake_Record) / sizeof(*Snake_Record);
//判斷文件是否存在或文件已被存滿
for (size_t i = 0; i<iend; ++i){
inopen.open(*(Snake_Record + i));
if (!inopen) ++fn;
else if (inopen.get() == EOF){
inopen.close();
return i;
}
else { ++fc; inopen.close(); }
}
if (fn == iend || fc == iend){
std::ofstream outopen;
//創建文本
for (size_t i = 0; i<iend; ++i){
outopen.open(*(Snake_Record + i));
outopen.close();
}
}
//返回打開成功的文件索引
return 0;
}
//判斷死亡(未測試)
void Snake_class::JudgeDie(){
std::vector<COORD>::iterator hbeg = pSnake->Snake_coord.begin(),
beg = hbeg + 1;
while (beg != pSnake->Snake_coord.end()){
if (beg->X == hbeg->X && beg->Y == hbeg->Y){
pSnake->state = FALSE;
return;
}
++beg;
}
COORD cd;
if (hbeg->X <= 0 || hbeg->Y <= 0 ||
hbeg->X >= info.srWindow.Right || hbeg->Y >= info.srWindow.Bottom - 5){
if (pSnake->Snake_size < 40){
pSnake->state = FALSE;
return;
}
//如果達到了40級可以穿牆
switch (pSnake->key){
case VK_UP:
cd.X = pSnake->Snake_coord.begin()->X;
cd.Y = info.srWindow.Bottom - 6;
break;
case VK_DOWN:
cd.X = pSnake->Snake_coord.begin()->X;
cd.Y = 1;
break;
case VK_LEFT:
cd.X = info.srWindow.Right - 1;
cd.Y = pSnake->Snake_coord.begin()->Y;
break;
case VK_RIGHT:
cd.X = 1;
cd.Y = pSnake->Snake_coord.begin()->Y;
break;
}
ShowSnake(cd);
}
}
//上榜判斷(未測試)
bool Snake_class::Jesus(){
std::ifstream inopen;
size_t i;
//判斷相應等級打開相應文件
switch (pSnake->rank){
case first:
i = 0; break;
case middle:
i = 1; break;
case high:
i = 2; break;
}
inopen.open(*(S_Armory + i));
if (inopen){
UINT _mark;
inopen >> _mark >> _mark;
if (_mark >= pSnake->mark){
inopen.close();
return FALSE;
}
}
std::ofstream outopen(*(S_Armory + i));//創建文件並輸入
if (!outopen){
std::cerr << "打開英雄榜文件出錯" << std::endl;
exit(0);
}
outopen << pSnake->rank << " " << pSnake->mark;
outopen.close();
return TRUE;
}
//顯示蛇(未測試)
void Snake_class::ShowSnake(COORD& cd){
if (cd.X == pSnake->food_coord.X && cd.Y == pSnake->food_coord.Y){
//在最後添加一個座標
pSnake->Snake_coord.push_back(*(pSnake->Snake_coord.rbegin()));
pSnake->food_coord.X = pSnake->food_coord.Y = 0;//標誌食物已被喫掉
++pSnake->mark;
++pSnake->Snake_size;
}
COORD cod;
cod.X = (pSnake->Snake_coord.rbegin())->X;
cod.Y = (pSnake->Snake_coord.rbegin())->Y;
std::vector<COORD>::reverse_iterator rbeg = pSnake->Snake_coord.rbegin();
while (rbeg != pSnake->Snake_coord.rend() - 1){
rbeg->X = (rbeg + 1)->X;
rbeg->Y = (rbeg + 1)->Y;
++rbeg;
}
//顯示蛇
pSnake->Snake_coord.begin()->X = cd.X;
pSnake->Snake_coord.begin()->Y = cd.Y;
for (std::vector<COORD>::iterator beg = pSnake->Snake_coord.begin();
beg != pSnake->Snake_coord.end(); ++beg){
SetConsoleCursorPosition(handle, *beg);
std::cout << "*";
}
SetConsoleCursorPosition(handle, cod);
std::cout << " ";
}
//顯示指針(完成)
inline void Snake_class::ShowPointer(COORD cd, std::string str){
SetConsoleCursorPosition(handle, cd);
std::cout << str[0];
pSnake->ID_interface != ID_6 ? cd.X += 14 : cd.X = info.srWindow.Right / 3 * 2 + 3;
SetConsoleCursorPosition(handle, cd);
std::cout << str[1];
}
//顯示無數據(完成)
inline void Snake_class::Show_not(){
COORD cd = { info.srWindow.Right / 2 - 4, info.srWindow.Bottom / 2 };
SetConsoleCursorPosition(handle, cd);
std::cout << "無 數 據 !";
cd.X -= 6;
cd.Y += 2;
SetConsoleCursorPosition(handle, cd);
std::cout << "請按回車返回主菜單......";
}
main函數主程序:
#include<iostream>
#include<direct.h>
#include"Snake_Class.h"
#define _max(ID) --snake.ID_option < ID_1?ID : snake.ID_option
#define _min(ID) ++snake.ID_option > ID?ID_1 : snake.ID_option
//鉤子過程
LRESULT CALLBACK _HookProc(int, WPARAM, LPARAM);
void Wall(); //畫牆函數
void Frame(); //畫框函數
void initialize_();//初始化蛇結構數據
Snake_data snake;
Snake_class csnake(&snake);
static HANDLE handle; //控制檯句柄
//控制檯信息結構
static CONSOLE_SCREEN_BUFFER_INFO info;
int main(){
using namespace std;
//獲取輸出緩衝區句柄
handle = GetStdHandle(STD_OUTPUT_HANDLE);
//獲取相關信息(主要是緩衝區大小)
GetConsoleScreenBufferInfo(handle, &info);
initialize_();
_mkdir("d://SnakeRecord"); //創建目錄
CONSOLE_CURSOR_INFO cursor; //光標結構
cursor.dwSize = 10;
cursor.bVisible = 0; //0爲隱藏光標
SetConsoleCursorInfo(handle, &cursor);//設置隱藏光標函數
//csnake.ShowMenu();
HHOOK hook;
MSG msg;
//相應的鉤子有相應的過程函數MSDN中可看,安裝鍵盤鉤子
hook = SetWindowsHookEx(WH_KEYBOARD_LL, _HookProc, GetModuleHandle(NULL), 0);
while (1){
//判斷蛇是否還活着
Wall();
if (!snake.state && snake.ID_interface == ID_2){
//csnake.Die();
snake.ID_interface = ID_4;
Frame();
}
if (snake.ID_interface == ID_2){
csnake.StartGame();
Sleep(snake.rank);
}
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){//循環接收消息
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
UnhookWindowsHookEx(hook); //卸載鉤子
return 0;
}
//定義鉤子過程(未完成)
LRESULT CALLBACK _HookProc(int message, WPARAM wParam, LPARAM lParam){
//判斷是否彈起按鍵消息
if (wParam == WM_KEYUP){
bool state = true;
switch (((LPKBDLLHOOKSTRUCT)lParam)->vkCode){//lParam:指向一個結構
//按下上鍵
case VK_UP:
switch (snake.ID_interface){
case ID_1:
snake.Flag = true;
csnake.ShowMenu();
snake.Flag = false;
snake.ID_option = _max(ID_5);
csnake.ShowMenu();
break;
case ID_2:
if (snake.key != VK_DOWN && snake.key != VK_UP){
snake.key = VK_UP;
}
break;
case ID_5:
snake.Flag = true;
csnake.ShowRank();
snake.ID_option = _max(ID_3);
snake.Flag = false;
csnake.ShowRank();
break;
case ID_6:
snake.Flag = true;
csnake.ShowRecord();
snake.ID_option = _max(ID_6);
snake.Flag = false;
csnake.ShowRecord();
break;
}
break;
//按下下鍵
case VK_DOWN:
switch (snake.ID_interface){
case ID_1:
snake.Flag = true;
csnake.ShowMenu();
snake.Flag = false;
snake.ID_option = _min(ID_5);
csnake.ShowMenu();
break;
case ID_2:
if (snake.key != VK_UP && snake.key != VK_DOWN){
snake.key = VK_DOWN;
}
break;
case ID_5:
snake.Flag = true;
csnake.ShowRank();
snake.ID_option = _min(ID_3);
snake.Flag = false;
csnake.ShowRank();
break;
case ID_6:
snake.Flag = true;
csnake.ShowRecord();
snake.ID_option = _min(ID_6);
snake.Flag = false;
csnake.ShowRecord();
break;
}
break;
//按下左鍵
case VK_LEFT:
switch (snake.ID_interface){
case ID_2:
if (snake.key != VK_RIGHT && snake.key != VK_LEFT){
snake.key = VK_LEFT;
}
break;
case ID_3:
snake.Flag = true;
csnake.ShowPause();
snake.ID_option = _max(ID_3);
snake.Flag = false;
csnake.ShowPause();
break;
case ID_4:
snake.Flag = true;
csnake.Die();
snake.ID_option = _max(ID_2);
snake.Flag = false;
csnake.Die();
break;
}
break;
//按下右鍵
case VK_RIGHT:
switch (snake.ID_interface){
case ID_2:
if (snake.key != VK_LEFT && snake.key != VK_RIGHT){
snake.key = VK_RIGHT;
}
break;
case ID_3:
snake.Flag = true;
csnake.ShowPause();
snake.ID_option = _min(ID_3);
snake.Flag = false;
csnake.ShowPause();
break;
case ID_4:
snake.Flag = true;
csnake.Die();
snake.ID_option = _min(ID_2);
snake.Flag = false;
csnake.Die();
break;
}
break;
//按下空格和回車鍵
case VK_SPACE:
case VK_RETURN:
system("cls");
switch (snake.ID_interface){
case ID_1://主菜單界面
switch (snake.ID_option){
case ID_1:
snake.ID_interface = ID_2;//開始遊戲界面ID
csnake.StartGame();
break;
case ID_2:
snake.ID_interface = ID_5;//等級界面
snake.ID_option = ID_1;
Frame();
//csnake.ShowRank();
break;
case ID_3:
snake.ID_interface = ID_6;//讀取記錄界面
snake.ID_option = ID_1;
csnake.ShowRecord();
break;
case ID_4:
snake.ID_interface = ID_7;//英雄榜界面
csnake.ShowArmory();
break;
case ID_5:
state = false;
break;
}
break;
case ID_2://遊戲界面
snake.ID_interface = ID_3;
snake.ID_option = ID_1;
Frame();
//csnake.ShowPause();
break;
case ID_3://暫停界面
switch (snake.ID_option){
case ID_1:
snake.ID_interface = ID_2;
csnake.StartGame();
break;
case ID_2:
csnake.SaveRecord();
break;
case ID_3:
state = false;
break;
}
break;
case ID_4://死亡界面
switch (snake.ID_option){
case ID_1:
snake.ID_interface = ID_1;
snake.ID_option = ID_1;
initialize_();
csnake.ShowMenu();
break;
case ID_2:
state = false;
break;
}
break;
case ID_5://等級界面
switch (snake.ID_option){
case ID_1:
snake.rank = first;
break;
case ID_2:
snake.rank = middle;
break;
case ID_3:
snake.rank = high;
break;
}
snake.ID_interface = ID_1;
snake.ID_option = ID_1;
csnake.ShowMenu();
break;
case ID_6://讀取界面
size_t id;
switch (snake.ID_option){
case ID_1:
id = 0; break;
case ID_2:
id = 1; break;
case ID_3:
id = 2; break;
case ID_4:
id = 3; break;
case ID_5:
id = 4; break;
}
//進行讀取文件
if (snake.ID_option != ID_6&&snake.ID_option != ID_7){
initialize_();
if (csnake.Read(id)){
snake.ID_interface = ID_2;
csnake.StartGame();
}
else snake.ID_interface = ID_6;
}
else {
snake.ID_interface = ID_1;
snake.ID_option = ID_1;
csnake.ShowMenu();
}
break;
case ID_7://英雄榜界面
snake.ID_interface = ID_1;
snake.ID_option = ID_1;
csnake.ShowMenu();
break;
}
if (!state){
COORD cd = { info.srWindow.Right / 4, info.srWindow.Bottom / 5 * 4 };
SetConsoleCursorPosition(handle, cd);
exit(0);
}
snake.ID_option = ID_1;
break;
}
}
//消息傳給下個鉤子
return CallNextHookEx(NULL, message, wParam, lParam);
}
//畫牆函數和調用相應界面(已測試完成)
void Wall(){
short i;
COORD coord = { 0, 0 }; //座標結構
//繪牆
SetConsoleCursorPosition(handle, coord);
for (i = 0; i <= info.srWindow.Right; ++i)
std::cout << "#";
coord.X = info.srWindow.Right;
coord.Y = 1;
for (i = 1; i<info.srWindow.Bottom; ++i){
SetConsoleCursorPosition(handle, coord);
std::cout << "#";
++coord.Y;
}
coord.X = 0;
coord.Y = info.srWindow.Bottom;
for (i = 1; i <= info.srWindow.Right; ++i){
SetConsoleCursorPosition(handle, coord);
std::cout << "#";
++coord.X;
}
coord.X = 0;
coord.Y = 1;
for (i = 1; i<info.srWindow.Bottom; ++i){
SetConsoleCursorPosition(handle, coord);
std::cout << "#";
++coord.Y;
}
//判斷所在界面顯示相關界面的菜單選項及其它
int j = info.srWindow.Right / 4;
switch (snake.ID_interface){
case ID_1:
csnake.ShowMenu();
coord.X = j;
coord.Y = info.srWindow.Bottom - 6;
SetConsoleCursorPosition(handle, coord);
std::cout << "o(-\"-)o 貪 #^_^# 喫 →_→ 蛇 \\(^o^)/";
break;//顯示菜單選項
case ID_2:
case ID_3:
case ID_4:
//繪輸出信息框
coord.X = 1;
coord.Y = info.srWindow.Bottom - 5;
SetConsoleCursorPosition(handle, coord);
for (i = 1; i<info.srWindow.Right; std::cout << "#", ++i);
for (coord.X = j; coord.X <= info.srWindow.Right - j; coord.X += j){
coord.Y = info.srWindow.Bottom - 5;
for (i = coord.Y; i<info.srWindow.Bottom; ++i){
SetConsoleCursorPosition(handle, coord);
std::cout << "#";
++coord.Y;
}
}
//輸出每個框的信息
coord.X = 2;
coord.Y -= 4;
SetConsoleCursorPosition(handle, coord);
std::cout << "遊戲難度:";
coord.Y += 2;
SetConsoleCursorPosition(handle, coord);
std::cout << "\t ";
switch (snake.rank){
case first:
std::cout << "初 級"; break;
case middle:
std::cout << "中 級"; break;
case high:
std::cout << "高 級"; break;
}
//當前分數
coord.X += j;
coord.Y -= 2;
SetConsoleCursorPosition(handle, coord);
std::cout << " 當 前 分 數";
coord.X += j / 2 - 3;
coord.Y += 2;
SetConsoleCursorPosition(handle, coord);
std::cout << snake.mark;
//操作說明
coord.X = j * 2 + 1;
coord.Y = info.srWindow.Bottom - 4;
SetConsoleCursorPosition(handle, coord);
std::cout << " 操作說明: ";
coord.Y += 2;
SetConsoleCursorPosition(handle, coord);
std::cout << " ↑ ↓ ← →";
++coord.Y;
SetConsoleCursorPosition(handle, coord);
std::cout << " 空格: 暫停遊戲";
//製作人
coord.X += j;
SetConsoleCursorPosition(handle, coord);
std::cout << "\t製作人: _ 翼";
break;
case ID_5:
csnake.ShowRank(); break;//顯示遊戲等級
case ID_6:
csnake.ShowRecord(); break;//顯示存檔記錄
case ID_7:
csnake.ShowArmory(); break;//顯示英雄榜
}
}
//畫框函數(完成)
void Frame(){
COORD coord = { 0, info.srWindow.Bottom / 3 };
SetConsoleCursorPosition(handle, coord);
for (short i = 0; i <= info.srWindow.Right; std::cout << "-", ++i);
coord.Y = info.srWindow.Bottom / 3 * 2;
SetConsoleCursorPosition(handle, coord);
for (short i = 0; i <= info.srWindow.Right; std::cout << "-", ++i);
switch (snake.ID_interface){
case ID_3:
csnake.ShowPause(); break;//顯示暫停菜單
case ID_4:
csnake.Die(); break;//顯示死亡界面菜單
case ID_5:
csnake.ShowRank(); break;//顯示等級選項
}
}
//初始化蛇數據(完成)
void initialize_(){
snake.state = true; //蛇狀態
snake.Snake_size = 5; //蛇初始化長度
//初始化蛇位置
COORD cd;
cd.Y = 3;
snake.Snake_coord.clear();
for (size_t i = 10; i>5; --i){
cd.X = i;
snake.Snake_coord.push_back(cd);
}
snake.food_coord.X = 0;
snake.food_coord.Y = 0;
snake.rank = first; //默認等級
snake.mark = 0; //分數
snake.key = VK_RIGHT;
snake.ID_interface = ID_1;//界面標記
snake.ID_option = ID_1; //選項標記
snake.Flag = false;
}