C++小遊戲
一仁賴語穗 一和呂念潔 一勇阮心宥 陳飛妃
報告
簡報
程式
賴語穗、陳飛妃靈感
賴語穗、陳飛妃、呂念潔、阮心宥
工作分配
賴語穗、陳飛妃
賴語穗、陳飛妃、呂念潔、阮心宥
- 本作品為以最初版本的 2048 規則為基礎所開發的小遊戲。
- 遊戲在 4×4 的棋盤中進行,玩家透過鍵盤方向鍵控制方塊移動,使相同數字的方塊在滑動過程中碰撞並合併成更大的數字。
- 目標是逐步合成出 2048。
作品介紹

遊戲規則
- 每次移動後隨機在空格生成一個新方塊
3. 生成新方塊
- 棋盤填滿
- 且無任何相鄰方塊可以合併
4. 失敗條件
- 相同數字碰撞會合併
- 每次滑動中,每個方塊最多只能合併一次
2. 合併規則
1. 操作方式
- 使用鍵盤 WASD
- 每次移動時,整個棋盤的數字會往同一方向滑動
1. 操作方式
# CHAPTER 2
程式介紹
1
Discovery of requirements for a project.
2
Research into the project space, competitors and the market.
3
Creating a Plan that sets the requirements for the design and build phases.
5
Review and Iterate on the designs with testing of ideas, client feedback and prototypes.
4
Design a number of iterations that capture the plans and requirements.
6
Build the project to an MVP to test and evaluate. Iterate using these learnings.
#include<iostream>
#include<vector>//動態陣列
#include<cstdlib>//產生亂數
#include<ctime>//計算時間
#include<iomanip>//輸出格式
# PRESENTING CODE
標頭檔
using namespace std;
int a[4][4]={0},n=4;//初始棋盤生成
struct zero{//記錄空格的位置
int r, c;
};
# PRESENTING CODE
void rd(){
vector<zero>emp;
bool f=false;//不能放數字
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]==0){//可以放新數字
emp.push_back({i, j});//座標存進emp
f=true;//可以放數字的話
}
}
}
if(f){//可以放新數字
int r=rand()%emp.size();//限制在 0 ~ emp.size()-1
zero t=emp[r];//第 r 個座標存進 t
a[t.r][t.c]=(rand()%10==0)?4:2;//條件式 ? 成立時的值 : 不成立時的值;
}
}
# PRESENTING CODE
各函式功能 rd()
void p(){
system("cls");
cout<<"--- C++ 2048 GAME ---"<<endl;
string Border="+------+------+------+------+";//可愛的邊界
for(int i=0; i<n ; i++){
cout<<Border<<endl;//放出結界
for(int j=0; j<n ; j++){
cout<<"|";//每個格子中間的槓槓
if(a[i][j]==0){
cout<<setw(7);
}
else{
cout<<setw(6)<<a[i][j];//固定格子的寬度
}
}
cout<<"|"<<endl;//每個格子中間的槓槓
}
cout<<Border<<endl;//把格子輸出
cout<<"控制方式--->[W]是上 [S]是下 [A]是左 [D]是右"<<endl;
}
# PRESENTING CODE
各函式功能 p()
bool left(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=0 ; j<n ; j++){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[i][k-1]==0){//如果左邊沒東西的話,全部過去
a[i][k-1]=a[i][k];
a[i][k]=0;
k--;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=0 ; j<n ; j++){
if(a[i][j]!=0 && a[i][j]==a[i][j+1]){
a[i][j]*=2;
a[i][j+1]=0;
moved=true;
}
}
}
for(int j=0 ; j<n ; j++){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[i][k-1]==0){
a[i][k-1]=a[i][k];
a[i][k]=0;
k--;
moved=true;
}
}
}
return moved;//回報主程式
}
# PRESENTING CODE
各函式功能 left()
bool right(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=n-2 ; j>=0 ; j--){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n -1 && a[i][k+1]==0){//如果右邊沒東西的話,全部過去
a[i][k+1]=a[i][k];
a[i][k]=0;
k++;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=n-2 ; j>= 0 ; j--){
if(a[i][j]!=0 && a[i][j]==a[i][j+1]){
a[i][j]*=2;
a[i][j+1]=0;
moved=true;
}
}
}
for(int j=n - 2 ; j>=0 ; j--){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n - 1 && a[i][k+1]==0){
a[i][k+1]=a[i][k];
a[i][k]=0;
k++;
moved=true;
}
}
}
return moved;//回報主程式
}
# PRESENTING CODE
各函式功能 right()
bool down(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=n-2 ; j>=0 ; j--){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n -1 && a[k+1][i]==0){//如果下面沒東西的話,全部過去
a[k+1][i]=a[k][i];
a[k][i]=0;
k++;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=n-2 ; j>= 0 ; j--){
if(a[j][i]!=0 && a[j][i]==a[j+1][i]){
a[j+1][i]*=2;
a[j][i]=0;
moved=true;
}
}
}
for(int j=n - 2 ; j>=0 ; j--){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n - 1 && a[k+1][i]==0){
a[k+1][i]=a[i][k];
a[k][i]=0;
k++;
moved=true;
}
}
}
return moved;//回報主程式
}
# PRESENTING CODE
各函式功能 down()
bool up(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=0 ; j<n ; j++){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[k-1][i]==0){//如果上面沒東西的話,全部過去
a[k-1][i]=a[k][i];
a[k][i]=0;
k--;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=0 ; j< n ; j++){
if(a[j][i]!=0 && a[j][i]==a[j-1][i]){
a[j-1][i]*=2;
a[j][i]=0;
moved=true;
}
}
}
for(int j=0 ; j<n ; j++){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[k-1][i]==0){
a[k-1][i]=a[k][i];
a[k][i]=0;
k--;
moved=true;
}
}
}
return moved;//回報主程式
}
# PRESENTING CODE
各函式功能 up()
bool gameover(){
bool g = false;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(a[i][j] == 0){
g = true;
}else if(a[i][j] == a[i+1][j] && i < 3){
g = true;
}else if(a[i][j] == a[i- 1][j] && i > 0){
g = true;
}else if(a[i][j] == a[i][j+1] && j < 3){
g = true;
}else if(a[i][j] == a[i][j-1] && i > 0){
g = true;
}
}
}
return g;
}
# PRESENTING CODE
各函式功能 gameover()
int main() {
srand(time(0));
rd();
rd();
//2048一開始畫面上會有兩個數字,所以rd()呼叫兩次
p();
char t;
while(cin >> t){
if(!gameover()){
cout<<"--- GAME OVER ---";
break;
}
if(t == 'W'){
up();
rd();
p();
}else if(t== 'S'){
down();
rd();
p();
}else if(t == 'A'){
left();
rd();
p();
}else if(t == 'D'){
right();
rd();
p();
}
}
return 0;
}
# PRESENTING CODE
主程式
#include<iostream>
#include<vector>//動態陣列
#include<cstdlib>//產生亂數
#include<ctime>//計算時間
#include<iomanip>//輸出格式
using namespace std;
int a[4][4]={0},n=4;//初始棋盤生成
struct zero{//記錄空格的位置
int r, c;
};
void rd(){
vector<zero>emp;
bool f=false;//如果不能放數字
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
if(a[i][j]==0){//如果=0表示可以放新數字
emp.push_back({i, j});//把這個可以放新數字的座標存進emp
f=true;//如果這個地方可以放數字的話,f=true
}
}
}
if(f){//如果有空格
int r=rand()%emp.size();//結果限制在 0 ~ emp.size()-1
zero t=emp[r];//從 emp 裡取出第 r 個空格座標,存進 t
a[t.r][t.c]=(rand()%10==0)?4:2;//條件式 ? 成立時的值 : 不成立時的值;
}
}
void p(){
system("cls");
cout<<"--- C++ 2048 GAME ---"<<endl;
string Border="+------+------+------+------+";//可愛的邊界
for(int i=0; i<n ; i++){
cout<<Border<<endl;//放出結界
for(int j=0; j<n ; j++){
cout<<"|";//每個格子中間的槓槓
if(a[i][j]==0){
cout<<setw(6)<<" ";
}
else{
cout<<setw(6)<<a[i][j];//固定格子的寬度
}
}
cout<<"|"<<endl;//每個格子中間的槓槓
}
cout<<Border<<endl;//把格子輸出
cout<<"控制方式--->[W]是上 [S]是下 [A]是左 [D]是右"<<endl;
}
bool left(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=0 ; j<n ; j++){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[i][k-1]==0){//如果左邊沒東西的話,全部過去
a[i][k-1]=a[i][k];
a[i][k]=0;
k--;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=0 ; j<n ; j++){
if(a[i][j]!=0 && a[i][j]==a[i][j+1]){
a[i][j]*=2;
a[i][j+1]=0;
moved=true;
}
}
}
for(int j=0 ; j<n ; j++){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[i][k-1]==0){
a[i][k-1]=a[i][k];
a[i][k]=0;
k--;
moved=true;
}
}
}
return moved;//回報主程式
}
bool right(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=n-2 ; j>=0 ; j--){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n -1 && a[i][k+1]==0){//如果右邊沒東西的話,全部過去
a[i][k+1]=a[i][k];
a[i][k]=0;
k++;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=n-2 ; j>= 0 ; j--){
if(a[i][j]!=0 && a[i][j]==a[i][j+1]){
a[i][j]*=2;
a[i][j+1]=0;
moved=true;
}
}
}
for(int j=n - 2 ; j>=0 ; j--){
if(a[i][j]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n - 1 && a[i][k+1]==0){
a[i][k+1]=a[i][k];
a[i][k]=0;
k++;
moved=true;
}
}
}
return moved;//回報主程式
}
bool down(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=n-2 ; j>=0 ; j--){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n -1 && a[k+1][i]==0){//如果下面沒東西的話,全部過去
a[k+1][i]=a[k][i];
a[k][i]=0;
k++;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=n-2 ; j>= 0 ; j--){
if(a[j][i]!=0 && a[j][i]==a[j+1][i]){
a[j+1][i]*=2;
a[j][i]=0;
moved=true;
}
}
}
for(int j=n - 2 ; j>=0 ; j--){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k<n - 1 && a[k+1][i]==0){
a[k+1][i]=a[i][k];
a[k][i]=0;
k++;
moved=true;
}
}
}
return moved;//回報主程式
}
bool up(){
bool moved=false;
for(int i=0 ; i<n ; i++){
for(int j=0 ; j<n ; j++){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[k-1][i]==0){//如果上面沒東西的話,全部過去
a[k-1][i]=a[k][i];
a[k][i]=0;
k--;
moved=true;
}
}
for(int i=0 ; i<n ; i++){//遇到相同的數字就併過去
for(int j=0 ; j< n ; j++){
if(a[j][i]!=0 && a[j][i]==a[j-1][i]){
a[j-1][i]*=2;
a[j][i]=0;
moved=true;
}
}
}
for(int j=0 ; j<n ; j++){
if(a[j][i]==0){
continue;
}
int k=j;//如果用j的話會毀掉原本的計數器
while(k>0 && a[k-1][i]==0){
a[k-1][i]=a[k][i];
a[k][i]=0;
k--;
moved=true;
}
}
}
return moved;//回報主程式
}
bool gameover(){
bool g = false;
for(int i = 0; i < n; i++){
for(int j = 0; j < n; j++){
if(a[i][j] == 0){
g = true;
}else if(a[i][j] == a[i+1][j] && i < 3){
g = true;
}else if(a[i][j] == a[i- 1][j] && i > 0){
g = true;
}else if(a[i][j] == a[i][j+1] && j < 3){
g = true;
}else if(a[i][j] == a[i][j-1] && i > 0){
g = true;
}
}
}
return g;
}
int main() {
srand(time(0));
rd();
rd();
//2048一開始畫面上會有兩個數字,所以rd()呼叫兩次
p();
char t;
while(cin >> t){
if(!gameover()){
cout<<"--- GAME OVER ---";
break;
}
if(t == 'W'){
up();
rd();
p();
}else if(t== 'S'){
down();
rd();
p();
}else if(t == 'A'){
left();
rd();
p();
}else if(t == 'D'){
right();
rd();
p();
}
}
return 0;
}
# PRESENTING CODE
完整程式
Code
By 陳飛妃
Code
- 21