IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C实现2048 -> 正文阅读

[C++知识库]C实现2048

C的简单新手小游戏练习,知识基本是数组,用到指针的比较少,代码含有少量简单的C++,个人认为2048的核心是数字的移动与合并,其次是玩家有效操作的判断,与井字棋有点像。

代码实现了2048的基本功能,数字移动、合并、随机数产生在随机空白位置、有效操作判定、步数记录、得分情况、放弃本局游戏,以及通过修改宏定义常量值能玩更大的棋盘。如果加入文件的读写应该可以多一个排行榜功能。

目前存在情况是随着数字的位数增加界面框会歪斜,以及在游戏菜单界面输入字母直接退出。

代码如下

game.h 文件

#pragma once
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
#define ROW 4
#define COL 4

extern void Intialize(int (*p)[COL]);
extern void Checkerboard(int (*p)[COL]);
extern void Random(int (*p)[COL],int k);
extern void MoveAss(int(*p)[COL], int i, int j,char o);
//extern void Valid(int(*p)[COL],char o,char q,int* g);
//extern void Valid(int(*p)[COL], char o, int q);
extern int Move(int(*p)[COL], char o);
extern void Operate(int (*p)[COL],int k,int* c,int* g);
extern int Criterion(int (*p)[COL]);
extern void Progress(int (*p)[COL]);


game.cpp 文件
#include "game.h"

