c++ 學習curses庫,2048簡單小遊戲

2048 簡單小遊戲

遊戲規則:

用W,S,A,D控制上下左右操作 Q退出,R重新開始
當某個位置得到2048時獲勝
不能再有新的操作時失敗
移動:
每次移動時,有兩個相同的撞在一起會疊加,每個數字一次移動只能疊加一次,從邊上開始往後疊加
如向左移動:空 2 2 2 左移動 -> 空 空 2 4, 2 2 2 2 左移動 -> 空 空 4 4

每次操作後都會隨機選擇兩個空位進行添加2或4,新出4的概率10%
如果沒有空位就不添加,只有一個添加一個
重新開始隨機兩個位置添加,其餘清空

運行結果:

在這裏插入圖片描述
在這裏插入圖片描述

依賴庫

linux:

sudo apt-get install libncurses5-dev 

編譯:

Linux/Mac: g++ 2048.cpp -l ncurses -o 2048 
Windows: g++ 2048.cpp C:\pdcurs36\wincon\pdcurses.a -I C:\pdcurs36\ -o 2048 

爲了嘗試一下curses庫,做了這個小遊戲,代碼有點醜有待改進

源代碼:

#include <string>
#include <string>
#include <vector>
#include <cstdlib>
#include <cstdio>
#include <stack>
#include <queue>
#include <ctime>
#include <iostream>
#include <curses.h>
using namespace std;
#define N 4 // 格子數
#define SI 5 //每個格子的字符長度
 // 遊戲狀態
#define S_FAIL   0
#define S_WIN    1
#define S_run 2
#define S_QUIT   3
class game2048 {
	public:
		const int offset = 12;
		game2048(): status(S_run) {
			restart();
		}
		int getstatus() {
			return status;
		}
		void processINPUT() {
			char c = getch();
			if (c >= 'a' && c <= 'z')
				c -= 32;
			if (status == S_run) {
				if (c == 'W') up();
				else if (c == 'S') down();
				else if (c == 'A') left();
				else if (c == 'D') right();
				nowstatus();
			}
			if (c == 'Q') status = S_QUIT;
			else if (c == 'R') restart();
		}
		void man() {
			clear(); //清空
			for (int i = 0; i <= N; ++i) {
				for (int j = 0; j <= N; ++j) {
					draw(2*i, offset+j*SI, '+');
					if (i != N) {
						draw(2*i+1, offset+j*SI, '|');
						if (j != N)
							drawnum(2*i+1, offset+(j+1)*SI-1, data[i][j]);
					}
					if (j != N) {
						for (int k = 1; k <= N; ++k)
							draw(2*i, offset+j*SI+k, '-');
					}
					
				}
			}
			mvprintw(2*N+2, -1/2, "W(UP),S(DOWN),A(LEFT),D(RIGHT),R(RESTART),Q(QUIT)");
			mvprintw(2*N+3, SI, "HCLG");	
			if (status == S_FAIL)
				mvprintw(3*N, SI, " YOU LOSE,PRESS R TO CONTINUE ");
			if (status == S_WIN)
				mvprintw(3*N, SI, " YOU WIN,PRESS R TO CONTINUE ");
		}
		void setTestData() {//調試用的測試數據
			for (int i = 0; i < N; ++i)
				for (int j = 0; j < N; ++j)
					data[i][j] = 16>>i>>j;
		}
		
	private:
		
	void nowstatus() {
		bool f = true;
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				if (data[i][j] == 0 || (j != N-1 && data[i][j] == data[i][j+1]) || (i != N-1 && data[i][j] == data[i+1][j])) f = false;
				if (data[i][j] == 2048) {
					status = S_WIN;
					return;
				}
			}
		}
		if (f) status = S_FAIL;
		return;
	}
	void left() {
		queue<int>q;
		for (int i = 0; i < N; ++i) {
			for (auto &j : data[i]) {
				if (j) {
					q.push(j);
					j = 0;
				}
			}
			int j = 0;
			while (!q.empty()) {
				data[i][j] = q.front();
				q.pop();
				if (!q.empty() && q.front() == data[i][j]) {
					q.pop();
					data[i][j]*=2;
				}
				++j;
			}
		}
		randNew();randNew();
	}
	void right() {
		stack<int>q;
		for (int i = 0; i < N; ++i) {
			for (auto &j : data[i]) {
				if (j) {
					q.push(j);
					j = 0;
				}
			}
			int j = N-1;
			while (!q.empty()) {
				data[i][j] = q.top();
				q.pop();
				if (!q.empty() && q.top() == data[i][j]) {
					q.pop();
					data[i][j]*=2;
				}
				--j;
			}
		}
		randNew();randNew();
	}
	void up() {
		queue<int>q;
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				if (data[j][i]) {
					q.push(data[j][i]);
					data[j][i] = 0;
				}
			}
			int j = 0;
			while (!q.empty()) {
				data[j][i] = q.front();
				q.pop();
				if (!q.empty() && q.front() == data[j][i]) {
					q.pop();
					data[j][i]*=2;
				}
				++j;
			}
		}
		randNew();randNew();
	}
	void down() {
		stack<int>q;
		for (int i = 0; i < N; ++i) {
			for (int j = 0; j < N; ++j) {
				if (data[j][i]) {
					q.push(data[j][i]);
					data[j][i] = 0;
				}
			}
			int j = N-1;
			while (!q.empty()) {
				data[j][i] = q.top();
				q.pop();
				if (!q.empty() && q.top() == data[j][i]) {
					q.pop();
					data[j][i]*=2;
				}
				--j;
			}
		}
		randNew();randNew();
	}
	void draw(int row, int col, char c) {
		move(row, col);
		addch(c);
	}
	void drawnum(int row, int col, int num) {
		while (num > 0) {
			draw(row, col, num%10+'0');
			num/=10;
			--col;
		}
	}
	void restart() {
		for (auto &i : data)
			for (auto &j : i)
				j = 0;
		randNew();
		randNew();
		status = S_run;
	}
	bool randNew() {
		vector<int> emp;
		for (int i = 0; i < N; ++i) 
			for (int j = 0; j < N; ++j)
				if (data[i][j] == 0)
					emp.push_back(i*N+j);
		if (emp.size() == 0)
			return false;
		int va = emp[rand()%emp.size()];
		//10%的概率產生4
		data[va/N][va%N] = rand()%10 == 1 ? 4 : 2;
		return true;
	}
	int data[N][N];
	int status;
};


void initialize() {
	//ncurses初始化
    initscr();
    //按鍵不需要輸入回車直接交互
    cbreak();
    //按鍵不顯示
    noecho();
    //隱藏光標
    curs_set(0);
    //隨機數
    srand(time(NULL));
}

void shutdown() {
    endwin();//ncurses清理
}

int main() {
    initialize();
    game2048 game;
    do {
		game.man();
        //move(5,5); //移動光標位置
	// addch(ch); //當前位置畫字符ch
	// mvprintw(2, 2, "HCL");//顯示在2,2的位置
       	game.processINPUT();
   }while (game.getstatus() != S_QUIT);
   shutdown();
   return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章