用C語言完整實現(xiàn)2048游戲

前言
游戲規(guī)則:游戲開始,在4x4的棋盤上隨機兩個方塊出現(xiàn)數(shù)字2,通過方向鍵控制所有方塊向同一個方向移動,兩個相同數(shù)字方塊撞在一起之后合并成為他們的和。每次移動,棋盤上還會在一個隨機位置增加一個數(shù)字2或者數(shù)字4,當最終得到一個“2048”的方塊就算勝利了。
簡單吧?簡單……個鬼啊,我以前玩了幾個小時都失敗了最后放棄了。
一、游戲思路
1、程序開始時出現(xiàn)菜單,讓玩家選擇開始游戲或者退出游戲。
2、玩家選擇開始游戲后,出現(xiàn)棋盤,通過方向鍵選擇移動的方向。
3、移動后會將所有方塊向該方向移動直至補全空格,同樣數(shù)字的方塊合并成它們的和,還會生成一個隨機位置的2或4。
4、當出現(xiàn)“2048”時,游戲勝利;當棋盤滿且無法消除時,游戲失敗。
二、游戲框架
1.菜單界面
菜單
void menu()
{
printf("**************************\n");
printf("*****按 1 開 始 游 戲*****\n");
printf("*****按 0 退 出 游 戲*****\n");
printf("**************************\n");
}
菜單的選擇
int main()
{
int input = 0;
do
{
menu();
printf("請選擇:");
scanf("%d", &input);
switch (input)
{
case 1:
game2048();
break;
case 0:
printf("退出游戲,客官常來玩呀~)\n");
break;
default:
printf("給你一次重新選擇的機會\n");
break;
}
} while (input);
return 0;
}
實際效果

