游戲功能介紹
/如果各種問題,請各位大神評論區指出/
1.J:蛇移動加速
2. 空格:游戲暫停
3.K:游戲存檔(只支持一次存檔)
4.自定義地圖(使用滑鼠)
5.多種功能食物
6.背景音樂與音效
7.蛇的多級速度
8.固定障礙物
9.esc回傳游戲大廳
10.簡單的積分功能
####### 使用的VS編輯器###########
應用到的基礎知識
函式 鏈表 指標 結構體 類(這個屬于C++)
功能分析
實作
墻模塊
經過專案分析,可以得出再墻模塊中,需要維護一個二維陣列,對整個游戲中的元素進行設定,所以可以宣告一個二維陣列,char gameArray[][],具體的行數和列數可以定義出一個列舉,比如本游戲中設定的是26行,26列,enum{ROW=26,COL=26};
那么墻模塊開發階段,需要提供得主要介面是 初始化墻initwall,以及列印墻,也就是將二維陣列中得內容列印到控制臺中,draw方法,當然對外還要提供出一個可以修改二維陣列元素的方法以及根據索引獲取二維陣列元素的方法:getWall,setWall
游戲中的實作元素
游戲中元素分為:墻壁,蛇,事物以及蛇的可行區域和右側的版本號和游戲玩法提示
墻壁
*號表示,代表一個區域范圍,也就是蛇的可移動區域,蛇如果碰到墻壁視為死亡,
蛇
分為蛇頭,蛇身,蛇頭用@符號表示,蛇身用=等號表示,當蛇吃到食物時候,蛇身+1,一意為著長度變長,貪吃蛇可以通過不斷地吃食物來增加自己的身體
食物
#井號表示,蛇碰到食物會將食物吃掉
可移動區域
空格 表示,代表蛇可以移動的區域
提示資訊
右側展示,可以顯示當前貪吃蛇版本號,制作人員,游戲玩法等提示資訊
游戲規則
當運行游戲時候,畫面靜止不動,可以默認讓蛇頭超右,游戲中設定w s a d 4個按鍵分別代表,上,下,左,右,也是用戶比較常用的方向按鍵,當用戶輸入w或者s或者d時候激活游戲,注意輸入a不可以激活,因為蛇不可以180°轉彎,因此蛇的移動方向只可以一直向前或者920°旋轉
當蛇吃掉食物時候,此時蛇會增加一個身段,另外食物需要重新隨機的設定到螢屏上
游戲結束方式有兩種:
蛇碰到墻壁為死亡
蛇碰到蛇身子,把自己吃掉也視為死亡
游戲移動
當激活游戲后,也分為兩種,一種是死亡,這個是當 蛇頭碰到蛇身或者是碰到墻壁兩種死亡,這個暫時先不考慮,第二種是正常移動,先分析下正常移動
在正常移動的時候,也分為兩種狀態
第一種:蛇沒吃到食物
這個時候,蛇只是單純的移動,沒吃到食物的時候,蛇會更新蛇頭的位置,并且將之前蛇尾巴的位置為空格,也就是表示向前移動
第二種:蛇吃到食物
當吃到食物時,當前的蛇頭的位置應該為之前食物的位置,那么蛇尾由于吃到了食物,就還是在原有位置,然后食物再重新分配到一個其他的位置,這個位置不能是蛇,也不能是墻,
游戲截圖


