C++控制檯貪吃蛇小遊戲詳細教程
遊戲截圖
開始動畫:
遊戲過程:
遊戲架構設計
該遊戲的玩法簡單,玩家通過鍵盤方向鍵控制蛇上下左右移動,吃到食物得分並增長,碰到牆或者自己的身體則死亡,遊戲結束。
整個遊戲其實就是一個無窮的迴圈,直到退出遊戲時退出迴圈。我們暫且將這個迴圈稱為一級迴圈,這個迴圈包含遊戲開始動畫,遊戲難度選擇,遊戲過程這三個子模組,其中游戲過程這個模組亦是一個迴圈,我們暫且將其稱為二級迴圈。它們之間的關係大致如下圖:
現在我們根據上圖進行細化,對各個模組的實現進行簡單描述。
1.遊戲開始動畫
開始動畫的實現主要依靠對點的操作來實現,這裡我們先建立一個概念,就是將控制檯介面看成一個原點在左上角的座標系,一個點(x,y)表示座標系中的一個格子,如下圖所示:
我們的開始動畫是由一條蛇和一行文字從左到右移動而成,這裡我們先單獨討論一下蛇,要達到移動的效果,我採取的策略是將整個過程分為三部分:
第一部分為蛇從左邊開始出現到整個身體完全出現
第二部分為蛇身整體從左移動到接觸右邊界的過程
第三部分為蛇從接觸右邊界到完全消失的過程
我們先來看一下第一部分,這一部分的實現首先是建立一個deque雙端佇列,用於儲存點的物件,這些點就是組成蛇身的元素,然後再用一個for迴圈將容器中的點依次打印出來,每列印一個點停頓一會,這樣就達到了移動的效果。全部列印完後就到了第二部分,這部分蛇的每次前進都是通過計算將要移動到的下一個點的座標,然後將這個點打印出來,與此同時將蛇尾,亦即queue中的首端點去掉,並擦除螢幕上該點顏色。第三部分就直接依次從蛇尾擦除即可。
同理,文字snake的移動也基本類似,稍微改動即可,因為無需對首尾進行操作,而是要對所以點進行移動,因此容器選用vector。
具體請參看startinterface.h以及startinterface.cpp
2.選擇難度
其實這個模組很簡單,我就簡單介紹一下,先將難度選擇的文字資訊列印在螢幕上,然後通過控制鍵盤方向鍵選擇,回車鍵確認,為了突出選中項,需要給選中項打上背景色,然後每一次上下移動時,先將當前的背景色去掉,然後給下一個選中項打上背景色,按下回車後通過改變蛇移動的速度實現改變難度。其中讀取鍵盤輸入是通過getch()函式完成的。
3.遊戲過程
這個模組就是整個遊戲最主要的部分了,首先它先繪製出地圖以及側邊欄,同時初始化蛇和食物,然後通過一個無窮迴圈監聽鍵盤,以此來控制蛇移動,同時又進行各種判斷,來判斷是否死亡、吃到食物或暫停。需要提一下,這裡使用kbhit()函式來監聽鍵盤,它用來判斷在一段固定的時間內是否有鍵盤輸入,要知道,這個函式的返回值有兩個,第一個是是否有輸入的返回值,第二個才是鍵盤輸入的內容,也就是說要經過兩次的讀取緩衝區才能讀到真正的鍵盤輸入。
遊戲程式碼實現
從這裡開始我們就可以真正動手來實現遊戲了,在動手之前,我建議先下載遊戲來玩幾局,弄清整個遊戲的邏輯,這樣更能有一個清晰的思路。
接著你可以將以下的程式碼或者github上的程式碼按下面幾張圖的流程新增進工程裡,當然如果你使用其他IDE的話就按照它的方式來弄,然後進行編譯試一下。
首先新建工程
然後將檔案一個一個新增進工程裡
最後所有檔案新增完就是這樣了
記得要把編譯器改成c++11標準
完成了以上幾步後就可以點編譯按鈕進行編譯,同時執行一下,看看效果。然後閱讀原始碼或者修改一下,看看編譯後有什麼不同。
這裡程式碼.h檔案是類的定義,.cpp檔案是類的實現。整個程式共有七個類,分別為Tools,Point,StartInterface,Snake,Map,Food。
因為整個遊戲需要對於點的大量操作,所以建立Tools和Point兩個類,Tools工具類主要是用於設定游標的位置以及輸出文字的顏色,Point類設定點的物件,因為其他類都是建立在這兩個類的基礎上的,所以閱讀程式碼時要先看這兩個。然後才開始從main.cpp開始看,一行一行,看到出現新的類就轉到該類的宣告與定義檔案去看,這樣閱讀起來比較清晰,這裡簡要說明一下各個類的功能,Controller類就是控制整個遊戲過程的,包括遊戲的各個階段,比如更新分數,遊戲難度選擇等;Food類實現食物的隨機出現;Map類負責繪製地圖,我由於時間關係(主要是懶)沒有加入地圖,只有邊界,但原理和邊界是一模一樣的,同樣是將點繪製出來,然後每一次都判斷蛇是否撞到地圖即可;Snake類控制蛇的移動和吃到食物等。
各個類之間的關係大致如下:
以下是實現的程式碼
main.cpp
#include "controller.h"
int main()//程式入口
{
Controller c;//宣告一個Controller類
c.Game();//整個遊戲迴圈
return 0;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
controller.h
#ifndef CONTROLLER_H
#define CONTROLLER_H
class Controller
{
public:
Controller() : speed(200), key(1), score(0) {}
void Start();
void Select();
void DrawGame();
int PlayGame();
void UpdateScore(const int&);
void RewriteScore();
int Menu();
void Game();
int GameOver();
private:
int speed;
int key;
int score;
};
#endif // CONTROLLER_H
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
controller.cpp
#include <iostream>
#include <time.h>
#include <conio.h>
#include <windows.h>
#include "controller.h"
#include "tools.h"
#include "startinterface.h"
#include "map.h"
#include "snake.h"
#include "food.h"
void Controller::Start()//開始介面
{
SetWindowSize(41, 32);//設定視窗大小
SetColor(2);//設定開始動畫顏色
StartInterface *start = new StartInterface();//動態分配一個StartInterface類start
start->Action();//開始動畫
delete start;//釋放記憶體空間
/*設定關標位置,並輸出提示語,等待任意鍵輸入結束*/
SetCursorPosition(13, 26);
std::cout << "Press any key to start... " ;
SetCursorPosition(13, 27);
system("pause");
}
void Controller::Select()//選擇介面
{
/*初始化介面選項*/
SetColor(3);
SetCursorPosition(13, 26);
std::cout << " " ;
SetCursorPosition(13, 27);
std::cout << " " ;
SetCursorPosition(6, 21);
std::cout << "請選擇遊戲難度:" ;
SetCursorPosition(6, 22);
std::cout << "(上下鍵選擇,回車確認)" ;
SetCursorPosition(27, 22);
SetBackColor();//第一個選項設定背景色以表示當前選中
std::cout << "簡單模式" ;
SetCursorPosition(27, 24);
SetColor(3);
std::cout << "普通模式" ;
SetCursorPosition(27, 26);
std::cout << "困難模式" ;
SetCursorPosition(27, 28);
std::cout << "煉獄模式" ;
SetCursorPosition(0, 31);
score = 0;
/*上下方向鍵選擇模組*/
int ch;//記錄鍵入值
key = 1;//記錄選中項,初始選擇第一個
bool flag = false;//記錄是否鍵入Enter鍵標記,初始置為否
while ((ch = getch()))
{
switch (ch)//檢測輸入鍵
{
case 72://UP上方向鍵
if (key > 1)//當此時選中項為第一項時,UP上方向鍵無效
{
switch (key)
{
case 2:
SetCursorPosition(27, 22);//給待選中項設定背景色
SetBackColor();
std::cout << "簡單模式" ;
SetCursorPosition(27, 24);//將已選中項取消我背景色
SetColor(3);
std::cout << "普通模式" ;
--key;
break;
case 3:
SetCursorPosition(27, 24);
SetBackColor();
std::cout << "普通模式" ;
SetCursorPosition(27, 26);
SetColor(3);
std::cout << "困難模式" ;
--key;
break;
case 4:
SetCursorPosition(27, 26);
SetBackColor();
std::cout << "困難模式" ;
SetCursorPosition(27, 28);
SetColor(3);
std::cout << "煉獄模式" ;
--key;
break;
}
}
break;
case 80://DOWN下方向鍵
if (key < 4)
{
switch (key)
{
case 1:
SetCursorPosition(27, 24);
SetBackColor();
std::cout << "普通模式" ;
SetCursorPosition(27, 22);
SetColor(3);
std::cout << "簡單模式" ;
++key;
break;
case 2:
SetCursorPosition(27, 26);
SetBackColor();
std::cout << "困難模式" ;
SetCursorPosition(27, 24);
SetColor(3);
std::cout << "普通模式" ;
++key;
break;
case 3:
SetCursorPosition(27, 28);
SetBackColor();
std::cout << "煉獄模式" ;
SetCursorPosition(27, 26);
SetColor(3);
std::cout << "困難模式" ;
++key;
break;
}
}
break;
case 13://Enter回車鍵
flag = true;
break;
default://無效按鍵
break;
}
if (flag) break;//輸入Enter回車鍵確認,退出檢查輸入迴圈
SetCursorPosition(0, 31);//將游標置於左下角,避免關標閃爍影響遊戲體驗
}
switch (key)//根據所選選項設定蛇的移動速度,speed值越小,速度越快
{
case 1:
speed = 135;
break;
case 2:
speed = 100;
break;
case 3:
speed = 60;
break;
case 4:
speed = 30;
break;
default:
break;
}
}
void Controller::DrawGame()//繪製遊戲介面
{
system("cls");//清屏
/*繪製地圖*/
SetColor(3);
Map *init_map = new Map();
init_map->PrintInitmap();
delete init_map;
/*繪製側邊欄*/
SetColor(3);
SetCursorPosition(33, 1);
std::cout << "Greedy Snake" ;
SetCursorPosition(34, 2);
std::cout << "貪吃蛇" ;
SetCursorPosition(31, 4);
std::cout << "難度:" ;
SetCursorPosition(36, 5);
switch (key)
{
case 1:
std::cout << "簡單模式" ;
break;
case 2:
std::cout << "普通模式" ;
break;
case 3:
std::cout << "困難模式" ;
break;
case 4:
std::cout << "煉獄模式" ;
break;
default:
break;
}
SetCursorPosition(31, 7);
std::cout << "得分:" ;
SetCursorPosition(37, 8);
std::cout << " 0" ;
SetCursorPosition(33, 13);
std::cout << " 方向鍵移動" ;
SetCursorPosition(33, 15);
std::cout << " ESC鍵暫停" ;
}
int Controller::PlayGame()//遊戲二級迴圈
{
/*初始化蛇和食物*/
Snake *csnake = new Snake();
Food *cfood = new Food();
SetColor(6);
csnake->InitSnake();
srand((unsigned)time(NULL));//設定隨機數種子,如果沒有 食物的出現位置將會固定
cfood->DrawFood(*csnake);
/*遊戲迴圈*/
while (csnake->OverEdge() && csnake->HitItself()) //判斷是否撞牆或撞到自身,即是否還有生命
{
/*調出選擇選單*/
if (!csnake->ChangeDirection()) //按Esc鍵時
{
int tmp = Menu();//繪製選單,並得到返回值
switch (tmp)
{
case 1://繼續遊戲
break;
case 2://重新開始
delete csnake;
delete cfood;
return 1;//將1作為PlayGame函式的返回值返回到Game函式中,表示重新開始
case 3://退出遊戲
delete csnake;
delete cfood;
return 2;//將2作為PlayGame函式的返回值返回到Game函式中,表示退出遊戲
default:
break;
}
}
if (csnake->GetFood(*cfood)) //吃到食物
{
csnake->Move();//蛇增長
UpdateScore(1);//更新分數,1為分數權重
RewriteScore();//重新繪製分數
cfood->DrawFood(*csnake);//繪製新食物
}
else
{
csnake->NormalMove();//蛇正常移動
}
if (csnake->GetBigFood(*cfood)) //吃到限時食物
{
csnake->Move();
UpdateScore(cfood->GetProgressBar()/5);//分數根據限時食物進度條確定
RewriteScore();
}
if (cfood->GetBigFlag()) //如果此時有限時食物,閃爍它
{
cfood->FlashBigFood();
}
Sleep(speed);//製造蛇的移動效果
}
/*蛇死亡*/
delete csnake;//釋放分配的記憶體空間
delete cfood;
int tmp = GameOver();//繪製遊戲結束介面,並返回所選項
switch (tmp)
{
case 1:
return 1;//重新開始
case 2:
return 2;//退出遊戲
default:
return 2;
}
}
void Controller::UpdateScore(const int& tmp)//更新分數
{
score += key * 10 * tmp;//所得分數根據遊戲難度及傳人的引數tmp確定
}
void Controller::RewriteScore()//重繪分數
{
/*為保持分數尾部對齊,將最大分數設定為6位,計算當前分數位數,將剩餘位數用空格補全,再輸出分數*/
SetCursorPosition(37, 8);
SetColor(11);
int bit = 0;
int tmp = score;
while (tmp != 0)
{
++bit;
tmp /= 10;
}
for (int i = 0; i < (6 - bit); ++i)
{
std::cout << " " ;
}
std::cout << score ;
}
int Controller::Menu()//選擇選單
{
/*繪製選單*/
SetColor(11);
SetCursorPosition(32, 19);
std::cout << "選單:" ;
Sleep(100);
SetCursorPosition(34, 21);
SetBackColor();
std::cout << "繼續遊戲" ;
Sleep(100);
SetCursorPosition(34, 23);
SetColor(11);
std::cout << "重新開始" ;
Sleep(100);
SetCursorPosition(34, 25);
std::cout << "退出遊戲" ;
SetCursorPosition(0, 31);
/*選擇部分*/
int ch;
int tmp_key = 1;
bool flag = false;
while ((ch = getch()))
{
switch (ch)
{
case 72://UP
if (tmp_key > 1)
{
switch (tmp_key)
{
case 2:
SetCursorPosition(34, 21);
SetBackColor();
std::cout << "繼續遊戲" ;
SetCursorPosition(34, 23);
SetColor(11);
std::cout << "重新開始" ;
--tmp_key;
break;
case 3:
SetCursorPosition(34, 23);
SetBackColor();
std::cout << "重新開始" ;
SetCursorPosition(34, 25);
SetColor(11);
std::cout << "退出遊戲" ;
--tmp_key;
break;
}
}
break;
case 80://DOWN
if (tmp_key < 3)
{
switch (tmp_key)
{
case 1:
SetCursorPosition(34, 23);
SetBackColor();
std::cout << "重新開始" ;
SetCursorPosition(34, 21);
SetColor(11);
std::cout << "繼續遊戲" ;
++tmp_key;
break;
case 2:
SetCursorPosition(34, 25);
SetBackColor();
std::cout << "退出遊戲" ;
SetCursorPosition(34, 23);
SetColor(11);
std::cout << "重新開始" ;
++tmp_key;
break;
}
}
break;
case 13://Enter
flag = true;
break;
default:
break;
}
if (flag)
{
break;
}
SetCursorPosition(0, 31);
}
if (tmp_key == 1) //選擇繼續遊戲,則將選單擦除
{
SetCursorPosition(32, 19);
std::cout << " " ;
SetCursorPosition(34, 21);
std::cout << " ";
SetCursorPosition(34, 23);
std::cout << " ";
SetCursorPosition(34, 25);
std::cout << " ";
}
return tmp_key;
}
void Controller::Game()//遊戲一級迴圈
{
Start();//開始介面
while (true)//遊戲可視為一個死迴圈,直到退出遊戲時迴圈結束
{
Select();//選擇介面
DrawGame();//繪製遊戲介面
int tmp = PlayGame();//開啟遊戲迴圈,當重新開始或退出遊戲時,結束迴圈並返回值給tmp
if (tmp == 1) //返回值為1時重新開始遊戲
{
system("cls");
continue;
}
else if (tmp == 2) //返回值為2時退出遊戲
{
break;
}
else
{
break;
}
}
}
int Controller::GameOver()//遊戲結束介面
{
/*繪製遊戲結束介面*/
Sleep(500);
SetColor(11);
SetCursorPosition(10, 8);
std::cout << "━━━━━━━━━━━━━━━━━━━━━━" ;
Sleep(30);
SetCursorPosition(9, 9);
std::cout << " ┃ Game Over !!! ┃" ;
Sleep(30);
SetCursorPosition(9, 10);
std::cout << " ┃ ┃" ;
Sleep(30);
SetCursorPosition(9, 11);
std::cout << " ┃ 很遺憾!你掛了 ┃" ;
Sleep(30);
SetCursorPosition(9, 12);
std::cout << " ┃ ┃" ;
Sleep(30);
SetCursorPosition(9, 13);
std::cout << " ┃ 你的分數為: ┃" ;
SetCursorPosition(24, 13);
std::cout << score ;
Sleep(30);
SetCursorPosition(9, 14);
std::cout << " ┃ ┃"
相關推薦
C++控制檯貪吃蛇小遊戲詳細教程
遊戲截圖 開始動畫: 遊戲過程: 遊戲架構設計 該遊戲的玩法簡單,玩家通過鍵盤方向鍵控制蛇上下左右移動,吃到食物得分並增長,碰到牆或者自己的身體則死亡,遊戲結束。 整個遊戲其實就是一個無窮的迴圈,直到退出遊戲時退出迴圈
c++經典專案控制檯貪吃蛇小遊戲詳細教程
貪吃蛇GreedySnake 本文將講解如何使用c++面向物件方法編寫控制檯版貪吃蛇小遊戲,專案github地址:silence1772/GreedySnake 遊戲下載:GreedySnake 本人屬初學者,水平所限,難免有所錯誤及不妥之處,勞請指出或發
c語言控制檯的一個貪吃蛇小遊戲
#include<stdio.h> #include<Windows.h> #include<conio.h> #include<stdlib.h> #include<time.h> #define HEAD 1
C語言編寫貪吃蛇小遊戲
**遊戲結構** 1.知道怎麼控制終端上游標的位置。 #include<stdio.h> #inc
基於QT5.4的C++貪吃蛇小遊戲
遊戲核心程式碼: void myWidget::timerEvent(QTimerEvent *e){//定時器 if(e->timerId() == timerId && gamePause){ if(direction
用連結串列做控制檯下的貪吃蛇小遊戲
本人大一學了C語言後的課程設計: 以下是大體流程圖: 這是我的執行程式碼: #include<stdio.h> #include<windows.h> #include&
js-->貪吃蛇小遊戲,能成功玩
function 小遊戲 absolute images 貪吃蛇 <!doctype html><html lang="en"><head> <meta charset="UTF-8"> <title>貪吃蛇小遊戲</tit
使用前端原生 js,貪吃蛇小遊戲
oct 新的 生成 方便 描述 logs turn asc 轉動 好久好久,真的是好久好久沒來寫過了,因為最近有點小忙。不過即使是忙,也也還是寫了兩個小遊戲,其中一個就是這個,貪吃蛇啦。 算是一個小練手了,這個是在有點太簡單了,只是第一次寫這種小遊戲,還是零零星星花了三
貪吃蛇小遊戲
C/C++MOVE__BOX部分:代碼如下#include<iostream>#include<Windows.h>#include <conio.h>using namespace std;void PutPlace(int x,int y);//設定輸出位置void c
JS貪吃蛇小遊戲
ttr etime opened IE title 跨瀏覽器 tac 再次 key 效果圖展示: 具體實現代碼如下: (1)html部分 1 !DOCTYPE html> 2 <html> 3 <head> 4
Android-貪吃蛇小遊戲-分析與實現-Kotlin語言描述
otl bject vid oid 小遊戲 同時 們的 http 畫布 Android-貪吃蛇小遊戲-分析與實現-Kotlin語言描述 Overview 本章的主要的內容是貪吃蛇小遊戲的分析和實現,關於實現的具體代碼可以在,文章底部的github的鏈接中找到。 整個遊戲通過
Java實現貪吃蛇小遊戲(附完整原始碼)
今天我就從零開始來完成這個小遊戲,完成的方式也是一步一步的新增功能這樣的方式來實現。 第一步完成的功能:寫一個介面 大家見到的貪吃蛇小遊戲,介面肯定是少不了的。因此,第一步就是寫一個小介面。 實現程式碼如下: 第二步完成的功能:在介面上畫成一格一格的 我們見過的貪吃蛇遊戲
JavaScript做貪吃蛇小遊戲
<body> <h1 >貪吃蛇</h1> <h2 id="score">0</h2>
js貪吃蛇小遊戲(相容ie8)DOM,BOM操作
效果圖 本篇將使用JavaScript 編寫一個貪吃蛇的小遊戲,採用OOP(面向物件)程式設計 基本沒有CSS樣式和HTML結構,主要是體會js操作 HTML程式碼 <div class="map"></div> &
java 貪吃蛇小遊戲效果圖加原始碼
今天寫了一個貪吃蛇的小遊戲用來練手,在流程控制方面也沒有封裝方法進行簡化,不過作為鍛鍊流程控制是很好的。 下面附上自己的原始碼 package com.oracle; import java.awt.Graphics; import java.awt.Image
使用opengl製作簡易貪吃蛇小遊戲
#include<iostream> #include<algorithm> #include<functional> #include<cstdlib> #include<cstdio> #include<g
C++控制檯貪吃蛇程式碼
1 #include"Snake_Class.h" 2 #include<iostream> 3 #include<fstream> 4 #include<ctime> 5 #include<cstdlib> 6 7 //獲取緩衝區控制代碼
用arduino編寫貪吃蛇小遊戲(完整程式碼)
用arduino編寫貪吃蛇小遊戲 裡面有大量的程式碼註釋,希望能真的幫助到電子愛好者。 工具 : 硬體:arduino UNO 、搖桿模組(控制貪吃蛇前後左右移動、 OLED 螢幕 軟體:arduino IDE1.8.2版本(基本上大於1.6版本,就能使用) 咱
好玩的貪吃蛇小遊戲,有趣極了!
(function ($) { $.fn.game1 = function (options) { var mainDiv = $(this); var defaults = { speed:150,//速度 leftSteps:50, topSteps:30 }; var opts = $.extend(d
android 簡單的貪吃蛇小遊戲
貪吃蛇是一款經典的小遊戲,遊戲比較簡單,實現也比較簡單。 本篇部落格將詳細介紹我自己寫的貪吃蛇的思路以及實現方式。 首先我們需要在遊戲介面將遊戲區域劃分成無數個小方格,類似下圖 畫布(遊戲區域)的寬為 width 高為 height ,列數 sizex=width/pointSiz