开篇

2048游戏现在很火啊,很多人应该已经玩过了。在博客园上也看见有人模仿做的GDI+版 2048游戏,鄙人暂且不做那么多动画的东西,毕竟是个小东东,在此奉上一个《控制台版2048》。

本文程序源码下载:http://pan.baidu.com/s/1mg8zntu

程序结构相对简单,一共200+行代码,注释很少,大家大概也看得懂,我在这解释下程序中各个方法的含义:
Main 方法程序入口,
RePaint 类似Win32程序中的刷新界面,
SquareRot90 矩形矩阵顺时针旋转90度角(参数可以为负,表示逆时针)。
Merge 向左移动,合并单元格中值相同的元素,并进行整理(将所有元素靠左放置)
RandomPoint 随机生成点,从矩阵的空位置(值为0)中随机生成一个点,若不存在空位置返回null。
CanMove 判断是否可以继续移动,也是判断游戏是否结束的方法。
IsEquals 判断两矩阵的值是否相同。
CopyToB 将矩阵复制一份。
流程图如下:
上代码
 
主函数Main
static void Main(string[] args)
{
int[,] a = new int[4, 4];
a[1, 2] = 2;
a[2, 2] = 2;
a[2, 1] = 2;
RePaint(a);
while (true)
{
ConsoleKeyInfo key = Console.ReadKey();
switch (key.Key)
{
case ConsoleKey.UpArrow:
a = SquareRot90(a, 3);
a = Merge(a);
a = SquareRot90(a, -3);
break;
case ConsoleKey.DownArrow:
a = SquareRot90(a, 1);
a = Merge(a);
a = SquareRot90(a, -1);
break;
case ConsoleKey.LeftArrow:
a = Merge(a);
break;
case ConsoleKey.RightArrow:
a = SquareRot90(a, 2);
a = Merge(a);
a = SquareRot90(a, -2);
break;
}
Point cp = RandomPoint(a);
if (cp != null)
{
a[cp.X, cp.Y] = 2;
RePaint(a);
}
if (cp == null && !CanMove(a))
{
RePaint(a, "Game Over");
}
}
}

  

矩阵旋转方法
/// 矩形顺时针旋转90°
/// </summary>
/// <param name="rotNum">旋转次数</param>
public static int[,] SquareRot90(int[,] a, int rotNum)
{
while (rotNum < 0)
{
rotNum += 4;
}
for (int rot_i = 0; rot_i < rotNum; rot_i++)
{
int[,] b = new int[a.GetLength(1), a.GetLength(0)];
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
b[j, a.GetLength(0) - i - 1] = a[i, j];
}
}
a = b;
}
return a;
}

  

随机点方法
public static Point RandomPoint(int[,] a)
{
List<Point> lstP = new List<Point>();
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
if (a[i, j] == 0)
{
lstP.Add(new Point(i, j));
}
}
}
if (lstP.Count == 0)
{
return null;
}
int rnd = new Random().Next(lstP.Count);
return lstP[rnd];
}

  

矩阵向左合成方法
public static int[,] Merge(int[,] a)
{
for (int i = 0; i < a.GetLength(0); i++)
{
int lastNum = 0;
int last_j = 0;
for (int j = 0; j < a.GetLength(1); j++)//合并
{
if (lastNum != a[i, j] && a[i, j] != 0)
{
lastNum = a[i, j];
last_j = j;
}
else if (lastNum == a[i, j])
{
a[i, last_j] = 0;
a[i, j] = lastNum + a[i, j];
}
}
last_j = 0;
for (int j = 0; j < a.GetLength(1); j++)//整理
{
if (a[i, j] != 0)
{
a[i, last_j] = a[i, j];
if (last_j != j)
a[i, j] = 0;
last_j++;
}
}
}
return a;
}

  