//界面初始化
void Intialize(int (*p)[COL])
{
	int i = 0;
	int j = 0;
	for (i = 0; i < ROW; i++)//遍历
	{
		for (j = 0; j < COL; j++)
			p[i][j] = 0;
	}
}
//打印界面
void Checkerboard(int (*p)[COL])
{
	int i = 0;
	int j = 0;
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (j == COL - 1)
			{
				if (p[i][j])
					cout << ' ' << p[i][j];
				else
					cout << ' ' << ' ';//掩盖 0 
			}
			else
			{
				if (p[i][j])
					cout << ' ' << p[i][j] << ' ' << '|';//打印  p[][] |  单元
				else
					cout << ' ' << ' ' << ' ' << '|';//掩盖 0 
			}
		}
		cout << endl;
		for (j = 0; j < COL; j++)
		{
			if (i != ROW-1)
				cout << "----";//打印 ---  单元
			if (j == COL - 1)
				cout << endl;
		}
	}
	cout << endl;
}
//在界面随机生成一个2/4数字
void Random(int (*p)[COL],int k)
{
	int x = 0;
	int y = 0;
	if (k != 2048)
	{
		if (k)
		{
			while (1)//生成一个随机数
			{
				x = rand() % ROW;
				y = rand() % COL;
				if (p[x][y] == 0)//寻找空位
				{
					p[x][y] =(rand() % 2 + 1) * 2;
					break;//(rand()%2+1)*2随机生成2/4数字
				}
			}
		}
		if (k != ROW * COL)
			Checkerboard(p);//在界面上显示
	}
}
//辅助移动
void MoveAss(int(*p)[COL],int i,int j,char o)
{
	switch (o)
	{
	case 'w':
	{
		if (p[i][j])
		{
			if ((i != 0)&&(i <= ROW-1))
			{
				if (p[i - 1][j] == 0)
				{
					p[i - 1][j] = p[i][j];
					p[i][j] = 0;
					MoveAss(p, i + 1, j, o);//递归调用
				}
			}
		}
		break;
	}
	case 's':
	{
		if (p[i][j])
		{
			if ((i != ROW-1)&&(i >= 0))
			{
				if (p[i + 1][j] == 0)
				{
					p[i + 1][j] = p[i][j];
					p[i][j] = 0;
					MoveAss(p, i - 1, j, o);//递归调用
				}
			}
		}
		break;
	}
	case 'a':
	{
		if (p[i][j])
		{
			if ((j != 0)&&(j <= COL - 1))
			{
				if (p[i][j - 1] == 0)
				{
					p[i][j - 1] = p[i][j];
					p[i][j] = 0;
					MoveAss(p, i, j + 1, o);//递归调用
				}
			}
		}
		break;
	}
	case 'd':
	{
		if (p[i][j])
		{
			if ((j != ROW - 1)&&(j >= 0))
			{
				if (p[i][j + 1] == 0)
				{
					p[i][j + 1] = p[i][j];
					p[i][j] = 0;
					MoveAss(p, i, j - 1, o);//递归调用
				}
			}
		}
		break;
	}
	}
}
//数字移动与合并
int Move(int (*p)[COL],char o)
{
	int i = 0;
	int j = 0;
	int g = 0;
	switch (o)
	{
	case 'w':
	{
		for (i = ROW - 1; i >= 0; i--)//移动
		{
			for (j = COL - 1; j >= 0; j--)
			{
				MoveAss(p, i, j, o);
			}
		}
		for (i = 0; i < ROW-1; i++)//合并
		{
			for (j = 0; j < COL; j++)
			{
				if (p[i][j] == p[i + 1][j])
				{
					p[i][j] = 2 * p[i][j];
					g = g + p[i][j];
					p[i + 1][j] = 0;
				}
			}
		}
		for (i = ROW - 1; i >= 0; i--)//移动
		{
			for (j = COL - 1; j >= 0; j--)
				MoveAss(p,i,j,o);
		}
		break;
	}
	case 's':
	{
		for (i = 0; i < ROW; i++)//移动
		{
			for (j = 0; j < COL; j++)
			{
				MoveAss(p, i, j, o);
			}
		}
		for (i = ROW-1; i > 0; i--)//合并
		{
			for (j = 0; j < COL; j++)
			{
				if (p[i][j] == p[i - 1][j])
				{
					p[i][j] = 2 * p[i][j];
					g = g + p[i][j];
					p[i - 1][j] = 0;
				}
			}
		}
		for (i = 0; i < ROW; i++)//移动
		{
			for (j = 0; j < COL; j++)
				MoveAss(p, i, j, o);
		}
		break;
	}
	case 'a':
	{
		for (j = COL - 1; j >= 0; j--)//移动
		{
			for (i = ROW - 1; i >= 0; i--)
			{
				MoveAss(p, i, j, o);
			}
		}
		for (j = 0; j < COL - 1; j++)//合并
		{
			for (i = 0; i < ROW; i++)
			{
				if (p[i][j] == p[i][j + 1])
				{
					p[i][j] = 2 * p[i][j];
					g = g + p[i][j];
					p[i][j + 1] = 0;
				}
			}
		}
		for (j = COL - 1; j >= 0; j--)//移动
		{
			for (i = ROW - 1; i >= 0; i--)
				MoveAss(p, i, j, o);
		}
		break;
	}
	case 'd':
	{
		for (j = 0; j < COL; j++)//移动
		{
			for (i = 0; i < ROW; i++)
			{
				MoveAss(p, i, j, o);
			}
		}
		for (j = COL-1; j > 0; j--)//合并
		{
			for (i = 0; i < ROW; i++)
			{
				if (p[i][j] == p[i][j - 1])
				{
					p[i][j] = 2 * p[i][j];
					g = g + p[i][j];
					p[i][j - 1] = 0;
				}
			}
		}
		for (j = 0; j < COL; j++)//移动
		{
			for (i = 0; i < ROW; i++)
				MoveAss(p, i, j, o);
		}
		break;
	}
	}
	return g;
}
//有效移动判定
int Valid(int (*p)[COL],char o,char q,int* g)//重载,通过参数为字符还是整形来调用同名的不同函数
{
	int arr1[ROW][COL];
	int i = 0;
	int j = 0;
	int v = 0;
	for (i = 0; i < ROW; i++)//拷贝一份
	{
		for (j = 0; j < COL; j++)
		{
			arr1[i][j] = p[i][j];
		}
	}
	*g = *g + Move(p, o);
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (arr1[i][j] != p[i][j])
			{
				v = 1;
				break;
			}
		}
		if (v == 1)
			break;
	}
	return v;
}
int Valid(int(*p)[COL], char o,int q)//重载,通过参数为字符还是整形来调用同名的不同函数
{
	int arr1[ROW][COL];
	int i = 0;
	int j = 0;
	int v = 0;
	for (i = 0; i < ROW; i++)//拷贝一份
	{
		for (j = 0; j < COL; j++)
		{
			arr1[i][j] = p[i][j];
		}
	}
	Move(arr1, o);
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (arr1[i][j] != p[i][j])
			{
				v = 1;
				break;
			}
		}
		if (v == 1)
			break;
	}
	return v;
}
//玩家操作
void Operate(int (*p)[COL],int* k,int* c,int* g)
{
	char o = '0';
	char ret[20];
	while (1)
	{
		cout << "请输入:" << endl;
		cin >> ret;
		o = ret[0];//只读取输入的第一个字符
		if (o == 'w' || o == 's' || o == 'a' || o == 'd')
		{
			if (Valid(p, o, 'q', g))
			{
				*c = *c + 1;
				break;
			}
			else
				cout << "无效移动" << endl;
		}
		else if (o == '0')
			break;
		else
			cout << "输入错误" << endl;
	}
	if (o == '0')
		*k = -1;
	else
		Checkerboard(p);
}
//游戏结束判定
int Criterion(int (*p)[COL])
{
	int i = 0;
	int j = 0;
	int k = COL * ROW;//空格剩余数
	for (i = 0; i < ROW; i++)
	{
		for (j = 0; j < COL; j++)
		{
			if (p[i][j] == 2048)//胜利
			{
				k = 2048;
				break;
			}
			if (p[i][j] != 0)
				k--;
		}
		if (k == 2048)
			break;
	}
	return k;
}
//控制游戏进程
void Progress(int (*p)[COL])
{
	int k = ROW * COL;//初始空格数
	int count = 0;
	int grade = 0;
	Random(p,k);
	while(1)
	{
		k = Criterion(p);
		Random(p,k);
		if ((k > 0) && (k != 2048))
			k = k - 1;
		if (k == 2048)
		{
			cout << "恭喜,你赢了!" << endl;
			break;
		}
		if (k == 0)
		{
			if ((Valid(p, 'w',1) || Valid(p, 's',1) || Valid(p, 'a',1) || Valid(p, 'd',1)) == 0)
			{
				cout << "很遗憾,你输了。" << endl;
				break;
			}
		}
		Operate(p, &k,&count,&grade);
		if (k == -1)
		{
			cout << "已放弃当前游戏。" << endl;
			break;
		}
		cout << "步数: " << count << "     ";
		cout << "分数: " << grade << endl << endl;
	}
}


