C++在控制檯上實現2048遊戲
剛學完C++基礎,想找一個專案練練手,萌發寫一個2048的遊戲的想法,既然有想法,就是幹!!自己第一次獨立完成一個專案(也不是全部是獨立的,開始之前參考過程式碼),雖然只有幾百行程式碼,但這是一個開始,朝著自己夢想一步一個腳印。fighting!! 首先在網上找了一個2048的專案,http://www.jb51.net/article/51111.htm,用這個程式碼運行了一下,大概有了整體的認識,並且粗略的看了一下模組。在這個程式中,有一些bug: ①和我們平常玩的2048不同,這個遊戲生成的隨機數是2的次方,我們一般只會生成2和4; ②遊戲中每一次移動後生成新數的位置是第一個空格,降低遊戲的體驗; ③遊戲只有兩個相鄰的大小相同的數才會結合,中間存在0的話,不會結合;其實是由於每次移動只會移動一格導致的; ④遊戲中含有零,看起來不舒服; 雖然有這些問題,但是這個程式給了我整體的思路,讓我能夠自己接下來走自己的路。
接下來是自己做專案遇到的一些問題和解決方法,最後附上自己的原始碼
一、控制檯如何從鍵盤上獲得方向鍵
之前簡單的以為方向鍵就是簡單的ASCII碼,too young too simple。 http://blog.csdn.net/feilong911hao/article/details/42081967,看完這篇部落格之後弄明白。之前問過很多人,各種搜也沒找到,感謝博主和萬能的CSDN。
總結:①方向鍵有兩個位元組,第一個位元組不是ASCII碼,後面一個位元組才是
②使用getch()沒有回顯的從鍵盤輸入。
程式碼:
//返回值
// 1 上 72
// 2 下 80
// 3 左 75
// 4 右 77
int get_direction()
{
char c1,c2;
int ret = 0;
c1 = getch();
if (!isascii(c1))
{
c2 = getch();
switch(c2)
{
case 72: ret = 1;break;
case 80: ret = 2;break;
case 75: ret = 3;break;
case 77 : ret = 4;break;
default: break;
}
}
return ret;
}
二、隨機數的生成
使用srand()和rand(),srand()使用time(0)當前的時間當做隨機數種子,避免偽隨機數;
http://wenku.baidu.com/link?url=XkB5uCfIkKL_LyBqEoM5ueoxl29mwXtEyfAzGSwfHsgGRB3-N9eR0O0EFoElSa1-YISWXb1mevClbOLytYDhFMoJrnrkhnlxK-brQsslt4O
程式碼:
//隨機產生一個0-n-1的數字
int rand_pro_s(int n)
{
srand(time(0));
int k = rand()%n;
return k;
}
三、移動(難點)
將移動分為兩步,第一步是合併相鄰兩個相同的數字(中間可以含有0);第二步,方格里面的數字全部向移動的方向移動,去除中間的零。
第一步:之前沒有理清思想,只合並了相鄰的兩個數字,沒有考慮含有0的情況。思路:遍歷每一行或者列,k來存放每一個非零的數,遇見一個非零,如果和k相等,那麼就將這個數變為2k,另外的數變為0.
第二步:使用一個k來作為記錄非零的個數,然後遍歷。
程式碼
void up_dir()
{
//完成第一步
int i,j;
for (i=0; i<4; i++)
{
/*for (j=0; j<3;)
{
if (array[j][i] == array[j+1][i])
{
array[j][i] = array[j][i] + array[j+1][i];
array[j+1][i] = 0;
j += 2;
continue;
}
j++;
}*/
int k = 0;
int x = 0;
int y = 0;
for (j=0; j<4; j++)
{
if (k==array[j][i] && k!=0)
{
//array[x][y] = 2*array[x][y];
//array[x][y] = 2*k;
array[x][y] = 2*k;
array[j][i] = 0;
k = 0;
continue;
}
if (array[j][i]!=0)
{
k = array[j][i];
//此處的bug是x和y分別應該儲存j和i
x = j;
y = i;
}
}
}
for (i=0; i<4; i++)
{
int k = 0;
for (j=0; j<4; j++)
{
//if (array[j][i])//此處有bug,假如k和j相等
if (array[j][i])
{
if (k != j)
{
array[k][i] = array[j][i];
array[j][i] = 0;
}
k++;
}
}
}
insert_num();
system("cls");//清屏
display();
}
四、如何隨機插入一個數(難點)
使用剩餘空格數N,並且將空格的座標記錄下來,生成1-N的隨機數n,並且在第n個空格插入2或者4.
tips:①vector<vector<int>> v(16 ,vector<int>());vector中含有vector不能定義為空
②插入數字的時候需要判斷空格數
五、如何判定遊戲結束
看是否能夠水平移動或者豎直移動,在移動操作的函式中修改,不改變二維陣列的值即可
程式所有的程式碼
#include <iostream>
#include <cstdlib> //rand(),time()
#include <ctime>
#include <conio.h> //getch()
#include <ctype.h> //
#include <vector>
#include <math.h> //pow
#include <iomanip> //setw
using namespace std;
int array[4][4] = {0};//申請全域性陣列作為方格里面的數
//0—3的隨機數產生
int rand_pro()
{
srand(time(0));
int k = rand()%4;
return k;
}
////////////////////////////////////介面函式////////////////////////////////////////////////////////////
//之前的介面
void display1()
{
int i,j;
for (i=0; i<4; i++)
{
for(j=0; j<4; j++)
{
cout<<array[i][j]<<" ";
}
cout<<endl;
}
cout<<"----------------------------------"<<endl;
}
//介面美化,不顯示0,顯示外框
void display2()
{
int i,j;
for (i=0; i<4; i++)
{
for(j=0; j<4; j++)
{
if (array[i][j] == 0)
{
cout<<" "<<" ";
}
else
cout<<array[i][j]<<" ";
}
cout<<endl;
}
cout<<"----------------------------------"<<endl;
}
void display() //顯示棋盤
{
cout<<setw(46)<<"X2048 by ziyunmumu"<<endl;
cout<<setw(50)<<" |-----------------------|"<<endl;
for(int i=0;i<=3;i++)
{
cout<<setw(24)<<"";
for(int j=0;j<=3;j++)
{
//SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_RED);
if (array[i][j] == 0)
{
cout<<setw(2)<<"|"<<setw(4)<<" ";
}
else
cout<<setw(2)<<"|"<<setw(4)<<array[i][j];
if(j==3)
{
cout<<setw(2)<<"|"<<endl;
cout<<setw(50)<<" |-----------------------|"<<endl;
}
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////新遊戲的開始////////////////////////////////////////////////////////////
void new_game()
{
//初始化內容
int i,j;
for(i=0;i<4;i++)
{
for (j=0;j<4;j++)
{
array[i][j] = 0;
}
}
int m = rand_pro();
int n = rand_pro();
array[m][n] = 2;
display();
}
////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////
//隨機產生一個0-n-1的數字
int rand_pro_s(int n)
{
srand(time(0));
int k = rand()%n;
return k;
}
//隨機產生一個1-n的數字
int rand_pro_ss(int n)
{
srand(time(0));
int k = rand()%n+1;
return k;
}
//統計0的個數,並且通過一個vector來存放座標
//p需要判斷
vector<vector<int>> zero_num(int* p)
{
int i,j;
int k = 0;
vector<vector<int>> v(16 ,vector<int>());
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (array[i][j] == 0)
{
v[k].push_back(i);
v[k].push_back(j);
k++;
}
}
}
*p = k;
return v;
}
//隨機插入一個數字,通空格的個數隨機插入
//返回值為true就說明成功插入,否則未能插入
bool insert_num()
{
int k = 0;
vector<vector<int>> v;
v = zero_num(&k);
if (k>0)
{
int m = rand_pro_s(k);
int x = v[m][0];
int y = v[m][1];
array[x][y] = pow(2.0,rand_pro_ss(2));
return true;
}
return false;
}
////////////////////////////////////獲得鍵盤方向////////////////////////////////////////////////////////////
//獲取方向
//返回值
// 1 上 72
// 2 下 80
// 3 左 75
// 4 右 77
int get_direction()
{
char c1,c2;
int ret = 0;
c1 = getch();
if (!isascii(c1))
{
c2 = getch();
switch(c2)
{
case 72: ret = 1;break;
case 80: ret = 2;break;
case 75: ret = 3;break;
case 77: ret = 4;break;
default: break;
}
}
return ret;
}
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////移動操作////////////////////////////////////////////////////////////
//上下左右操作
//操作分為兩步,首先將相鄰的相同數字加起來,然後去除空格
//操作完之後需要插入數字
//之前分為兩步的想法有問題,假如是兩個相同數字之間有0的話,也是可以結合的
void up_dir()
{
//完成第一步
int i,j;
for (i=0; i<4; i++)
{
/*for (j=0; j<3;)
{
if (array[j][i] == array[j+1][i])
{
array[j][i] = array[j][i] + array[j+1][i];
array[j+1][i] = 0;
j += 2;
continue;
}
j++;
}*/
int k = 0;
int x = 0;
int y = 0;
for (j=0; j<4; j++)
{
if (k==array[j][i] && k!=0)
{
//array[x][y] = 2*array[x][y];
//array[x][y] = 2*k;
array[x][y] = 2*k;
array[j][i] = 0;
k = 0;
continue;
}
if (array[j][i]!=0)
{
k = array[j][i];
//此處的bug是x和y分別應該儲存j和i
x = j;
y = i;
}
}
}
for (i=0; i<4; i++)
{
int k = 0;
for (j=0; j<4; j++)
{
//if (array[j][i])//此處有bug,假如k和j相等
if (array[j][i])
{
if (k != j)
{
array[k][i] = array[j][i];
array[j][i] = 0;
}
k++;
}
}
}
insert_num();
system("cls");//清屏
display();
}
void down_dir()
{
//完成第一步
int i,j;
for (i=0; i<4; i++)
{
/*for (j=3; j>0;)
{
if (array[j][i] == array[j-1][i])
{
array[j][i] = array[j][i] + array[j-1][i];
array[j-1][i] = 0;
j -= 2;
continue;
}
j--;
}*/
int k = 0;
int x = 0;
int y = 0;
for (j=3; j>=0; j--)
{
if (k==array[j][i] && k!=0)
{
array[x][y] = 2*k;
array[j][i] = 0;
k = 0;
continue;
}
if (array[j][i]!=0)
{
k = array[j][i];
x = j;
y = i;
}
}
}
for (i=0; i<4; i++)
{
int k = 3;
for (j=3; j>=0; j--)
{
if (array[j][i])
{
if (k != j)
{
array[k][i] = array[j][i];
array[j][i] = 0;
}
k--;
}
}
}
insert_num();
system("cls");//清屏
display();
}
void left_dir()
{
int i,j;
for (i=0; i<4; i++)
{
int k = 0;
int x = 0;
int y = 0;
for (j=0; j<4; j++)
{
if (k==array[i][j] && k!=0)
{
array[x][y] = 2*k;
array[i][j] = 0;
k = 0;
continue;
}
if (array[i][j]!=0)
{
k = array[i][j];
x = i;
y = j;
}
}
}
for (i=0; i<4; i++)
{
int k = 0;
for (j=0; j<4; j++)
{
if (array[i][j])
{
if (k != j)
{
array[i][k] = array[i][j];
array[i][j] = 0;
}
k++;
}
}
}
insert_num();
system("cls");//清屏
display();
}
void right_dir()
{
//完成第一步
int i,j;
for (i=0; i<4; i++)
{
int k = 0;
int x = 0;
int y = 0;
for (j=3; j>=0; j--)
{
if (k==array[i][j] && k!=0)
{
array[x][y] = 2*k;
array[i][j] = 0;
k = 0;
continue;
}
if (array[i][j]!=0)
{
k = array[i][j];
x = i;
y = j;
}
}
}
for (i=0; i<4; i++)
{
int k = 3;
for (j=3; j>=0; j--)
{
if (array[i][j])
{
if (k != j)
{
array[i][k] = array[i][j];
array[i][j] = 0;
}
k--;
}
}
}
insert_num();
system("cls");//清屏
display();
}
////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////遊戲結束////////////////////////////////////////////////////////////
//判斷遊戲結束
//將求解最大值和判斷2048糅合在一起
bool iswin()
{
int i,j;
for (i=0; i<4; i++)
{
for (j=0; j<4; j++)
{
if (array[i][j] == 2048)
{
return true;
}
}
}
return false;
}
//建構函式can_up...,不能改變全域性變數的值
//只需要兩個方向,水平或者垂直;
bool can_ver()
{
int i,j;
for (i=0; i<4; i++)
{
int k = 0;
for (j=0; j<4; j++)
{
if (k==array[j][i] && k!=0)
{
return true;
}
if (array[j][i]!=0)
{
k = array[j][i];
}
}
}
return false;
}
bool can_hor()
{
int i,j;
for (i=0; i<4; i++)
{
int k = 0;
for (j=3; j>=0; j--)
{
if (k==array[i][j] && k!=0)
{
return true;
}
if (array[i][j]!=0)
{
k = array[i][j];
}
}
}
return false;
}
//怎麼做到提前預判已經不能左右移動了
bool islose()
{
int k = 0;
zero_num(&k);
if (k>0)
{
return false;
}
if (can_ver() || can_hor())
{
return false;
}
return true;
}
////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
new_game();
int dir = 0;
while(1)
{
if (iswin())
{
cout<<"you win"<<endl;
break;
}
if (islose())
{
cout<<"you lose"<<endl;
break;
}
dir = get_direction();
switch(dir)
{
case 1: up_dir();break;
case 2: down_dir();break;
case 3: left_dir();break;
case 4: right_dir();break;
default:break;
}
}
system("pause");
}
相關推薦
C++在控制檯上實現2048遊戲
剛學完C++基礎,想找一個專案練練手,萌發寫一個2048的遊戲的想法,既然有想法,就是幹!!自己第一次獨立完成一個專案(也不是全部是獨立的,開始之前參考過程式碼),雖然只有幾百行程式碼,但這是一個開始,朝著自己夢想一步一個腳印。fighting!!
c++實現2048遊戲(控制檯)
#ifndef CGAME_H #define CGAME_H #include <windows.h> #include <String> #define ROW 4 //格子總行數 #define COLUMN 4 //格子總列數 class cGame { pub
C語言實現2048遊戲
文章目錄列印介面生成隨機數是否獲勝移動遊戲程式碼: 2048遊戲在很長一段時間內是一款很火的小遊戲。 遊戲要求: 最開始兩個隨機數 每次生成一個隨機數2或者4,生成4的概率是1/10 鍵盤上下左右鍵控制遊戲的走向 當出現2048數字時,玩家獲勝 列印介面
C語言介面實現2048小遊戲
這是我在大一第二學期(兩年前)為了參加比賽,自學後寫的一個Dome,拿出來和大家分享一下,程式碼為兩年前的程式碼,未改動,優化以及各式可能很一般,請見諒。 #include "stdio.h" #include "stdlib.h" #include "time.h" #d
詳解!C語言程式設計實現小遊戲“三子棋”
今天我們來程式設計實現一個充滿童趣的小遊戲“三子棋” 先來說一下三子棋的規則: 三子棋又叫九宮棋、圈圈叉叉、一條龍等。 將正方形對角線連起來,或相對兩邊依次擺上三個雙方棋子, 總之只要將自己的三個棋子走成一條線, 對方就算輸了。 不用再過多解釋了,相信大家一定都玩過! 那麼,該
【C語言】實現小遊戲掃雷
用C語言實現掃雷小遊戲,一共有三部分的程式碼 game.h #ifndef __GAME_H_ #define __GAME_H_ #include <stdio.h> #include <stdlib.h> #include <time.h> #def
【C語言】實現小遊戲三子棋
三子棋的規則:在九宮格棋盤中,只要橫、豎、對角線都能走成一條直線,就贏了。 我將實現三子棋遊戲的程式分為三個部分 第一部分:標頭檔案 game.h #ifndef _GAME_H_ #define _GAME_H_ #include <string.h> #include
C++控制檯貪吃蛇小遊戲詳細教程
遊戲截圖 開始動畫: 遊戲過程: 遊戲架構設計 該遊戲的玩法簡單,玩家通過鍵盤方向鍵控制蛇上下左右移動,吃到食物得分並增長,碰到牆或者自己的身體則死亡,遊戲結束。 整個遊戲其實就是一個無窮的迴圈,直到退出遊戲時退出迴圈
c語言簡單實現掃雷遊戲
對於掃雷遊戲,我相信每個人都玩過,大概瞭解它應有的操作和大概的原理。那我們應該怎樣著手去實現掃雷遊戲呢…… 首先對於雷陣這個介面,就想到可以定義的一個二維陣列,我們不可能把把雷的位置也顯示出來,所有需要定義2個二維陣列:mine用來佈雷,show用來顯示掃雷
c語言編寫的2048遊戲程式碼,大家可以參考一下這些
2048_launcher.c#include <stdio.h> #include <stdlib.h> #include <Windows.h> void main() { printf("正在啟動中,請稍後!\n"); Sleep(
C++實現2048小遊戲(控制檯版的)
無聊,在公司寫了個2048小遊戲的程式,聊以自娛。(事實是我手機壞了,沒得玩)。 很簡單,直接上程式碼了。 #include <iostream> #include <windows.h> #include <ctime> using
用C++、Qt實現的小遊戲2048
圖片 explicit AC 向上 類的構造函數 += cli 而後 遊戲 窗口布局與遊戲截圖: 實現思路: 1.使用二維數組模擬整個遊戲網格,並將二維數組中每個數的大小用作遊戲中每個網格中的數據。 2.將對遊戲的數據及數據的操作(即玩家的操
c++實現2048[牛客網、控制檯]
1.前言 剛學完c++基礎,找個專案練練手,於是上牛客網找了個2048練練手,文章最後給出原始碼 2.簡介 一次只能合併相鄰的兩個數字,例如 [2 2 2 2] ,向右合併以後是 [空 空 4 4] ,不是 [空 空 空 8] 每次合併的時候,合併方向優先順序高,例如 [空
C# 控制檯實現的五子棋遊戲
今天用到陣列在控制檯做了一個五子棋遊戲,實現如下: static void Main(string[] args) { string[,] QP = new string[17, 17];
C++ 實現 2048 (控制檯版)
// 山寨黑框框 2048 #include #include #include using namespace std; #define rand(x) ( rand() % (x) ) #define UP 1 #define DOWN 2 #define LEFT 3 #define
2048遊戲(java控制檯-原生jdk實現)
import java.util.Random; import java.util.Scanner; public class game_2048 { public static int score = 0; public static Random random
C語言在linux終端下實現2048小遊戲:第二版
原來我轉載過一個機遇ncurses的2048,今天無聊自己手寫了一個,看下我的目錄結構: $ tree ../2048/ ../2048/ ├── 2048.c ├── 2048.h └── main.c 0 directories, 3 files 2048.h
C++ 控制檯版 2048小遊戲
先說說2048遊戲的規則: 開始的時候空格中會出現兩個數字(只能為2或者4),使用者可以選擇上下左右鍵進行移動,數字們整體沿著方向移動,中間不存在空格,如果相鄰的兩個數字相等,那麼合併至沿著方向的後一個,更新最大值,總分數加上新出現的數字。當出現2048,Win。或者沒有空
C#實現2048小遊戲
要實現這個簡單的小遊戲主要在於實現一個方向移動 數字的移動及合併該如何處理 然後其它方向的邏輯是相同的 我做的這個基本功能實現了 主要分為三個類 Box.cs格子類(一些格子裡儲存的資料,行下標,列下標,是否合併過的開關。。) Grid.cs網格類(主要演算法在裡
C++練習例項———控制檯程式碼實現坦克大戰小遊戲
坦克大戰是一款經典的遊戲,今天我來介紹一個在vs中僅用控制檯程式碼實現的坦克大戰小遊戲,在很多學校裡作為一個面對物件程式設計的大作業,對於學習C++的多型性很有幫助。程式的架構思路由老師提供,遊戲中用到了EasyX圖形庫,這個庫非常小巧輕便,下載地址:https://