是否可以继续移动CanMove方法
public static bool CanMove(int[,] a)
{
bool res = false;
int[,] b = CopyToB(a);
b = Merge(b);
if (!IsEquals(a, b))
res = true;
b = CopyToB(a);
b = SquareRot90(b, 1);
b = Merge(b);
b = SquareRot90(b, -1);
if (!IsEquals(a, b))
res = true;
b = CopyToB(a);
b = SquareRot90(b, 2);
b = Merge(b);
b = SquareRot90(b, -2);
if (!IsEquals(a, b))
res = true;
b = CopyToB(a);
b = SquareRot90(b, 3);
b = Merge(b);
b = SquareRot90(b, -3);
if (!IsEquals(a, b))
res = true;
return res;
}

  

CanMove中用到的IsEquals方法,判断矩阵相等
public static bool IsEquals(int[,] a, int[,] b)
{
bool res = true;
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
if (b[i, j] != a[i, j])
{
res = false;
break;
}
}
if (!res)
break;
}
return res;
}

  

CanMove中用到的矩阵复制方法CopyToB
public static int[,] CopyToB(int[,] a)
{
int[,] b = new int[a.GetLength(0), a.GetLength(1)];
for (int i = 0; i < a.GetLength(0); i++)
{
for (int j = 0; j < a.GetLength(1); j++)
{
b[i, j] = a[i, j];
}
}
return b;
}

  

两个RePain方法,重新打印,前面的表示GameOver
public static void RePaint(int[,] a, string s)
{
while (true)
{
Console.Clear();
RePaint(a);
Console.WriteLine("\n\n\n\n\t\t" + s + "\n\n");
Console.ReadKey();
}
}
public static void RePaint(int[,] a)
{
Console.Clear();
for (int j = 0; j < a.GetLength(1); j++)
{
Console.Write("───");
}
Console.Write("\n");
for (int i = 0; i < a.GetLength(0); i++)
{
Console.Write("│");
for (int j = 0; j < a.GetLength(1); j++)
{
string s = "";
if (a[i, j] == 0)
s = " ";
else if (a[i, j] < 10)
s = " " + a[i, j] + " ";
else if (a[i, j] < 100)
s = "" + a[i, j] + " ";
else
s = "" + a[i, j];
Console.Write(s + "│");
}
Console.Write("\n");
for (int j = 0; j < a.GetLength(1); j++)
{
Console.Write("───");
}
Console.Write("\n");
}
}

  

辅助类Point
class Point
{
public Point(int x, int y)
{
this.X = x;
this.Y = y;
}
public int X
{
get;
set;
}
public int Y
{
get;
set;
}
}

  

结束语
     其实要写一个游戏并不是像想像中那么容易,要处理算法等问题,必须要事先仔细的设计,需要一张草纸作为设计图,这样会让工作效率大大提高。之前贴过毕设的游戏《保卫萝卜》,由于时间关系迟迟没有整理,等毕设答辩完成后,一定好好整理,给大家分享。现在功能基本完成了,在这先贴一个缩减版的游戏程序,链接: http://pan.baidu.com/s/1sjvxO7N 。程序有什么问题、BUG,希望大家多多留言。源码整理后再上传。
     过几天是蓝桥杯比赛,哈哈,北京我来了。
本文程序源码下载:http://pan.baidu.com/s/1mg8zntu 
 