test.cpp 文件

#include "game.h"

void nume()
{
	cout << endl;
	cout << "*****************************" << endl;
	cout << "******   2  0  4  8   *******" << endl;
	cout << "******     1:paly     *******" << endl;
	cout << "******     0:exit     *******" << endl;
	cout << "*****************************" << endl << endl;
}

void game()
{
	int ARR[ROW][COL] = {0};
	int (*p)[COL] = ARR;
	Intialize(p);
	//Checkerboard(p);
	Procgress(p);
}

void select()
{
	int input = 0;
	do
	{
		nume();
		srand((unsigned int)time(NULL));
		cout << "请选择" << endl << endl;
		cin >> input;
		cout << endl;
		switch (input)
		{
		case 1:
			cout << "开始游戏" << endl << endl;
			cout << "  w:上移  s:下移" << endl << endl;
			cout << "  a:左移  d:右移" << endl << endl;
			cout << "  0:放弃当前游戏" << endl << endl;
			game();
			break;
		case 0:
			cout << "退出" << endl;
			break;
		default:
			cout << "选择错误,请重新选择" << endl<<endl;
			break;
		}
	} while (input);
}
int main()
{
	srand((unsigned int)time(NULL));
	select();
	return 0;
}

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-12-16 17:29:31  更:2021-12-16 17:31:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 12:41:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码