菜單我覺得還是挺順眼的,就是有點丑,畢竟是初學者就不要要求太高了。
2.游戲主體
1.初始化界面:
生成一個4行4列的數(shù)組(此處的行數(shù)和列數(shù)已在頭文件中用#define宏定義)。
并且打印出來。
void DisplayBoard(int board[ROW][COL],int row, int col)
{
int i = 0;
int j = 0;
for (int j = 0; j < COL; j++)
printf("+-----");
printf("+\n");
for (int i = 0; i < ROW; i++)
{
for (int j= 0; j < COL; j++)
{
printf("|");
if (board[i][j]!=0)
printf("%5d", board[i][j]);
else
printf(" ");
}
printf("|\n");
for (int j = 0; j < COL; j++)
{
printf("+-----");
}
printf("+\n");
}
}
效果如下:

方嗎?方就對了,方就是個好界面!
2.隨機生成初始數(shù)字
游戲的界面我們現(xiàn)在已經(jīng)有了,接下來要做的就是加入兩個隨機位置的”2"。
void get_num(int board[ROW][COL])
{
int x, y;
x = rand() % ROW;
y = rand() % COL;
board[x][y] = 2;//一開始隨機的數(shù)為2
x = rand() % ROW;
y = rand() % COL;
while (board[x][y] == 2)
{
x = rand() % ROW;
y = rand() % COL;
}
board[x][y] = 2;
system("cls"); //清屏,美觀界面
return;
}
(這里照例還是使用了時間戳獲取隨機數(shù)的方法)


可以看到每一次出現(xiàn)的兩個位置都是隨機的。
3.實現(xiàn)移動
這里我們以向上為例,我們要實現(xiàn)移動,以及判定兩個方塊數(shù)字相同就合并成為它們的和,并且當合并后存在空格時繼續(xù)向上移動。
簡單來說,就是 移動 → 合并 → 再次移動補空。其他三個方向也是一樣的道理,只需要改變其中的數(shù)值便可實現(xiàn)。
void up(int board[ROW][COL])
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
for (i = 0; i < ROW; i++)
{
//移動
j = 0;
y = 0;
while (j < COL-1 && y < COL-1 )
{
if (board[j][i] == 0)
{
for (x = j; x < ROW-1; x++)
board[x][i] = board[x + 1][i];
board[ROW-1][i] = 0;
y++;
}
else
j++;
}
//合并
for (j = 0; j < COL-1; j++)
if (board[j][i] == board[j + 1][i] && board[j][i] != 0)
{
board[j][i] = board[j][i] * 2; //和
board[j + 1][i] = 0;
}
//再次移動補空
j = 0;
y = 0;
while (j < COL - 1 && y < COL - 1)
{
if (board[j][i] == 0)
{
for (x = j; x < ROW - 1; x++)
board[x][i] = board[x + 1][i];
board[ROW - 1][i] = 0;
y++;
}
else
j++;
}
}
}
4.增加新數(shù)字
每次移動會在隨機位置出現(xiàn)一個新的數(shù)字,可能是2,可能是4。
通過查詢網(wǎng)上資料得知,隨機到2的概率約為 9/10,隨機到4的概率約為 1/10。
void put_num(int board[ROW][COL])
{
int x = 0;
int y = 0;
int z = 0;
x = rand() % ROW;
y = rand() % COL;
while (board[x][y] !=0)
{
x = rand() % ROW;
y = rand() % COL;
}
z = rand() % 10;
if (z<9)
board[x][y] = 2;
else
board[x][y] = 4;
return;
}
5.判定勝負
當出現(xiàn)2048時勝利,當格子滿了且無法消除時失敗。
int is_fail(int board[ROW][COL])
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == 0)
return 0;
if (i > 0)
{
if (board[i - 1][j] == board[i][j])
return 0;
}
if (j > 0)
{
if (board[i][j - 1] == board[i][j])
return 0;
}
}
}
return 1;
}
int is_win(int board[ROW][COL])
{
int i = 0;
int j = 0;
int num = 0;
for (i = 0; i < ROW; i++)
for (j = 0; j < COL; j++)
{
if (board[i][j] > num)
num = board[i][j];
}
if (num >= 2048)
return 1;
else
return 0;
}
6.游戲函數(shù)
將上述代碼結合起來
void game2048()
{
int board[ROW][COL] = { {0} };
int control = 0;
DisplayBoard(board);
init_num(board);
system("cls"); //清屏,美觀界面
DisplayBoard(board);
while ((control = _getch()) != 0x1b)
{
switch (control)
{
case 0xe0:
switch (control = getch())
{
case 72:
up(board);
break;
case 80:
down(board);
break;
case 75:
left(board);
break;
case 77:
right(board);
break;
default:
break;
}
system("cls");
DisplayBoard(board);
if (is_win(board) == 1)
{
printf("恭喜你贏了!");
}
if (is_fail(board) == 1)
{
printf("哈哈哈哈哈哈哈好菜\n");
}
}
}
}
三、游戲運行
已知目前游戲存在bug,當格子滿了的時候假定一個方向可以消除,另一個方向不可以消除,按了那個不可以消除的方向的話,就會無法操作了,鑒于本人目前初學者并未能夠想到很好的解決方法。若有大佬有好的方法也可指點一下。
我太菜了玩了好久都玩不到2048,最高只有512,1024還是舍友打出來的。

更新:修復了bug
先判斷數(shù)組是否相同再選擇是否添加新的隨機位置的數(shù)字。
在此感謝各位幫助我測試的朋友,無論成功與否,當然特別感謝提供了這張圖片的朋友。

