C语言写的2048小游戏
基于"基于C_语言的2048算法设计_颜冠鹏.pdf"
这一篇文献提供的思路
在中国知网上能找到 就不贴具体内容了
[摘 要] 针对2048的游戏规则,分析了该游戏的算法特点,对其相关的功能需求和算法设计进行了简单介绍,提出了一种 新的设计方案。解决了该设计在方阵数据结构、运动算法和游戏结束判断方面的问题,并阐述了以队列方式进行坐标运算和操 作扩展的关键技术。软件测试表明,该设计的方块数值最大值受方阵阶数和操作次数的限制,四阶方阵的理论最大值为 65 536, 智力极高的人可达 16 384,而一般人仅能达到 2 048 左右。
[关键词] 2048 算法设计 数据结构 坐标运算 队列
中图分类号:TP301.6 文献标识码:A 文章编号:1008- 1739(2014)24- 62- 5
主要是几个小的函数
用两个for循环打印地图和遍历地图
把一个4*4的二维数组改成一个一维数组来简化处理思路
学到的知识
switch函数每一个case都需要加break来结束判断
for在c99标准下 初始化的循环变量和外界所有变量毫无关系
c99标准才有了布尔型变量
尽量不要大循环套小循环 嵌套四层循环之后就晕了 下断点都不好调试
如果数组越界访问会返回0
随机数函数必须撒种子 不然每次都是同一个值
//
// main.c
// 2048
// 表示 为了练习C语言 在这先写着一个小游戏吧
// “听说以后上课要用?”
// 调试代码已注释 目前游戏所有功能均实现
// 唯一不足的是在苹果系统环境无getch函数
// 且不会自行实现 在其他系统直接include <conio.h>
// 把getchar改为getch即可畅玩2048
// Created by licsber on 2018/10/11.
// Copyright © 2018 licsber. All rights reserved.
//
#include <stdio.h>//emmmm
#include <stdbool.h> //c里没有布尔型变量 c99标准才加的
#include <time.h>//用于产生随机数
#include <stdlib.h>
//#include <ncurses.h>//图形界面库 等后来更新printMap函数再引用
void gameStart(void);//游戏开始
void randomAdd(void);//在空格随机加2和4 其中2为十分之九概率
void printMap(void);//用printf打印地图
void getDirection(void);//读取键盘输入
void moveUp(void);//上
void moveDown(void);//下
void moveLeft(void);//左
void moveRight(void);//右
void moveForward(void);//推进
void moveMerge(void);//合并
bool checkIfGameOver(void);//检测游戏是否over 即无空位同时相邻数组元素各不相等
void restart(void);//重新开始
void loop(void);//循环游戏
//int countZero(void);//还有几个是0
//int returnZero(int line);
int score = 0;//当前得分
int map[4][4]={
{0,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,0}
};//这是地图 用二维数组实现
int tmp[4] = {0,0,0,0};
void gameStart(void){
printf("Welcome to play 2048 game! by licsber\n");
randomAdd();
printMap();
printf("[w][s][a][d]move [r]restart [q]quit\n");
}
void randomAdd(void){
srand((unsigned int)time(NULL));//撒随机数种子
//printf("%d",rand());
int i,j,time = 0;//行 列 循环次数(debug用)
do{
i = rand() % 4;
j = rand() % 4;
time++;
}while (map[i][j] != 0);
if (rand() % 10 == 0 ) {
map[i][j]=4;
}
else{
map[i][j]=2;
}
//printf("%d",time);
//上面的代码在格子快满之后也有几率循环N次都不停
//todo改进方案:先找到所有空格子
//下面的代码是有问题的 有几率无限循环
/*
bool finish = 0;//本轮是否已放置方块
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (!map[i][j]) {
if (rand() % 16 == 0 && finish == 0) {
// 十分之一的概率放4
if (rand() % 10 == 0 ) {
map[i][j]=4;
}
else{
map[i][j]=2;
}
finish = 1;
}
}
}
}
if (finish == 0) {
randomAdd();
}
else{
return;
}
*/
}
void printMap(void){
for (int i = 0; i < 4; i++) {
printf(" ");
for (int j = 0; j < 4; j++) {
printf("%4d ",map[i][j]);
}
printf("\n");
}
return;
}
void getDirection(void){
tmp[0] = tmp[1] = tmp[2] = tmp[3] = 0;
char in = getchar();
switch (in) {
case 'w':
moveUp();
break;
case 's':
moveDown();
break;
case 'a':
moveLeft();
break;
case 'd':
moveRight();
break;
case 'r':
restart();
break;
case 'q':
exit(0);
break;
default:
getDirection();
break;
}
}
void moveUp(void){
for (int line = 0; line < 4; line++) {
for (int i = 0; i < 4; i++) {
tmp[i] = map[i][line];
}
moveMerge();
for (int i = 0; i < 4; i++) {
map[i][line] = tmp[i];
}
}
}
void moveDown(void){
for (int line = 0; line < 4; line++) {
for (int i = 0; i < 4; i++) {
tmp[3 - i] = map[i][line];
}
moveMerge();
for (int i = 0; i < 4; i++) {
map[i][line] = tmp[3 - i];
}
}
}
void moveLeft(void){
for (int line = 0; line < 4; line++) {
for (int i = 0; i < 4; i++) {
tmp[i] = map[line][i];
}
moveMerge();
for (int i = 0; i < 4; i++) {
map[line][i] = tmp[i];
}
}
}
void moveRight(void){
for (int line = 0; line < 4; line++) {
for (int i = 3; i >= 0; i--) {
tmp[3 - i] = map[line][i];
}
moveMerge();
for (int i = 3; i >= 0; i--) {
map[line][i] = tmp[3 - i];
}
}
}
bool checkIfGameOver(void){
//先检查格子是不是都满了
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (!map[i][j]) {
//只要有空的格子 游戏就没结束
return false;
}
}
}
//格子满了之后
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
if (map[i][j] == map[i+1][j] || map[i][j] == map[i][j+1]) {
//如果一个格子和它右边或下边相等 游戏也没结束
//这里数组如果越界访问会返回0 所以不影响结果
return false;
}
}
}
return true;
}
void moveForward(void){
//i为0的话就把最先一个非零的j挪到i的位置
int j = 0;
for (int i = 0; i < 4; i++) {
j++;
if (tmp[i] == 0) {
for (; j < 4; j++) {
if (tmp[j] != 0) {
tmp[i] = tmp[j];
tmp[j] = 0;
break;
}
}
}
}
}
void moveMerge(void){
//处理合并 每合并一次就推进一次
moveForward();
for (int i = 0; i < 3; i++) {
if (tmp[i] == tmp[i + 1]) {
tmp[i] *=2;
tmp[i + 1] = 0;
moveForward();
}
}
}
/*
int countZero(void){
int zero = 0;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (!map[i][j]) {
zero++;
}
}
}
return zero;
}
*/
void restart(void){
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
map[i][j] = 0;
}
}
gameStart();
loop();
}
void loop(void){
for(;;) {
getDirection();
printMap();
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 4; j++) {
if (!map[i][j]) {
//只要有空的格子 就加
randomAdd();
goto go;
}
}
}
go:
if (checkIfGameOver() == true){
printf("You are lose!");
exit(0);
}
}
}
int main() {
gameStart();
loop();
return 0;
}
C语言写的2048小游戏的更多相关文章
- C语言实现简易2048小游戏
一直很喜欢玩这个小游戏,简单的游戏中包含运气与思考与策略,喜欢这种简约又不失内涵的游戏风格.于是萌生了用C语言实现一下的想法. 具体代码是模仿这个:https://www.cnblogs.com/ju ...
- C/C++编程笔记:C语言写推箱子小游戏,大一学习C语言练手项目
C语言,作为大多数人的第一门编程语言,重要性不言而喻,很多编程习惯,逻辑方式在此时就已经形成了.这个是我在大一学习 C语言 后写的推箱子小游戏,自己的逻辑能力得到了提升,在这里同大家分享这个推箱子小游 ...
- Qt 制作2048小游戏
相信大家都玩过2048把,下面是我用qt写得2048小游戏. 2048.pro HEADERS += \ Widget.h SOURCES += \ Widget.cpp \ main.cpp QT ...
- 2048小游戏(Java)(swing实现)(一)
自己写的2048小游戏,仅支持鼠标操作 主要是我不知道怎么添加键盘监听 import javax.swing.*; import java.awt.*; import java.awt.event.* ...
- c#撸的控制台版2048小游戏
1.分析 最近心血来潮,突然想写一个2048小游戏.于是搜索了一个在线2048玩玩,熟悉熟悉规则. 只谈核心规则:(以左移为例) 1.1合并 以行为单位,忽略0位,每列依次向左进行合并,且每列只能合并 ...
- 2048小游戏代码解析 C语言版
2048小游戏,也算是风靡一时的益智游戏.其背后实现的逻辑比较简单,代码量不算多,而且趣味性强,适合作为有语言基础的童鞋来加强编程训练.本篇分析2048小游戏的C语言实现代码. 前言 游戏截图: 游 ...
- C语言初级编程实践:2048小游戏
大部分同学学习C语言编程以后不知道能通过什么样的项目才可以锻炼自己的思维功力,2048相信大家都应该熟悉,不管是手机上还是网页版的相信大家都玩过,这个简单的控制台版本的游戏是我曾经在伟易达上班时一个嵌 ...
- 2048小游戏4X4C语言
*/ #include<stdio.h> #include<stdlib.h> #include<conio.h> #include<time.h> v ...
- Swift实战之2048小游戏
上周在图书馆借了一本Swift语言实战入门,入个门玩一玩^_^正好这本书的后面有一个2048小游戏的实例,笔者跟着实战了一把. 差不多一周的时间,到今天,游戏的基本功能已基本实现,细节我已不打算继续完 ...
随机推荐
- linux系统PKWindows系统,从各方便分析linux和Windows的优劣
服务器系统linux系统和linux系统哪个好用,公说公有理婆说婆有理,今天鼎峰凡凡大概对Linux系统与Windows系统的优缺点PK!可以从以下几个方面来看 ①成本 赞成Linux的声音Linu ...
- SpringMVC与shiro集成及配置文件说明!
在项目中xml文件的配置是必不可少的,特别是SpringMVC框架.但是几乎所有项目的配置都是大同小异,很多人都是直接复制黏贴了事,不少人对其具体含义及用途都不甚全知.本片文章将正对项目中常用的框架S ...
- [翻译] KVNProgress
KVNProgress KVNProgress is a fully customizable progress HUD that can be full screen or not. KVNProg ...
- java获取每月的最后一天
public static void main(String[] args) throws ParseException { // 获取当月的天数(需完善) SimpleDateFormat date ...
- 沉淀再出发:java中的equals()辨析
沉淀再出发:java中的equals()辨析 一.前言 关于java中的equals,我们可能非常奇怪,在Object中定义了这个函数,其他的很多类中都重载了它,导致了我们对于辨析其中的内涵有了混淆, ...
- windows系统镜像 微软官方资源便捷下载教程
今天跟小师弟学到了一个下载软件的好办法,省得到各种网站下载带有病毒,插件的资源. 这个神奇的网站叫做 MSDN, 我告诉你,这是一个私人维护的网站,里面有各种官方软件的下载地址.可以直接用下载工具 ...
- Using shared access signatures (SAS) From Microsoft
A shared access signature (SAS) provides you with a way to grant limited access to objects in your s ...
- php中的extract函数
extract函数用来将一个数字分解成多个变量直接使用,下面是W3C的解释:PHP extract() 函数从数组中把变量导入到当前的符号表中.对于数组中的每个元素,键名用于变量名,键值用于变量值.第 ...
- HTTP协议图--HTTP 报文实体
1. HTTP 报文实体概述 HTTP 报文结构 大家请仔细看看上面示例中,各个组成部分对应的内容. 接着,我们来看看报文和实体的概念.如果把 HTTP 报文想象成因特网货运系统中的箱子,那么 H ...
- linux性能系列--块设备
一.啥是块设备呢? 回答:I/O设备大致分为两类:块设备和字符设备.块设备将信息存储在固定大小的块中,每个块都有自己的地址.数据块的大小通常在512字节到32768字节之间.块设备的基本特征是每个块都 ...