main()函式中用到了滑鼠與鍵盤控制的函式(滑鼠回應)
// _怎么添加滑鼠回應.cpp : 此檔案包含 "main" 函式,程式執行將在此處開始并結束,
//
#include <iostream>
#include <Windows.h>
void WriteChar(int x, int y, const char* szInfo)
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { x * 2,y };
SetConsoleCursorPosition(hOut, pos);
printf(szInfo);
}
int main()
{
HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
SetConsoleMode(hIn, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
//PINPUT_RECORD p=NULL;
INPUT_RECORD stcInput;
DWORD dwSize = 0;
while (true)
{
ReadConsoleInput(
hIn,
&stcInput, //這里應該傳什么,傳遞一個有效的記憶體區域
1,
&dwSize
);
//我們判斷結構體中的EventType去確定是不是一個滑鼠事件
if (stcInput.EventType == MOUSE_EVENT)
{
int nButtonState = stcInput.Event.MouseEvent.dwButtonState;
if (nButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
{
int x = stcInput.Event.MouseEvent.dwMousePosition.X;
int y = stcInput.Event.MouseEvent.dwMousePosition.Y;
WriteChar(x / 2, y, "☆");
}
}
}
}
拿這段代碼運行一下,用滑鼠在cmd中按住左拖拽一下
---------------------------------------------------------------------------------------我是分割線-------------------------------------------------------------
各個頭檔案功能簡介
//控制臺
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "main.h"
#include "Wall.h" //墻類
#include "Snake.h" //蛇類
#include "Food.h" //食物類
#include "Scene.h" //基類
#include "Hall.h" //主界面
#include "Game.h" //功能按鍵設定類
#include "Editor.h" //地圖編輯與廢棄
上代碼–(頭檔案與cpp檔案已分開寫-----內含注釋)
common.h
#ifndef __COMMON_H__
#define __COMMON_H__
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <iostream>
using namespace std;
#define MAX_LINE 1024
#pragma comment(lib,"winmm.lib")
/*
設定游標位置
*/
static void gotoxy(int x, int y)
{
COORD c;
c.X = x;
c.Y = y;
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}
/******************************************************************************************/
/*
文字顏色函式
*/
static int color(int c)
{
//SetConsoleTextAttribute是API設定控制臺視窗字體顏色和背景色的函式
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); //更改文字顏色
return 0;
}
#endif
食物類頭檔案Food.h
#ifndef __FOOD_H__
#define __FOOD_H__
#include "common.h"
#include "Wall.h"
//食物類
class Food
{
public:
Food(Wall *tempWall);
void setFood();
int foodX;
int foodY;
Wall *wall;
};
#endif
Food.cpp
#include "Food.h"
#include <Windows.h>
#include <time.h>
Food::Food(Wall *tempWall) :wall(tempWall)
{
}
/******************************************************************************************/
void Food::setFood()
{
while (true)
{
srand((unsigned)time(NULL));
foodX = rand() % (Wall::ROW - 2) + 1;
foodY = rand() % (Wall::COL - 2) + 1;
//如果隨機的位置是蛇頭或蛇身,就重新生成亂數
if (wall->getWall(foodX, foodY) == ' ')
{
int rnd = rand() % 2;
if (rnd == 0)
{
color(5);
wall->setWall(foodX, foodY, '#'); //普通食物
gotoxy(foodY * 2, foodX);
printf("#");
}
else if (rnd == 1)
{
color(5);
wall->setWall(foodX, foodY, '$'); //使蛇變短食物
gotoxy(foodY * 2, foodX);
printf("$");
}
else
{
color(5);
wall->setWall(foodX, foodY, '&'); //加速食物
gotoxy(foodY * 2, foodX);
printf("&");
}
break;
}
}
}
Game.h
#ifndef __GAME_H__
#define __GAME_H__
#include "Wall.h"
#include "Snake.h"
#include "Food.h"
#include "Scene.h"
//游戲功能類
class Game : public Scene
{
public:
Game();
virtual ~Game();
public:
virtual bool init(bool load);
//virtual void destroy();
virtual void draw();
virtual void keyEventProc(char key, bool down);
virtual void mouseEventProc(int x, int y);
void onGameOver();
private:
bool isDead;
char curKey;
char preKey;
Wall *wall;
Food *food;
Snake *snake;
bool pause;
};
#endif
Game.cpp
#include "Game.h"
#include "main.h"
Game::Game()
{
isDead = false;
pause = false;
curKey = 0;
preKey = 0;
wall = new Wall;
food = new Food(wall);
snake = new Snake(wall, food);
}
/******************************************************************************************/
Game::~Game()
{
}
/******************************************************************************************/
bool Game::init(bool load)
{
cleanScreen();
wall->initWall();
if (load)
{
wall->loadMap();
}
wall->drawWall();
if (!wall->hasFood())
{
food->setFood();
}
if (load)
{
snake->load();
}
else
{
snake->InitSnake();
}
PlaySound(NULL, NULL, NULL);
return true;
}
/******************************************************************************************/
//void Game::destroy()
//{
//}
/******************************************************************************************/
void Game::draw()
{
//判斷如果是第一次按了,左鍵,才不能激活游戲
//判斷上一次移動方向
if (preKey == 0 )
{
return;
}
if (curKey == 0)
{
return;
}
if (isDead)
{
return;
}
if (pause)
{
return;
}
if (snake->move(curKey) == true)
{
gotoxy(0, Wall::ROW);
printf("得分:%d分", snake->getScore());
Sleep(snake->getSleepTime());
}
else
{
isDead = true;
onGameOver();
}
}
/******************************************************************************************/
void Game::keyEventProc(char key, bool down)
{
if (key == 106) //j加速
{
if (down)
{
snake->setSpeedUp(true);
}
else
{
snake->setSpeedUp(false);
}
}
if (!down)
{
return;
}
if (key == Snake::UP || key == Snake::DOWN || key == Snake::LEFT || key == Snake::RIGHT)
{
//判斷本次按鍵是否與上次沖突
if ((key == Snake::LEFT && preKey == Snake::RIGHT) ||
(key == Snake::RIGHT && preKey == Snake::LEFT) ||
(key == Snake::UP && preKey == Snake::DOWN) ||
(key == Snake::DOWN && preKey == Snake::UP)
)
{
curKey = preKey;
}
else
{
curKey = key;
preKey = curKey; //不是沖突按鍵,可以更新按鍵
}
}
else
{
curKey = preKey; //強制將錯誤按鍵變為上一次移動的方向
}
if (key == 27) //esc
{
enterScene(SCENE_TYPE_HALL, false);
return;
}
if (key == 32) //空格/暫停
{
if (pause)
{
pause = false;
}
else
{
pause = true;
}
}
if (key == 107) //k存檔
{
wall->saveMap();
snake->save();
}
}
/******************************************************************************************/
void Game::mouseEventProc(int x, int y)
{
}
/******************************************************************************************/
void Game::onGameOver()
{
cleanScreen();
wall->drawWall();
gotoxy(0, Wall::ROW + 1);
printf("GAME OVER\n");
}
Hall.h
#ifndef __HALL_H__
#define __HALL_H__
#include "Scene.h"
class Hall : public Scene
{
public:
Hall();
virtual ~Hall();
public:
virtual bool init(bool load);
//virtual void destroy();
virtual void keyEventProc(char key, bool down);
virtual void mouseEventProc(int x, int y);
void printSnake();
void welcomeToGame();
void explation();
void openMap();
};
#endif
Hall.cpp
#include "Hall.h"
#include "main.h"
Hall::Hall()
{
}
/******************************************************************************************/
Hall::~Hall()
{
}
/******************************************************************************************/
bool Hall::init(bool load)
{
cleanScreen();
printSnake();
welcomeToGame();
PlaySound("sound/bgm_server.wav", NULL, SND_FILENAME | SND_ASYNC | SND_LOOP);
return true;
}
/******************************************************************************************/
//void Hall::destroy()
//{
//}
/******************************************************************************************/
void Hall::keyEventProc(char key, bool down)
{
if (!down)
{
return;
}
switch (key)
{
case 49: //選擇開始游戲
enterScene(SCENE_TYPE_GAME, false);
break;
case 50: //選擇讀取進度開始
enterScene(SCENE_TYPE_GAME, true);
break;
case 51: //選擇編輯地圖
enterScene(SCENE_TYPE_EDITOR, false);
//openMap();
break;
default: //輸入非1~3之間的選項
cleanScreen(); //清屏
printSnake();
welcomeToGame();
break;
}
}
/******************************************************************************************/
void Hall::mouseEventProc(int x, int y)
{
}
/******************************************************************************************/
/*
字符拼成英文圖案
*/
void Hall::printSnake()
{
color(2);
printf(" \n");
printf(" __________ ___ \n");
printf(" / \\ / \\ \\ |____ __\\__ \n");
printf(" / ________ \\ / ___ \\ _/ __ | | / \n");
printf(" | | |__| _/_ |_| / [|] |/ \n");
printf(" | | | | | / _|_ \\__/ \n");
printf(" \\ \\_______ / \\ |___/ ____ \n");
printf(" \\ \\ ____ ____ ____ __ | | ___ ______ \n");
printf(" \\_______ \\ | |/ \\ / \\_/ / | | / / / \\ \n");
printf(" \\ \\ | ___ \\ / ____ / | |/ / / ____ \\ \n");
printf(" __ | | | / \\ \\ | | | / | / | /____\\ | \n");
printf(" \\ \\_______| | | | | | | |__| | | \\ | ________/ \n");
printf(" \\ / | | | | \\ \\ | |\\ \\ \\ \\____ \n");
printf(" \\__________/ |__| |__| \\___/\\__\\ |__| \\__\\ \\______/ \n");
}
/******************************************************************************************/
/*
開始界面
*/
void Hall::welcomeToGame()
{
int n;
int i, j = 1;
gotoxy(34, 15);
color(11);
printf("貪 吃 蛇 游 戲");
color(14); //黃色邊框
for (i = 17; i <= 23; i++) //輸出上下邊框┅
{
for (j = 16; j <= 68; j++) //輸出左右邊框┇
{
gotoxy(j, i);
if (i == 17 || i == 23)
{
printf("-");
}
else if (j == 16 || j == 68)
{
printf("|");
}
}
}
color(10);
gotoxy(26, 19);
printf("1.純凈模式");
gotoxy(46, 19);
printf("2.DIY與進度讀取");
gotoxy(26, 21);
printf("3.DIY障礙物");
gotoxy(46, 21);
printf("祝天天好心情O(∩_∩)O");
gotoxy(10000, 10000);
}
/******************************************************************************************/
/*
滑鼠編輯地圖
*/
void Hall::explation()
{
//int i, j = 1;
//system("cls");
//color(15);
//gotoxy(44, 3);
//printf("游戲說明");
//color(2);
//for (i = 6; i <= 22; i++) //輸出上下邊框===
//{
// for (j = 20; j <= 76; j++) //輸出左右邊框||
// {
// gotoxy(j, i);
// if (i == 6 || i == 22) printf("=");
// else if (j == 20 || j == 75) printf("||");
// }
//}
//color(3);
//gotoxy(30, 8);
//printf("tip1: 不能撞墻,不能咬到自己");
//color(10);
//gotoxy(30, 11);
//printf("tip2: 用w.a.s.d分別控制蛇的移動");
//color(14);
//gotoxy(30, 14);
//printf("tip3: 按空格鍵暫停游戲,再按空格鍵繼續");
//color(11);
//gotoxy(30, 17);
//printf("tip4: 按ESC鍵退出游戲回傳大廳");
}
/******************************************************************************************/
void Hall::openMap()
{
ShellExecute(NULL, TEXT("open"), "notepad.exe", "save/default.map", TEXT(""), SW_SHOWNORMAL);
}
/******************************************************************************************/
main.h
#ifndef __MAIN_H__
#define __MAIN_H__
enum Scene_Type
{
SCENE_TYPE_HALL = 0,
SCENE_TYPE_GAME ,
SCENE_TYPE_EDITOR ,
};
void cleanScreen();
void enterScene(Scene_Type type, bool load);
#endif
main.cpp
//控制臺
#include <windows.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include "main.h"
#include "Wall.h" //墻類
#include "Snake.h" //蛇類
#include "Food.h" //食物類
#include "Scene.h" //基類
#include "Hall.h" //主界面
#include "Game.h" //功能按鍵設定類
#include "Editor.h" //地圖編輯與廢棄
Scene *scene;
HANDLE hStdin;
int init();
void keyEventProc(char key, bool down);
void mouseEventProc(int x, int y);
/******************************************************************************************/
int main(const char* user)
{
keybd_event(VK_SHIFT,0,0,0); //自動切換英文
Sleep(100);
keybd_event(VK_SHIFT,0,KEYEVENTF_KEYUP,0);
hStdin = GetStdHandle(STD_INPUT_HANDLE); //句柄控制
INPUT_RECORD stcRecord[128] = { 0 };
DWORD dwRead = 0;
SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT); //獲取操作
init();
while (1)
{
GetNumberOfConsoleInputEvents(hStdin, &dwRead);
if (dwRead > 0)
{
ReadConsoleInput(hStdin, &stcRecord[0], 128, &dwRead); //獲取資料
for (int i = 0; i < dwRead; i++)
{
if (stcRecord[i].EventType == KEY_EVENT)
{
keyEventProc(stcRecord[i].Event.KeyEvent.uChar.AsciiChar, stcRecord[i].Event.KeyEvent.bKeyDown);
}
else if (stcRecord[i].EventType == MOUSE_EVENT)
{
if (stcRecord[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED
&& stcRecord[i].Event.MouseEvent.dwEventFlags != MOUSE_MOVED)
{
mouseEventProc(stcRecord[i].Event.MouseEvent.dwMousePosition.Y, stcRecord[i].Event.MouseEvent.dwMousePosition.X);
}
}
}
}
if (scene)
{
scene->draw();
}
Sleep(50);
}
return 0;
}
/******************************************************************************************/
int init()
{
scene = NULL;
enterScene(SCENE_TYPE_HALL, false);
return 1;
}
/******************************************************************************************/
void enterScene(Scene_Type type, bool load)
{
if (scene)
{
scene->destroy();
//delete scene;
}
if (type == SCENE_TYPE_HALL)
{
scene = new Hall;
scene->init(load);
}
else if (type == SCENE_TYPE_GAME)
{
scene = new Game;
scene->init(load);
}
else if (type == SCENE_TYPE_EDITOR)
{
scene = new Editor;
scene->init(load);
}
}
/******************************************************************************************/
void keyEventProc(char key, bool down)
{
if (scene)
{
scene->keyEventProc(key, down);
}
}
/******************************************************************************************/
void mouseEventProc(int x, int y)
{
if (scene)
{
scene->mouseEventProc(x, y);
}
}
void cleanScreen()
{
system("cls");
SetConsoleMode(hStdin, ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT);
}
Scene.h
#ifndef __SCENE_H__
#define __SCENE_H__
#include "common.h"
//GAME與HALL的基類
class Scene
{
public:
Scene();
virtual ~Scene();
public:
virtual bool init(bool load);
virtual void destroy();
virtual void draw();
virtual void keyEventProc(char key, bool down);
virtual void mouseEventProc(int x, int y);
};
#endif
Scene.cpp
#include "Scene.h"
#include "main.h"
Scene::Scene()
{
}
/******************************************************************************************/
Scene::~Scene()
{
}
/******************************************************************************************/
bool Scene::init(bool load)
{
return false;
}
/******************************************************************************************/
void Scene::destroy()
{
cleanScreen();
gotoxy(0, 0);
}
/******************************************************************************************/
void Scene::draw()
{
}
/******************************************************************************************/
void Scene::keyEventProc(char key, bool down)
{
}
/******************************************************************************************/
void Scene::mouseEventProc(int x, int y)
{
}
Snake.h
#ifndef __SNAKE_H__
#define __SNAKE_H__
#include "common.h"
#include "Wall.h"
#include "Food.h"
class Snake
{
public:
Snake(Wall *tempWall, Food* food);
enum
{
UP = 'w',
DOWN = 's',
LEFT = 'a',
RIGHT = 'd'
};
struct Point
{
//資料域
int x;
int y;
//指標域
Point *next;
};
//初始化結點
void InitSnake();
//銷毀結點
void destroyPoint();
//添加結點
void addPoint(int x, int y);
//移動時洗掉結點
void delPoint();
//移動操作
//回傳值代表是否成功
bool move(char key);
//設定難度
//獲取刷屏時間
int getSleepTime();
//獲取蛇的身段
int countList();
//獲取分數
int getScore();
//加速
void setSpeedUp(bool speedUp);
void load();
void save();
private:
Point *pHead;
Wall *wall;
Food *food;
bool isRool; //回圈的標識
int sleepTime;
float speedUp; //加速速度
bool bSpeedUp; //加速標志
};
#endif
Snake.cpp
#include "Snake.h"
#include "Wall.h"
#include <Windows.h>
Snake::Snake(Wall *tempWall, Food* tempFood) : wall(tempWall), food(tempFood)
{
pHead = NULL;
isRool = false;
sleepTime = 300;
speedUp = 0.5f;
bSpeedUp = false;
}
/******************************************************************************************/
void Snake::destroyPoint()
{
Point * pCur = pHead;
while (pHead != NULL)
{
pCur = pHead->next;
delete pHead;
pHead = pCur;
}
}
/******************************************************************************************/
void Snake::addPoint(int x, int y)
{
//創建新結點
Point * newpoint = new Point;
newpoint->x = x;
newpoint->y = y;
newpoint->next = NULL;
//如果原來頭不為空,改為身子
if (pHead != NULL)
{
color(3);
wall->setWall(pHead->x, pHead->y, '=');
gotoxy(pHead->y * 2, pHead->x);
printf("=");
}
color(4);
newpoint->next = pHead;
pHead = newpoint;//更新頭部
wall->setWall(pHead->x, pHead->y, '@');
gotoxy(pHead->y * 2, pHead->x);
printf("@");
}
/******************************************************************************************/
//初始化坐標
void Snake::InitSnake()
{
destroyPoint();
addPoint(5, 3);
addPoint(5, 4);
addPoint(5, 5);
addPoint(5, 6);
addPoint(5, 7);
addPoint(5, 8);
addPoint(5, 9);
}
/******************************************************************************************/
//移動時洗掉結點
void Snake::delPoint()
{
//三個以上結點 才去做洗掉操作
if (pHead == NULL || pHead->next == NULL || pHead->next->next == NULL)
{
return;
}
//當前結點
Point *pCur = pHead->next;
//上一個結點
Point *pPre = pHead;
while (pCur && pCur->next != NULL)
{
pPre = pPre->next;
pCur = pCur->next;
}
//洗掉尾結點
wall->setWall(pCur->x, pCur->y, ' ');
gotoxy(pCur->y * 2, pCur->x);
printf(" ");
delete pCur;
pCur = NULL;
pPre->next = NULL;
}
/******************************************************************************************/
bool Snake::move(char key)
{
int x = pHead->x;
int y = pHead->y; /*蛇的移動*/
switch (key)
{
case UP:
x--;
break;
case DOWN:
x++;
break;
case LEFT:
y--;
break;
case RIGHT:
y++;
break;
default:
return true;
}
//判斷 如果下一步碰到的是尾巴,不應該死亡
Point *pCur = pHead->next;
//上一個結點
Point *pPre = pHead;
while (pCur && pCur->next != NULL)
{
pPre = pPre->next;
pCur = pCur->next;
}
if (pCur->x == x && pCur->y == y)
{
//碰到尾巴的回圈
isRool = true;
}
else
{
//判斷用戶要到達的位置是否成功
if (wall->getWall(x, y) == '*' || wall->getWall(x, y) == '=')
{
addPoint(x, y);
delPoint();
return false;
}
}
//移動成功 分兩種
//吃到食物,未吃到食物
if (wall->getWall(x, y) == '#')
{
addPoint(x, y);
//重新設定食物
food->setFood();
PlaySound("sound/boss_bfz.wav", NULL, SND_FILENAME | SND_ASYNC);
}
else if (wall->getWall(x, y) == '$')
{
addPoint(x, y);
delPoint();
delPoint();
//重新設定食物
food->setFood();
PlaySound("sound/boss_bfz.wav", NULL, SND_FILENAME | SND_ASYNC);
}
else if (wall->getWall(x, y) == '&')
{
sleepTime -= 30;
addPoint(x, y);
//重新設定食物
food->setFood();
PlaySound("sound/boss_bfz.wav", NULL, SND_FILENAME | SND_ASYNC);
}
//蛇頭
else
{
addPoint(x, y);
delPoint();
if (isRool == true)
{
color(4);
wall->setWall(x, y, '@');
gotoxy(y * 2, x);
printf("@");
}
}
return true;
}
/******************************************************************************************/
int Snake::getSleepTime() /*蛇長與速度*/
{
if (sleepTime < 0)
{
sleepTime = 0;
}
int size = countList();
if (size < 5)
{
sleepTime = 300;
}
else if (size >= 5 && size <= 10)
{
sleepTime = 200;
}
else if (size >= 10 && size <= 30)
{
sleepTime = 150;
}
else if (size >= 30 && size <= 60)
{
sleepTime = 100;
}
else if (size >= 60 && size <= 100)
{
sleepTime = 50;
}
if (bSpeedUp)
{
sleepTime = speedUp * sleepTime;
}
return sleepTime;
}
/******************************************************************************************/
//獲得蛇身段
int Snake::countList()
{
int size = 0;
Point * curPoint = pHead;
while (curPoint != NULL)
{
size++;
curPoint = curPoint->next;
}
return size;
}
/******************************************************************************************/
//分數
int Snake::getScore()
{
int size = countList();
int score = (size - 3) * 100;
return score;
}
/******************************************************************************************/
//加速
void Snake::setSpeedUp(bool speedUp)
{
bSpeedUp = speedUp;
}
/******************************************************************************************/
void Snake::load() //蛇狀態加載
{
destroyPoint();
char buf[MAX_LINE];
FILE *fp;
if ((fp = fopen("save/default.snake", "r")) == NULL)
{
perror("fail to read");
exit(1);
}
while (fgets(buf, MAX_LINE, fp) != NULL)
{
int len = strlen(buf);
buf[len - 1] = '\0';
len = len - 1;
int x = 0;
int y = 0;
sscanf(buf, "%d,%d", &x, &y);
addPoint(x, y);
}
fclose(fp);
}
/******************************************************************************************/
void Snake::save() //蛇狀態存檔
{
int count = 0;
Point *points[2048] = { 0 };
FILE *fp;
int len = 0;
if ((fp = fopen("save/default.snake", "w")) == NULL)
{
perror("fail to read");
exit(1);
}
Point * pCur = pHead;
while (pCur != NULL)
{
points[count++] = pCur;
pCur = pCur->next;
}
for (int i = count-1; i >= 0; i--)
{
char buf[MAX_LINE] = { 0 };
sprintf(buf, "%d,%d\n", points[i]->x, points[i]->y);
fwrite(buf, strlen(buf), 1, fp);
}
fclose(fp);
}
Wall.h
#ifndef __WALL_H__
#define __WALL_H__
#include "common.h"
class Wall
{
public:
enum
{
ROW = 26, //行數
COL = 26//列數
};
//初始化墻壁
void initWall();
//畫出墻壁
void drawWall();
void loadMap();
void saveMap();
//根據索引來設定 二維陣列里的內容
//設定蛇的部分的時候和設定食物要用
void setWall(int x, int y, char c);
//根據索引來獲取當前位置的符號
char getWall(int x, int y);
bool hasFood();
private:
char gameArray[ROW][COL];
};
#endif
Wall.cpp
#include "Wall.h"
void Wall::initWall() //初始化墻壁,用二維陣列
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
//放墻壁的地方
if (i == 0 || j == 0 || i == ROW - 1 || j == COL - 1)
{
color(6);
gameArray[i][j] = '*';
}
else
{
color(3);
gameArray[i][j] = ' ';
}
}
}
for (int i = 19; i < 23; i++)
{
gameArray[15][i] = '*'; //地圖內障礙物
}
}
/******************************************************************************************/
void Wall::drawWall()
{
for (int i = 0; i < ROW; ++i)
{
for (int j = 0; j < COL; ++j)
{
if (gameArray[i][j] == '*')
{
color(6);
}
else if (gameArray[i][j] == '#')
{
color(5);
}
else if (gameArray[i][j] == '$')
{
color(5);
}
else if (gameArray[i][j] == '&')
{
color(5);
}
//畫的時候多加一個空格,看起來好看一些
printf("%c ", gameArray[i][j] );
}
printf("\n");
}
color(18);
gotoxy(55, 6);
printf("j加速");
color(3);
gotoxy(55, 8);
printf("撞到墻與自己會死");
color(49);
gotoxy(55, 11);
printf("w.a.s.d控制方向");
color(14);
gotoxy(55, 14);
printf("#普通/$變短/&加速");
color(11);
gotoxy(55, 17);
printf("空格/暫停");
color(15);
gotoxy(55, 20);
printf("ESC回傳大廳");
color(10);
gotoxy(55, 22);
printf("k存檔");
gotoxy(0, Wall::ROW+1);
}
/******************************************************************************************/
void Wall::loadMap() //地圖加載
{
char buf[MAX_LINE]; /*緩沖區*/
FILE *fp; /*檔案指標*/
int i = 0, len = 0; /*行字符個數*/
if ((fp = fopen("save/default.map", "r")) == NULL)
{
perror("fail to read");
exit(1);
}
while (fgets(buf, MAX_LINE, fp) != NULL)
{
len = strlen(buf);
buf[len - 1] = '\0';
len = len - 1;
if (len > COL)
{
break;
}
for (int j = 0; j < len; j++)
{
if ((buf[j]) == '1')
{
gameArray[i][j] = '*';
}
else if ((buf[j]) == '2')
{
gameArray[i][j] = '#';
}
else if ((buf[j]) == '3')
{
gameArray[i][j] = '$';
}
else if ((buf[j]) == '4')
{
gameArray[i][j] = '&';
}
else
{
gameArray[i][j] = ' ';
}
}
i++;
if (i > ROW)
{
break;
}
}
fclose(fp);
}
/******************************************************************************************/
void Wall::saveMap() //地圖保存
{
char buf[MAX_LINE]; /*緩沖區*/
FILE *fp; /*檔案指標*/
int i = 0, len = 0; /*行字符個數*/
if ((fp = fopen("save/default.map", "w")) == NULL)
{
perror("fail to read");
exit(1);
}
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (gameArray[i][j] == '*')
{
fwrite("1", sizeof(char), 1, fp);
}
else if (gameArray[i][j] == '#')
{
fwrite("2", sizeof(char), 1, fp);
}
else if (gameArray[i][j] == '$')
{
fwrite("3", sizeof(char), 1, fp);
}
else if (gameArray[i][j] == '&')
{
fwrite("4", sizeof(char), 1, fp);
}
else
{
fwrite("0", sizeof(char), 1, fp);
}
}
fwrite("\n", sizeof(char), 1, fp);
}
fclose(fp);
}
/******************************************************************************************/
void Wall::setWall(int x, int y, char c)
{
gameArray[x][y] = c;
}
/******************************************************************************************/
char Wall::getWall(int x, int y)
{
return gameArray[x][y];
}
bool Wall::hasFood()
{
for (int i = 0; i < ROW; i++)
{
for (int j = 0; j < COL; j++)
{
if (gameArray[i][j] == '#')
{
return true;
}
else if (gameArray[i][j] == '$')
{
return true;
}
else if (gameArray[i][j] == '&')
{
return true;
}
}
}
return false;
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/195281.html
標籤:其他