四、所有代碼
game2048.h
#pragma once #include <stdio.h> #include <time.h> #include <stdlib.h> #include <windows.h> #include<conio.h> #define ROW 4 #define COL 4 const int copy[ROW][COL]; //初始化并打印游戲界面 void DisplayBoard(int board[ROW][COL]); //開局隨機生成兩個2 void init_num(int board[ROW][COL]); //在移動后隨機放置數(shù)字2或4 void put_num(int board[ROW][COL]); //移動 void up(int board[ROW][COL]); void down(int board[ROW][COL]); void left(int board[ROW][COL]); void right(int board[ROW][COL]); //判定勝負 int is_win(int board[ROW][COL]); int is_fail(int board[ROW][COL]);
game2048.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game2048.h"
void DisplayBoard(int board[ROW][COL])
{
int i = 0;
int j = 0;
printf("tip:*方向鍵控制方塊移動*ESC鍵返回菜單*\n");
for (int j = 0; j < COL; j++)
printf("+-----");
printf("+\n");
for (int i = 0; i < ROW; i++)
{
for (int j= 0; j < COL; j++)
{
printf("|");
if (board[i][j]!=0)
printf("%5d", board[i][j]);
else
printf(" ");
}
printf("|\n");
for (int j = 0; j < COL; j++)
{
printf("+-----");
}
printf("+\n");
}
}
void init_num(int board[ROW][COL])
{
int x, y;
x = rand() % ROW;
y = rand() % COL;
board[x][y] = 2;//隨機在一個位置生成2
x = rand() % ROW;
y = rand() % COL;
while (board[x][y] == 2)
{
x = rand() % ROW;
y = rand() % COL;
}
board[x][y] = 2;
return;
}
void put_num(int board[ROW][COL])
{
int x = 0;
int y = 0;
int z = 0;
x = rand() % ROW;
y = rand() % COL;
while (board[x][y] !=0)
{
x = rand() % ROW;
y = rand() % COL;
}
z = rand() % 10;
if (z<9)
board[x][y] = 2;
else
board[x][y] = 4;
return;
}
void up(int board[ROW][COL])
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
for (i = 0; i < ROW; i++)
{
//移動
j = 0;
y = 0;
while (j < COL-1 && y < COL-1 )
{
if (board[j][i] == 0)
{
for (x = j; x < ROW-1; x++)
board[x][i] = board[x + 1][i];
board[ROW-1][i] = 0;
y++;
}
else
j++;
}
//合并
for (j = 0; j < COL-1; j++)
if (board[j][i] == board[j + 1][i] && board[j][i] != 0)
{
board[j][i] = board[j][i] * 2;
board[j + 1][i] = 0;
}
//再次移動補空
j = 0;
y = 0;
while (j < COL - 1 && y < COL - 1)
{
if (board[j][i] == 0)
{
for (x = j; x < ROW - 1; x++)
board[x][i] = board[x + 1][i];
board[ROW - 1][i] = 0;
y++;
}
else
j++;
}
}
if (contrast(board) == 0)
put_num(board);
else
return;
}
void down(int board[ROW][COL])
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
for (i = 0; i < ROW; i++)
{
j = COL-1;
y = 0;
while (j > 0 && y < COL-1)
{
if (board[j][i] == 0)
{
for (x = j; x > 0; x--)
board[x][i] = board[x - 1][i];
board[0][i] = 0;
y++;
}
else
j--;
}
for (j = COL-1; j > 0; j--)
if (board[j][i] == board[j - 1][i] && board[j][i] != 0)
{
board[j][i] = board[j][i] * 2;
board[j - 1][i] = 0;
}
j = COL - 1;
y = 0;
while (j > 0 && y < COL - 1)
{
if (board[j][i] == 0)
{
for (x = j; x > 0; x--)
board[x][i] = board[x - 1][i];
board[0][i] = 0;
y++;
}
else
j--;
}
}
if (contrast(board) == 0)
put_num(board);
else
return;
}
void left(int board[ROW][COL])
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
for (i = 0; i < ROW; i++)
{
j = 0;
y = 0;
while (j < 3 && y < 3 )
{
if (board[i][j] == 0)
{
for (x = j; x < ROW-1; x++)
board[i][x] = board[i][x + 1];
board[i][COL-1] = 0;
y++;
}
else
j++;
}
for (j = 0; j < 3; j++)
if (board[i][j] == board[i][j + 1] && board[i][j] != 0)
{
board[i][j] = board[i][j] * 2;
board[i][j + 1] = 0;
}
j = 0;
y = 0;
while (j < 3 && y < 3)
{
if (board[i][j] == 0)
{
for (x = j; x < ROW - 1; x++)
board[i][x] = board[i][x + 1];
board[i][COL - 1] = 0;
y++;
}
else
j++;
}
}
if (contrast(board) == 0)
put_num(board);
else
return;
}
void right(int board[ROW][COL])
{
int i = 0;
int j = 0;
int x = 0;
int y = 0;
for (i = 0; i < 4; i++)
{
j = COL-1;
y = 0;
while (j>0 && y < COL-1)
{
if (board[i][j] == 0)
{
for (x = j; x > 0; x--)
board[i][x] = board[i][x - 1];
board[i][0] = 0;
y++;
}
else j--;
}
for (j = 3; j > 0; j--)
if (board[i][j] == board[i][j - 1] && board[i][j] != 0)
{
board[i][j] = board[i][j] * 2;
board[i][j - 1] = 0;
}
j = COL - 1;
y = 0;
while (j > 0 && y < COL - 1)
{
if (board[i][j] == 0)
{
for (x = j; x > 0; x--)
board[i][x] = board[i][x - 1];
board[i][0] = 0;
y++;
}
else j--;
}
}
if (contrast(board) == 0)
put_num(board);
else
return;
}
int is_fail(int board[ROW][COL])
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
{
for (j = 0; j < COL; j++)
{
if (board[i][j] == 0)
return 0;
if (i > 0)
{
if (board[i - 1][j] == board[i][j])
return 0;
}
if (j > 0)
{
if (board[i][j - 1] == board[i][j])
return 0;
}
}
}
return 1;
}
int is_win(int board[ROW][COL])
{
int i = 0;
int j = 0;
int num = 0;
for (i = 0; i < ROW; i++)
for (j = 0; j < COL; j++)
{
if (board[i][j] > num)
num = board[i][j];
}
if (num >= 2048)
return 1;
else
return 0;
}
void copyboard(int board[ROW][COL],int copy[ROW][COL])
{
int i = 0;
int j = 0;
for (i = 0; i < ROW; i++)
for (j = 0; j < COL; j++)
copy[i][j] = board[i][j];
}
int contrast(int board[ROW][COL])
{
int i = 0;
int j = 0;
for (i = 0; i < 4; i++)
for (j = 0; j < 4; j++)
if (copy[i][j] != board[i][j])
return 0;
return 1;
}
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game2048.h"
void menu()
{
printf("**************************\n");
printf("*****按 1 開 始 游 戲*****\n");
printf("*****按 0 退 出 游 戲*****\n");
printf("**************************\n");
}
void game2048()
{
int board[ROW][COL] = { {0} };
int control = 0;
DisplayBoard(board);
init_num(board);
system("cls"); //清屏,美觀界面
DisplayBoard(board);
while ((control = _getch()) != 0x1b)
{
switch (control)
{
case 0xe0:
switch (control = getch())
{
case 72:
copyboard(board, copy);
up(board);
break;
case 80:
copyboard(board, copy);
down(board);
break;
case 75:
copyboard(board, copy);
left(board);
break;
case 77:
copyboard(board, copy);
right(board);
break;
default:
break;
}
system("cls");
DisplayBoard(board);
if (is_win(board) == 1)
{
printf("恭喜你贏了!\n");
}
if (is_fail(board) == 1)
{
printf("哈哈哈哈哈哈哈好菜\n");
}
}
}
}
int main()
{
int input = 0;
srand((unsigned int)time(NULL));
do
{ menu();
printf("請選擇:");
scanf("%d", &input);
switch (input)
{
case 1:
game2048();
break;
case 0:
printf("退出游戲,客官常來玩呀~)\n");
break;
default:
printf("給你一次重新選擇的機會\n");
break;
}
} while (input);
return 0;
}
總結
感謝各位幫我測試的朋友們!
很久以前看過一部小說,主人公的第一個C語言程序就是實現(xiàn)一個2048的小游戲。
我不是生活中的主人公,但是我還是想要努力到能夠讓自己不再留下遺憾,努力到配得上自己喜歡的人。
三天時間,2048,愿不忘初心。
到此這篇關于用C語言完整實現(xiàn)2048游戲的文章就介紹到這了,更多相關C語言 2048游戲內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解C++中StringBuilder類的實現(xiàn)及其性能優(yōu)化
在Java和C#中,StringBuilder可以創(chuàng)造可變字符序列來動態(tài)地擴充字符串,那么在C++中我們同樣也可以實現(xiàn)一個StringBuilder并且用來提升性能,下面就來詳解C++中StringBuilder類的實現(xiàn)及其性能優(yōu)化2016-05-05
C語言實現(xiàn)Linux下的socket文件傳輸實例
這篇文章主要介紹了C語言實現(xiàn)Linux下的socket文件傳輸?shù)姆椒?較為詳細的分析了C語言文件Socket文件傳輸客戶端與服務器端相關實現(xiàn)技巧,需要的朋友可以參考下2015-06-06