2048 控制台版(C#)的更多相关文章

  1. c/c++ 贪吃蛇控制台版

    贪吃蛇控制台版(操作系统win7 64位:编译环境gcc, vs2017通过,其它环境未测试 不保证一定通过) 运行效果: #include <iomanip> #include < ...

  2. 基于TCP协议的聊天室控制台版

    我之前写过一篇博客,主要是基于TCP协议实现的聊天室swing版,在此再写一个基于TCP协议实现的聊天室控制台版,便于学习和比较. package 聊天室console版.utils; import ...

  3. c++实现通讯录管理系统(控制台版)

    c++实现通讯录管理系统(控制台版) 此项目适合c++初学者,针对c++基础知识,涉及到变量.结构体定义使用.数组定义使用.指针定义使用等. 运行之后的结果如下: 代码: #include <i ...

  4. C++实现控制台版2048

    前言 之前做过一个JavaScript版本的2048游戏,最近在学习C++,昨天晚上突然心血来潮,想用C++来实现,因为核心算法已十分理解,所以两个小时撸出来一个C++的简易版本. 简介 二维数组遍历 ...

  5. c#撸的控制台版2048小游戏

    1.分析 最近心血来潮,突然想写一个2048小游戏.于是搜索了一个在线2048玩玩,熟悉熟悉规则. 只谈核心规则:(以左移为例) 1.1合并 以行为单位,忽略0位,每列依次向左进行合并,且每列只能合并 ...

  6. Delphi_01_控制台版HelloWorld

    对于Windows下的控制台编程,我相信很多人都不陌生.而C语言开始的著名的“Hello world”程序基本是学习编程的第一步.我想对于 RAD开发,大家熟悉的一般都是GUI编程,而对于consol ...

  7. [C++项目]2048控制台游戏

    #include <iostream> #include <windows.h> #include <ctime> using namespace std; ; ; ...

  8. Java小例子(学习整理)-----学生管理系统-控制台版

    1.功能介绍: 首先,这个小案例没有使用数据库,用集合的形式暂时保存数据,做测试! 功能: 增加学生信息 删除学生信息 修改学生信息 查询学生信息:  按照学号(精确查询)  按照姓名(模糊查询) 打 ...

  9. 2048聚合版开源代码,cocos2d-js编写,基于CocosEditor开发工具,可运行Android,ios,html5等

    1. [代码][JavaScript]代码         /** * @GameName : * 2048 * * @DevelopTool: * Cocos2d-x Editor (CocosEd ...

随机推荐

  1. bootstrap组件和插件

    一.用node.js读取文件 //引入fs模块 var fs= require ('fs'); // console.log(fs); //调用fs模块的readFile方法 fs.readFile( ...

  2. Java 函数传入参数后,究竟发生了什么?java函数传参数原理解析

    JAVA函数在传入参数A时,会在函数作用周期内生成一个与参数相同类型的局部变量B. B与A指向同一块内存区域,并且具有相同的名字如param. 在函数内所有对param的操作都是对B的操作.对B进行赋 ...

  3. 从此Redis是路人

    从此Redis是路人 序言:Redis(Remote DIctionary Server)作为一个开源/C实现/高性能/基于内存的key-value存储系统,相信做Java的小伙伴都不会陌生.Redi ...

  4. 08 JS的事件流的概念(重点)

    在学习jQuery的事件之前,大家必须要对JS的事件有所了解.看下文 事件的概念 HTML中与javascript交互是通过事件驱动来实现的,例如鼠标点击事件.页面的滚动事件onscroll等等,可以 ...

  5. eclipse 工具在工作中实用方法

    不断更新记录工作中用到的实用技巧 1.快捷方式管理多个工作空间 参数: -showlocation 设置eclipse顶部显示工作空间位置 -data 文件位置 设置打开的工作空间位置 创建eclip ...

  6. ASP.NET Core[源码分析篇] - 认证

    追本溯源,从使用开始 首先看一下我们的通常是如何使用微软自带的认证,一般在Startup里面配置我们所需的依赖认证服务,这里通过JWT的认证方式讲解 public void ConfigureServ ...

  7. 【fullGC】内存监控工具

    什么是fullGC: 从年轻代空间(包括 Eden 和 Survivor 区域)回收内存被称为 Minor GC,对老年代GC称为Major GC,而Full GC是对整个堆来说的,在最近几个版本的J ...

  8. 跟我学SpringCloud | 第六篇:Spring Cloud Config Github配置中心

    SpringCloud系列教程 | 第六篇:Spring Cloud Config Github配置中心 Springboot: 2.1.6.RELEASE SpringCloud: Greenwic ...

  9. top命令输出详解

    前言 Linux下的top命令我相信大家都用过,自从我接触Linux以来就一直用top查看进程的CPU和MEM排行榜.但是top命令的其他输出结果我都没有了解,这些指标都代表什么呢,什么情况下需要关注 ...

  10. 小代学Spring Boot之开篇

    想要获取更多文章可以访问我的博客 - 代码无止境. 前情提要 小代是一名入职不久的程序员,公司同事都亲切的称他小代.有一天小代的老大陈BOSS和小代说,公司后端最近准备换技术框架了. 小代: 换成啥? ...