用c++實現遊戲2048---前三步
利用c++實現遊戲2048(命令列版)
寫在前面
在知乎上偶爾看到有人利用寫這種小程式練手,正好最近剛考完期末考試,所以就花了一個晚上寫了一下,也簡單的寫了一個2048.
以下是效果圖。
之前沒有用c++寫過比較大型的內容,對c++的理解也不是很深。所以經過這一次編寫,對遊戲演算法的理解以及c++多檔案之間的呼叫有了更深刻的理解。
在寫之前,我先簡單的構思了以下整個遊戲會分成哪幾個部分,私以為可以簡單的分為六個部分:
- 初始化遊戲地圖
- 在遊戲地圖內格子隨機生成一個數字
- 在螢幕上顯示出地圖
- 玩家輸入操控指令
- 程式對玩家的指令進行相應移動與合併
- 判斷遊戲是否結束,若沒有結束就跳到2,否則跳出
我發現這六點當中,只有第5點最有難度,也就是如何去移動整個錶盤中的元素,如何判別是否可以合併,四個方向上的移動合併有什麼共同點和差別,如何合併等內容。其他5點就很簡單了,基本上沒有這麼複雜的邏輯。
下面我就以這6點分別進行講解。
主程式
將主程式放在單獨的一個檔案內
//source.cpp
#include <iostream>
#include <Windows.h>
#include "OperateMap.h"
#include "Parameter.h"
using namespace std;
int main() {
//遊戲地圖
int MAP[MAP_SIZE][MAP_SIZE];
//初始化地圖
Initlize(MAP);
bool isFull = false;
int score = 0;
while (!isFull) {
//重新整理視窗
system("cls");
//生成數字
Generate(MAP);
//顯示地圖
ShowMap(MAP, score);
//輸入指令
char command;
cin >> command;
//移動地圖
MoveMap(MAP, command, score);
//是否結束?
isFull = IsOver(MAP);
}
system("pause");
return 0;
}
可以看出我引用了兩個自定義的檔案,即OperateMap.h和Parameter.h。
OperateMap.h定義了主函式中所用到的Initlize(), Generate(), ShowMap(), MoveMap(), IsOver()等函式。
Parameter.h則定義了一些重要的引數,諸如地圖大小MAP_SIZE。
程式的邏輯比較容易看懂,就是很簡單的判斷isFull是否為ture,也就是地圖滿了沒,如果滿了,那就是遊戲結束。
初始化地圖
初始化地圖所用到的函式為Initlize(),具體實現過程如下
void Initlize(int(&MAP)[MAP_SIZE][MAP_SIZE]) {
/*初始化地圖MAP*/
cerr << "-----Initlize Finish!" << endl;
for (int i = 0; i < MAP_SIZE; i++) {
for (int j = 0; j < MAP_SIZE; j++) {
MAP[i][j] = 0;
}
}
}
也就是通過引用傳遞MAP將其內所有元素設定為0.
隨機生成數字
在上面已經將地圖初始化了,但是全部格點都是0,在呈現給玩家看之前就需要先隨機生成一個點,這一步就是解決這一個問題的。
在剛開始的時候,我是從整個地圖中隨機生成一個座標,然後賦值2或者4。但是這樣子會讓程式效率十分低下,因為在後期格子只有少數幾個為0的情況下,隨機很難直接隨機到那幾個點,所以會導致不斷的生成座標點,效率極其低下。
為此做的對應的修改就是,首先將地圖遍歷一遍,記錄當前為0的格點,然後從這些格點當中抽出一個賦值為2或4即可。
對應的程式碼如下
void Generate(int(&MAP)[MAP_SIZE][MAP_SIZE]) {
/*在地圖中生成隨機數*/
//判斷生成2還是4
int randNum[2] = { 2, 4 };
int chose24;
if (Rand021() <= 0.5) chose24 = 2;
else chose24 = 4;
int noZeroMAP[MAP_SIZE*MAP_SIZE][2], noZeroNum = 0;
//將不是0的格子儲存下來, 從中選出一個生成
for (int i = 0; i < MAP_SIZE; i++) {
for(int j = 0; j < MAP_SIZE; j++) {
if (MAP[i][j] != 0) {
noZeroMAP[noZeroNum][0] = i;
noZeroMAP[noZeroNum][1] = j;
noZeroNum++;
}
}
}
int generatePos = RandA2B(0, noZeroNum-1);
MAP[noZeroMAP[noZeroNum][0]][noZeroMAP[noZeroNum][1]] = chose24;
}
這裡用到的Rand021()是隨機生成0到1之間的隨機浮點數,和RandA2B()是隨機生成A到B之間的隨機整數,具體定義如下
//Rand.cpp
#include <cstdlib>
#include <ctime>
double Rand021() {
srand((int)time(0));
return rand() / double(RAND_MAX);
}
int RandA2B(int A, int B) {
srand((int)time(0));
return rand() % (B - A + 1) + A;
}
顯示地圖
顯示地圖相當於沒什麼技術含量了,就是簡單粗暴的直接輸出就好。不過為了地圖更好看,將0替換成-進行輸出。
void ShowMap(int(&MAP)[MAP_SIZE][MAP_SIZE], int score) {
/*輸出地圖*/
cout << "Now Your Game Map is: " << endl;
cout << "---------------------------------" << endl;
for (int i = 0; i < MAP_SIZE; i++) {
for (int j = 0; j < MAP_SIZE; j++) {
if (MAP[i][j] == 0) cout << " " << "-";
else cout << " " << MAP[i][j];
}
cout << endl;
}
cout << "---------------------------------" << endl;
cout << "Now Your Score is: " << score << endl;
cout << "Plase Move Map(up:w down:s left:a right:d): ";
}
告一段落
下一部分就是移動地圖的內容了,內容比較多,所以我放在下一篇文章中進行講解。
如果有幫助的話還麻煩點個關注點個贊噢~
相關推薦
用c++實現遊戲2048---前三步
利用c++實現遊戲2048(命令列版) 寫在前面 在知乎上偶爾看到有人利用寫這種小程式練手,正好最近剛考完期末考試,所以就花了一個晚上寫了一下,也簡單的寫了一個2048. 以下是效果圖。 之前沒有用c++寫過比較大型的內容,對c++的理解也不是很
有限元剛度矩陣的一維變頻寬儲存用C++實現(三)
在有限元剛度矩陣的一維變頻寬儲存用C++實現(二)中,我們已經把總體剛度矩陣[K]中下三角部分的帶內元素順利存入pGK陣列中,現在我們來討論如何從pGK陣列中取出[K]內的任意元素。 從儲存了總剛矩陣[K]中的帶內元素的一維陣列pGK中取出總剛矩陣[K]的元素,主要是建立總
用c#實現拼圖遊戲
上學期程式是設計實驗之二,用c#實現一個拼圖遊戲 (一)需求:(這個需求書寫較為簡單) 圖片:有圖 切割:拼圖不是一個圖,我們需要把一個整圖它切割成N*N的小圖 打亂:把這N*N的小圖打亂順序,才能叫拼圖qwq 判斷:判斷拼圖是否成功 互動:選擇滑鼠點選拖動
用C#實現貪吃蛇遊戲
先說了,如果不會GDI+,類的定義這些基礎東西的,請先搜尋相關貼子學習。 這次教大家用C#做一個簡單的貪吃蛇遊戲。 先介紹用到的技術: GDI+ 定義類 列舉 因為C#是一門面向物件的語言,我們不用把所有程式碼都寫在一個窗體上,應該有一個分層思想(介面還介
用C++實現連連看程式碼原理及解析(三)——消除演算法
C++連連看消除程式碼的實現,過程比較複雜。 【加入我們的學習群(C/C++群:892643663;Java群:957907127),大牛線上為您提供服務,還有免費編譯大禮包和視訊教程贈送哦】 以下是程式碼: #include<iostream> #include&l
用C++實現二叉樹的三種遍歷方式
- 非遞迴實現程式碼: #include<stdio.h> #include<stdlib.h> #include"data_structure.h" //建立一棵二叉樹 BTree create_tree() { BTree
VS下用C++實現的簡單3D射擊遊戲(附遊戲檔案與源工程程式碼)
記不得什麼時候開始感興趣寫遊戲程式碼了。開始的時候就只是寫一些簡單的小遊戲,打檯球,開小車,走迷宮,用一些2Dgraphics庫,完成每個小作品後都很開心。後來一想,在現在的計算機裝置條件下,2D太簡陋了,於是開始著手做一個3D賽車遊戲。說是賽車,實際上也就只有一輛小車。模
用C++實現約瑟夫環的問題
content 人在 -h tel padding next family bsp sun 約瑟夫問題是個有名的問題:N個人圍成一圈。從第一個開始報數,第M個將被殺掉,最後剩下一個,其余人都將被殺掉。比如N=6,M=5。被殺掉的人的序號為5,4,6。2。3。最後剩下1
用c++實現高精度加法
strlen 數位 cout col 代碼 code pre 操作數 eof c++實習高精度加法 最近遇到一個c++實現高精度加法的問題,高精度問題往往十復雜但發現其中的規律後發現並沒有那麽復雜,這裏我實現了一個整數的高精度加法,主要需要註意以下幾點: 1:將所需
用c實現的各種排序的方法
else print switch %d [] code article 選擇 ++ #include <stdio.h> void swap(int *a, int *b); void bubble_sort(int a[], int n); void
用OpenCV實現Photoshop算法(三): 曲線調整
快的 nes copy eve pla 很快 view 特點 色值 http://blog.csdn.net/c80486/article/details/52499919 系列文章: 用OpenCV實現Photoshop算法(一): 圖像旋轉 用OpenCV實現Photo
【C/C++】:用C實現輸出日期的陰歷日子
print http this while lunar void 大小 oid pan 前言 輸出陰歷一直是個老大難的問題。由於陰歷日子沒有規律。所以這裏須要做的就是通過打表的算法做到輸出陰歷日子,可是非常多人都不太了解原理,我這裏就給大家送上了一個福
用 C# 實現一個簡單的 Rest Service 供外部調用
message [] operation rem adk www span method title 用 C# 實現一個簡單的 Restful Service 供外部調用,大體總結為4點: The service contract (the methods it o
C++實現利用(前序和中序生成二叉樹)以及(二叉樹的鏡像)
lse pub 非遞歸 ace 方法 [] reorder spa push #include<iostream> #include<string.h> #include<stack> using namespace std; type
學習筆記-用c實現三角函數的計算
math \n 數值 print spa 轉化 弧度 can ID 剛剛編好,記錄一下: #include <stdio.h> #include <math.h> int main(void) { while(1) {
RabbitMQ初探--用C#實現通訊服務
download gin summary color 發送消息 sta 過程調用 change rod MQ全稱為Message Queue, 消息隊列(MQ)是一種應用程序對應用程序的通信方法。應用程序通過讀寫出入隊列的消息(針對應用程序的數據)來通信,而無需專用連接來鏈
用 UniRx 實現 Timeline 式的異步操作
lin code property set pos llb 等待 all 適合 沒接觸 UniRx 之前,我在 Unity 中通常用 Coroutine 或 Callback 來實現異步操作。根據我的任務,一般都是去實現遊戲組件的演出,比如:敵方角色圖形顯示後,我方角
用c#實現文件的讀取和系列操作
static filename ros ima git int lin {0} ase Gitee代碼鏈接:https://gitee.com/hyr5201314/workcount 1.解題思路 首先要先讀取文件,然後調用函數實現返回文件的字符數,行數,單詞總數。用
用c實現一個跳動的小球
#include<stdio.h> #include<stdlib.h> int main() { int x=1,y=1,dirx=1,diry=1; for(;;) { int line,col; fo
用c++實現環形陣列的最大子陣列之和(結對)
結對作業 1.分解問題,將環形陣列,剪開變成一個一維陣列。 2.用一維陣列的最大子陣列和解決。 對於一個環形陣列,對每一個一維陣列的表示共有n-1種 原始碼如下: 1 #include<iostream> 2 using namespace std; 3 int max_