C語(yǔ)言實(shí)現(xiàn)2048小游戲
更新時(shí)間:2018年05月03日 16:34:37 作者:毒初萊式鯊壁
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)2048小游戲,注釋清晰,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
本文實(shí)例為大家分享了C語(yǔ)言實(shí)現(xiàn)2048游戲的具體代碼,供大家參考,具體內(nèi)容如下
滑塊有顏色、有最高分(用到文件)
#include <stdio.h>
#include <stdlib.h>
#include <conio.h> /*使用getch()函數(shù)*/
#include <time.h>
#include <windows.h> /*使用Sleep()函數(shù)*/
void Menu();//菜單
void Rule_of_game();//游戲規(guī)則
void Begin(int max); //開(kāi)始
void Table();//打印4×4方格
int Random_number1();//產(chǎn)生2或4的隨機(jī)數(shù)
int Random_number2();//產(chǎn)生0、1、2、3的隨機(jī)數(shù)
int Get(int *p_cnt, int score);//輸入指令
void Move();//保留上一次的棋盤布局
int If_move();//判斷是否移動(dòng)
int Over();//判斷是否結(jié)束
void Establish_game();//創(chuàng)建用于保存最高分的文件
void Write_max(int score);//向2048游戲-最高記錄寫入最高分
int Read_max();//讀出最高分記錄的文件
void Establish_file();//創(chuàng)建存檔文件
void Write_file(int *p_cnt, int scort);//存檔
int Read_file(int *p_cnt);//讀檔
void again();//是否繼續(xù)游戲
int color(int c);//更改顏色
void box_color(int x);//不同數(shù)值對(duì)應(yīng)不同顏色
int a[4][4] = {0};// 定義全局的二維數(shù)組
int A[4][4]; //保留上一步的棋局
char *name_max = "2048游戲-最高記錄";
char *name_file = "[空白]-2048游戲";
int main() {
system("mode con cols=90 lines=30");
system("title 2048超級(jí)大大型游戲"); //程序標(biāo)題
system("color F0");//F 表示背景顏色,0表示前景顏色
Menu();
system("pause"); //暫停,輸入任意鍵繼續(xù)
system("cls"); //清屏
again(); //是否繼續(xù)游戲
return 0;
}
void Menu() //菜單
{
printf("\t\t╔══════════════════════════════════════════════╗\n");
printf("\t\t║ 歡迎使用由[空白]制作的2048超級(jí)大大型游戲 ║\n");
printf("\t\t╟──────────────────────────────────────────────╢\n");
printf("\t\t║請(qǐng)輸入選項(xiàng): ║\n");
printf("\t\t║ ┌───┐ ║\n");
printf("\t\t║ │ 1 │ 游戲規(guī)則 ║\n");
printf("\t\t║ └───┘ ║\n");
printf("\t\t║ ┌───┐ ║\n");
printf("\t\t║ │ 2 │ 開(kāi)始游戲 ║\n");
printf("\t\t║ └───┘ ║\n");
printf("\t\t║ ┌───┐ ║\n");
printf("\t\t║ │ 3 │ 繼續(xù)游戲 ║\n");
printf("\t\t║ └───┘ ║\n");
printf("\t\t║ ┌───┐ ║\n");
printf("\t\t║ │ 4 │ 退出游戲 ║\n");
printf("\t\t║ └───┘ ║\n");
printf("\t\t╚══════════════════════════════════════════════╝\n");
int x = 1, max = 0;
while(x){
switch(getch()){
case '1':
x = 0;
Rule_of_game();//游戲規(guī)則
Menu();
break;
case '2':
x = 0;
system("cls");//清屏
Establish_game(name_file);//創(chuàng)建新的讀檔文件
Establish_game(name_max);//創(chuàng)建新的保存最高記錄的文件
Begin(max); //開(kāi)始游戲
break;
case '3':
x = 0;
system("cls");//清屏
max = Read_max();//讀取之前的最高記錄
Begin(max); //開(kāi)始游戲
break;
case '4':
exit(0);
default:
printf("輸入了非法選項(xiàng),請(qǐng)重新選擇!\n");
}
}
}
void Rule_of_game()
{
system("cls");//清屏
printf("╔══════════════════════════════════════════════════════════════════════════════════╗\n");
printf("║本游戲通過(guò)按鍵W、S、A、D(不區(qū)分大小寫)四個(gè)鍵分別控制滑塊上移、下移、左移和右移。║\n");
printf("║滑塊移動(dòng)的過(guò)程中,如有相鄰且相等數(shù)字的滑塊將會(huì)相加,并獲得相應(yīng)的分?jǐn)?shù)。 ║\n");
printf("║當(dāng)棋盤上的所有位置均有數(shù)字,且不能合成,則游戲結(jié)束。本游戲未設(shè)置游戲成功。 ║\n");
printf("║游戲過(guò)程中輸入I即為存檔并退出游戲,輸入O即為讀檔,輸入P則退出游戲。 ║\n");
printf("║“開(kāi)始游戲”則清除最高記錄及存檔、“繼續(xù)游戲”則保存之前的最高記錄,且可以讀檔。 ║\n");
printf("╚══════════════════════════════════════════════════════════════════════════════════╝\n");
system("pause");//暫停
system("cls");//清屏
}
void Begin(int max)
{
int score = 0;
int sign = 1;
int h, l, cnt = 0;
int *p_cnt = &cnt;
while(1) {
printf("\t\t╔══════════════════════════════════════════════╗\n");
printf("\t\t║ 歡迎使用由[空白]制作的2048超級(jí)大大型游戲 ║\n");
printf("\t\t╟──────────────────────────────────────────────╢\n");
printf("\t\t║移動(dòng): ┌───┐ 存檔: 讀檔: 退出: ║\n");
printf("\t\t║ │ W │ ║\n");
printf("\t\t║ ┌───┼───┼───┐ ┌───┐ ┌───┐ ┌───┐ ║\n");
printf("\t\t║ │ A │ S │ D │ │ I │ │ O │ │ P │ ║\n");
printf("\t\t║ └───┴───┴───┘ └───┘ └───┘ └───┘ ║\n");
printf("\t\t╚══════════════════════════════════════════════╝\n");
while(1){
if(sign == 1){
h = Random_number2();
l = Random_number2();
if(a[h][l] == 0){
a[h][l] = Random_number1();
cnt ++;
break;
}
}
else{
break;
}
}
Table();//打印棋盤
printf("\t\t移動(dòng)的步數(shù):%d\t當(dāng)前得分:%d\n\t\t最高記錄:%d\n", cnt-1, score, max);
Move();//保留棋盤
score += Get(p_cnt, score);//得分
sign = If_move();//判斷棋盤是否有變動(dòng)
if(Over() == 0){
if(max < score){//打破記錄
Establish_game(name_max);//清除之前的記錄
Write_max(score);//保存此次記錄
printf("\t\t恭喜您已打破記錄!\n");
}
break;
}
system("cls"); //清屏
}
}
void Table()
{
int h, l;
for(h = 0; h < 4; h ++){
if(h == 0){
printf("\t\t\t┏━━━━━━┳━━━━━━┳━━━━━━┳━━━━━━┓\n");
}
else {
printf("\t\t\t┣━━━━━━╋━━━━━━╋━━━━━━╋━━━━━━┫\n");
}
printf("\t\t\t┃ ┃ ┃ ┃ ┃\n");
for(l = 0; l < 4; l ++){
if(a[h][l] == 0){//如果二維數(shù)組與棋盤對(duì)應(yīng)的位置為零,則不放入數(shù)據(jù)
if(l == 0){
printf("\t\t\t┃ ");
}
else {
printf("┃ ");
}
}
else{//否則放入與二維數(shù)組對(duì)應(yīng)的數(shù)據(jù)
if(l == 0){
printf("\t\t\t┃");
box_color(a[h][l]);//判斷滑塊的數(shù)值,給對(duì)應(yīng)顏色
printf("%5d ", a[h][l]);
color(0);//恢復(fù)白色背景
}
else {
printf("┃");
box_color(a[h][l]);//判斷滑塊的數(shù)值,給對(duì)應(yīng)顏色
printf("%5d ", a[h][l]);
color(0);//恢復(fù)白色背景
}
}
}
printf("┃\n");
printf("\t\t\t┃ ┃ ┃ ┃ ┃\n");
}
printf("\t\t\t┗━━━━━━┻━━━━━━┻━━━━━━┻━━━━━━┛\n");
}
int Random_number1()/*隨機(jī)生成2 or 4*/
{
int s;
srand( time(NULL) );
s = ((unsigned)rand() % 2);
s = s == 0 ? 2 : 4;
return s;
}
int Random_number2()/*隨機(jī)生成二維數(shù)組的下標(biāo)*/
{
int x;
x = ((unsigned)rand() % 4);
return x;
}
int Get(int *p_cnt, int score)
{
int h, l, t, sum = 0;
char ch;
ch = getch();//輸入字符
switch (ch){
/*滑塊向上移動(dòng)*/
case 'w':
case 'W':
/*向上聚集數(shù)字*/
for(l = 0; l < 4; l ++){
for(t = 0; t < 4; t ++){
for(h = 3; h > 0; h --){
if(a[h-1][l] == 0){
a[h-1][l] = a[h][l];
a[h][l] = 0;
}
}
}
}
/*豎直方向上,相鄰且相同的數(shù)字相加*/
for(l = 0; l < 4; l ++){
for(h = 0; h < 3; h ++){
if(a[h][l] == a[h+1][l]){
a[h][l] += a[h+1][l];
a[h+1][l] = 0;
sum += a[h][l];
}
}
}
/*向上聚集數(shù)字*/
for(l = 0; l < 4; l ++){
for(t = 0; t < 4; t ++){
for(h = 3; h > 0; h --){
if(a[h-1][l] == 0){
a[h-1][l] = a[h][l];
a[h][l] = 0;
}
}
}
}
break;
case 's':
case 'S':
for(l = 0; l < 4; l ++){
for(t = 0; t < 4; t ++){
for(h = 0; h < 3; h ++){
if(a[h+1][l] == 0){
a[h+1][l] = a[h][l];
a[h][l] = 0;
}
}
}
}
for(l = 0; l < 4; l ++){
for(h = 3; h > 0; h --){
if(a[h][l] == a[h-1][l]){
a[h][l] += a[h-1][l];
a[h-1][l] = 0;
sum += a[h][l];
}
}
}
for(l = 0; l < 4; l ++){
for(t = 0; t < 4; t ++){
for(h = 0; h < 3; h ++){
if(a[h+1][l] == 0){
a[h+1][l] = a[h][l];
a[h][l] = 0;
}
}
}
}
break;
case 'a':
case 'A':
for(h = 0; h < 4; h ++){
for(t = 0; t < 4; t ++){
for(l = 3; l > 0; l --){
if(a[h][l-1] == 0){
a[h][l-1] = a[h][l];
a[h][l] = 0;
}
}
}
}
for(h = 0; h < 4; h ++){
for(l = 0; l < 3; l ++){
if(a[h][l] == a[h][l+1]){
a[h][l] += a[h][l+1];
a[h][l+1] = 0;
sum += a[h][l];
}
}
}
for(h = 0; h < 4; h ++){
for(t = 0; t < 4; t ++){
for(l = 3; l > 0; l --){
if(a[h][l-1] == 0){
a[h][l-1] = a[h][l];
a[h][l] = 0;
}
}
}
}
break;
case 'd':
case 'D':
for(h = 0; h < 4; h ++){
for(t = 0; t < 4; t ++){
for(l = 0; l < 3; l ++){
if(a[h][l+1] == 0){
a[h][l+1] = a[h][l];
a[h][l] = 0;
}
}
}
}
for(h = 0; h < 4; h ++){
for(l = 3; l > 0; l --){
if(a[h][l] == a[h][l-1]){
a[h][l] += a[h][l-1];
a[h][l-1] = 0;
sum += a[h][l];
}
}
}
for(h = 0; h < 4; h ++){
for(t = 0; t < 4; t ++){
for(l = 0; l < 3; l ++){
if(a[h][l+1] == 0){
a[h][l+1] = a[h][l];
a[h][l] = 0;
}
}
}
}
break;
case 'i':
case 'I': //存檔當(dāng)前游戲格局
Establish_file();//創(chuàng)建用于存檔的文件
Write_file(p_cnt, score);//調(diào)用存檔函數(shù)
break;
case 'o':
case 'O':
sum = Read_file(p_cnt);//讀檔
break;
case 'p':
case 'P':
exit(0);//退出程序
default:
break;
}
return sum;
}
void Move()
{
int h, l;
for(h = 0; h < 4; h ++){
for(l = 0; l < 4; l ++){
A[h][l] = a[h][l];
}
}
}
int If_move()
{
int h, l, sign = 0;
for(h = 0; h < 4; h ++){
for(l = 0; l < 4; l ++){
if(a[h][l] != A[h][l]){//未進(jìn)入條件框,說(shuō)明滑塊沒(méi)有發(fā)生移動(dòng)
sign = 1;
goto out;
}
}
}
out:
return sign;
}
int Over()
{
int over = 0;
int h, l;
for(h = 0; h < 4; h ++){
for(l = 0; l < 4; l ++){
if(a[h][l] == 0){//有空格
over = 1;//游戲繼續(xù)
return 1;
}
}
}
if(over == 0){//沒(méi)有空格
for(h = 0; h < 3; h ++){
for(l = 0; l < 3; l ++){
if(a[h][l] == a[h][l+1]){
over = 1;//游戲繼續(xù)
break;
}
else if(a[h][l] == a[h+1][l]){
over = 1;//游戲繼續(xù)
break;
}
}
if(over == 1){
break;
}
}
}
return over;//游戲結(jié)束
}
void Establish_game()//創(chuàng)建文件
{
int h;
if(h = fopen(name_max, "wb") == NULL){ //函數(shù)fopen()返回NULL則創(chuàng)建文件失敗
printf("\t\t創(chuàng)建文件失?。〕绦蚣磳⒆詣?dòng)退出 . . .\n");
Sleep(3000);//睡眠3000毫秒,即停留3秒鐘
exit(0); //退出程序
}
}
void Write_max(int score)//寫入文件
{
/*FILE *fp是指向文件的指針*/
FILE *fp=fopen(name_max,"at+");// at+讀寫打開(kāi)或著建立一個(gè)文本文件;允許讀寫。
if(fp==NULL) //函數(shù)fopen()返回NULL則創(chuàng)建文件失敗
{
printf("\t\t保存最高分失?。〕绦蚣磳⒆詣?dòng)退出 . . .");
Sleep(3000);//睡眠3000毫秒,即停留3秒鐘
exit(0); //退出程序
}
else{
fprintf(fp, "%d", score);//將score的值寫入*pf指向的文件內(nèi)
}
fclose(fp);//關(guān)閉*pf指向的文件
}
int Read_max()//讀出文件
{
int max_score = 0;
FILE *fp=fopen(name_max,"at+");// at+讀寫打開(kāi)或著建立一個(gè)文本文件;允許讀寫。
if(fp==NULL)
{
printf("\t\t讀取失敗!程序即將自動(dòng)退出 . . .");
Sleep(3000);//睡眠3000毫秒,即停留3秒鐘
exit(0); //退出程序
}
else{
fscanf(fp, "%d", &max_score);//從*pf指向的文件內(nèi)數(shù)值賦值給max_score
}
fclose(fp);//關(guān)閉*pf指向的文件
return max_score;//返回最高記錄的值
}
void Establish_file()//創(chuàng)建文件
{
int h;
if(h = fopen(name_file, "wb") == NULL){ //函數(shù)fopen()返回NULL則創(chuàng)建文件失敗
printf("\t\t創(chuàng)建文件失?。〕绦蚣磳⒆詣?dòng)退出 . . .\n");
Sleep(3000);//睡眠3000毫秒,即停留3秒鐘
exit(0); //退出程序
}
}
void Write_file(int *p_cnt, int score)
{
int h, l;
FILE *fp=fopen(name_file,"at+");// at+讀寫打開(kāi)或著建立一個(gè)文本文件;允許讀寫。
if(fp==NULL)
{
printf("\t\t存檔失??!程序即將自動(dòng)退出 . . .\n");
Sleep(3000);//睡眠3000毫秒,即停留3秒鐘
exit(0);
}
else{
for(h = 0; h < 4; h ++){
for(l = 0; l < 4; l ++){
fprintf(fp, "%d ", a[h][l]);
}
}
}
fprintf(fp, "%d ", score);
fprintf(fp, "%d ", *p_cnt-1);
printf("\t\t存檔成功!游戲即將自動(dòng)退出 . . .\n");
Sleep(3000); //睡眠3000毫秒,即停留3秒鐘
exit(0);
fclose(fp);//關(guān)閉文件
}
int Read_file(int *p_cnt)
{
int h, l, score = 0;
FILE *fp=fopen(name_file,"at+");// at+讀寫打開(kāi)或著建立一個(gè)文本文件;允許讀寫。
if(fp==NULL)
{
printf("\t\t讀檔失??!程序即將自動(dòng)退出 . . .\n");
Sleep(3000); //睡眠3000毫秒,即停留3秒鐘
exit(0);
}
else{
for(h = 0; h < 4; h ++){
for(l = 0; l < 4; l ++){
fscanf(fp, "%d ", &a[h][l]);
}
}
}
fscanf(fp, "%d ", &score);
fscanf(fp, "%d ", p_cnt);
fclose(fp); //關(guān)閉文件
return score;
}
void again()//是否繼續(xù)游戲
{
printf("\t\t╔══════════════════════════════════════════════╗\n");
printf("\t\t║ 您已失敗 ║\n");
printf("\t\t╟──────────────────────────────────────────────╢\n");
printf("\t\t║是否繼續(xù): ║\n");
printf("\t\t║ ┌───┐ ║\n");
printf("\t\t║ │ 1 │ 扶我起來(lái),我還能再來(lái)一局! ║\n");
printf("\t\t║ └───┘ ║\n");
printf("\t\t║ ┌───┐ ║\n");
printf("\t\t║ │ 2 │ 不了不了,我要學(xué)習(xí)! ║\n");
printf("\t\t║ └───┘ ║\n");
printf("\t\t╚══════════════════════════════════════════════╝\n");
if(_getch() == '1'){
system("cls");//清屏
int h, l;
for(h = 0; h < 4; h ++){
for(l = 0; l < 4; l ++){
a[h][l] = 0;
A[h][l] = 0;
}
}
Menu();//回到菜單
}
else {
printf("\t\t游戲結(jié)束!\n");
}
}
int color(int c)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),
BACKGROUND_INTENSITY |
BACKGROUND_BLUE |
BACKGROUND_RED |
BACKGROUND_GREEN |
c);
return 0;
}
void box_color(int x)
{
switch(x){
case 2:
color(8);
break;
case 4:
color(0);
break;
case 8:
color(2);
break;
case 16:
color(6);
break;
case 32:
color(10);
break;
case 64:
color(3);
break;
case 128:
color(9);
break;
case 256:
color(11);
break;
case 512:
color(5);
break;
case 1024:
color(13);
break;
case 2048:
color(12);
break;
default :
color(4);
break;
}
}
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)memcpy函數(shù)的使用示例
在C語(yǔ)言中,我們可以自己實(shí)現(xiàn) memcpy 函數(shù)來(lái)實(shí)現(xiàn)內(nèi)存數(shù)據(jù)的拷貝操作,本文就來(lái)介紹一下C語(yǔ)言實(shí)現(xiàn)memcpy函數(shù)的使用示例,感興趣的可以了解一下2023-09-09
C++如何將二叉搜索樹(shù)轉(zhuǎn)換成雙向循環(huán)鏈表(雙指針或數(shù)組)
這篇文章主要介紹了C++如何將二叉搜索樹(shù)轉(zhuǎn)換成雙向循環(huán)鏈表(雙指針或數(shù)組),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
c++中關(guān)于max_element()函數(shù)解讀
這篇文章主要介紹了c++中關(guān)于max_element()函數(shù)解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02

