用C語言自己寫2048
2048是之前非常火爆的一個遊戲,記得之前上課的時候很多同學都在玩這個遊戲。尤其是一些比較無聊的課上玩的人更多。那麼我們應該如何用代碼自己來實作2048這個遊戲的編寫呢?
之前在實驗樓網站學習linux的時候碰巧看到了一個教程,是以就試着玩了一下,代碼編寫也很簡單,當然我也無聊的玩到了2048,是以我發現其實實驗樓上面給的代碼也是有點小bug的,是以我對代碼進行了一個簡單的更改。
實驗樓該教程網址:
https://www.shiyanlou.com/courses/155
下面就是操作及其我修改後的代碼:
基礎知識
要實作我們的 2048 小遊戲,需要涉及一些資料結構的知識,以及一些 Linux 的系統調用。此外,為了友善在螢幕上使用字元繪圖,我們還需要使用一個文本界面的螢幕繪圖庫 ncurses ,具體到操作就是在編譯的時候需要加上 -lcurses 選項。
ncurses 庫的安裝操作如下:
sudo apt-get install libncurses5-dev
```
## 我修改後的代碼
建立一個c檔案,命名為.c
代碼如下:
```c
<div class="se-preview-section-delimiter"></div>
#include <stdio.h>
<div class="se-preview-section-delimiter"></div>
#include <stdlib.h>
<div class="se-preview-section-delimiter"></div>
#include <curses.h>
<div class="se-preview-section-delimiter"></div>
#include <time.h>
<div class="se-preview-section-delimiter"></div>
#include <unistd.h>
<div class="se-preview-section-delimiter"></div>
#include <signal.h>
// *方格
int a[][] = {};
// 方格裡空格的個數
int empty;
int old_y, old_x;
void draw();
void play();
void init();
void draw_one(int y, int x);
void cnt_value(int *new_y, int *new_x);
int game_over();
int cnt_one(int y, int x);
int main()
{
init();
play();
endwin();
return ;
}
void init()
{
int x, y;
initscr();
cbreak();
noecho();
curs_set();
empty = ;
srand(time());
x = rand() % ;
y = rand() % ;
a[y][x] = ;
draw();
}
void draw()
{
int n, m, x, y;
char c[] = {'0', '0', '0', '0'};
clear();
for(n = ; n < ; n += ) //橫線
for(m = ; m < ; m++) {
move(n, m);
addch('-');
refresh();
}
for(m = ; m < ; m += ) //豎線
for(n = ; n < ; n++) {
move(n, m);
addch('|');
refresh();
}
for(y = ; y < ; y++) //數字
for(x = ; x < ; x++) {
draw_one(y, x);
}
}
void draw_one(int y, int x)
{
int i, m, k, j;
char c[] = {'0', '0', '0', '0'};
i = a[y][x];
m = ;
do {
j = i % ;
c[m++] = j + '0';
i = i / ;
}while(i > );
m = ;
k = (x + ) * - ;
while(c[m] != '0') {
move(*y+, k);
addch(c[m++]);
k--;
}
}
void play()
{
int x, y, i, new_x, new_y, tmp;
int old_empty, move;
char ch;
while() {
move = ;
old_empty = empty;
//draw();
ch = getch();
switch(ch) {
case 'A':
case 'a':
//從左向右消去相同方塊
for(y = ; y < ; y++)
for(x = ; x < ; ) {
if(a[y][x] == ) {
x++;
continue;
} else {
for(i = x + ; i < ; i++) {
if(a[y][i] == ) {
continue;
}
else {
if(a[y][x] == a[y][i]) {
a[y][x] += a[y][i];
a[y][i] = ;
x = i + ;
empty++;
break;
}
else {
x = i;
break;
}
}
}
x = i;
}
}
//向左移動方塊
for(y = ; y < ; y++)
for(x = ; x < ; x++) {
if(a[y][x] == ) {
continue;
} else {
for(i = x; (i > ) && (a[y][i-] == ); i--) {
a[y][i-] = a[y][i];
a[y][i] = ;
move = ;
}
}
}
break;
case 'D':
case 'd':
//從右向左消去相同方塊
for(y = ; y < ; y++)
for(x = ; x >= ; ) {
if(a[y][x] == ) {
x--;
continue;
} else {
for(i = x - ; i >= ; i--) {
if(a[y][i] == ) {
continue;
} else if(a[y][x] == a[y][i]) {
a[y][x] += a[y][i];
a[y][i] = ;
x = i - ;
empty++;
break;
} else {
x = i;
break;
}
}
x = i;
}
}
//向右移動方塊
for(y = ; y < ; y++)
for(x = ; x >= ; x--) {
if(a[y][x] == ) {
continue;
} else {
for(i = x; (i < ) && (a[y][i+] == ); i++) {
a[y][i+] = a[y][i];
a[y][i] = ;
move = ;
}
}
}
break;
case 'W':
case 'w':
//從上向下消去相同方塊
for(x = ; x < ; x++)
for(y = ; y < ; ) {
if(a[y][x] == ) {
y++;
continue;
} else {
for(i = y + ; i < ; i++) {
if(a[i][x] == ) {
continue;
} else if(a[y][x] == a[i][x]) {
a[y][x] += a[i][x];
a[i][x] = ;
y = i + ;
empty++;
break;
} else {
y = i;
break;
}
}
y = i;
}
}
//向上移動方塊
for(x = ; x < ; x++)
for(y = ; y < ; y++) {
if(a[y][x] == ) {
continue;
} else {
for(i = y; (i > ) && (a[i-][x] == ); i--) {
a[i-][x] = a[i][x];
a[i][x] = ;
move = ;
}
}
}
break;
case 'S':
case 's':
//從下向上消去相同方塊
for(x = ; x < ; x++)
for(y = ; y >= ; ) {
if(a[y][x] == ) {
y--;
continue;
} else {
for(i = y - ; i >= ; i--) {
if(a[i][x] == ) {
continue;
} else if(a[y][x] == a[i][x]) {
a[y][x] += a[i][x];
a[i][x] = ;
y = i -;
empty++;
break;
} else {
y = i;
break;
}
}
y = i;
}
}
//向下移動方塊
for(x = ; x < ; x++)
for(y = ; y >= ; y--) {
if(a[y][x] == ) {
continue;
} else {
for(i = y; (i < ) && (a[i+][x] == ); i++) {
a[i+][x] = a[i][x];
a[i][x] = ;
move = ;
}
}
}
break;
case 'Q':
case 'q':
game_over();
break;
default:
continue;
break;
}
if(empty <= )
game_over();
draw();
//生成新方塊
if((empty != old_empty) || (move == )) { //修複了不移動或消除方塊也生成新方塊的bug
do {
new_x = rand() % ;
new_y = rand() % ;
}while(a[new_y][new_x] != );
cnt_value(&new_y, &new_x);
do {
tmp = rand() % ;
}while(tmp == || tmp == );
a[new_y][new_x] = tmp + ;
empty--;
draw_one(new_y, new_x);
}
}
}
int cnt_one(int y, int x)
{
int value = ;
if(y - > )
a[y-][x] ? : value++;
if(y + < )
a[y+][x] ? : value++;
if(x - >= )
a[y][x-] ? : value++;
if(x + < )
a[y][x+] ? : value++;
if(y - >= && x - >= )
a[y-][x-] ? : value++;
if(y - >= && x + < )
a[y-][x+] ? : value++;
if(y + < && x - >= )
a[y+][x-] ? : value++;
if(y + < && x + < )
a[y+][x+] ? : value++;
return value;
}
void cnt_value(int *new_y, int *new_x)
{
int max_x, max_y, x, y, value;
int max = ;
max = cnt_one(*new_y, *new_x);
for(y = ; y < ; y++)
for(x = ; x < ; x++) {
if(!a[y][x]) {
value = cnt_one(y, x);
if(value > max && old_y != y && old_x != x) { //避免在同一位置反複出現新方塊
*new_y = y;
*new_x = x;
old_x = x;
old_y = y;
break;
}
}
}
}
int game_over()
{
sleep();
endwin();
exit();
}
<div class="se-preview-section-delimiter"></div>
編譯程式
gcc .c -o -lcurses
<div class="se-preview-section-delimiter"></div>
運作程式
./
操作
使用“w”;”a”;”s”;”d”;或者”W”;”A”;”S”;”D”來進行移動
效果圖如下:
{% img /images/2048.png %}
操作
使用“w”;”a”;”s”;”d”;或者”W”;”A”;”S”;”D”來進行移動
效果圖如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiI0NXYFhGd192UvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcNTRE9UdW12Y5Z0RaZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39TN2ADNyIDM5EzMwQDM4EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)