曾经使用C#控制台应用程序写的一个2048,现在翻出来回顾一下

  • Box类是2048中每一个小格子的相关信息,包括格子的横纵坐标、格子的值和格子是否刚合并这些信息。
  • Grid类是网格的相关信息,包括网格的长宽(默认是4X4,也可以改成其他形式的),分数等。
  • Manager2048类是个大杂烩的类,写的很乱,什么乱七八糟的方法都丢在了里面。

=================================贼好看的分割线=============

Program.CS

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _031_test
{
/// <summary>
/// 2048
/// </summary>
class Program
{
static void Main(string[] args)
{
Manager2048 m2048 = new Manager2048();
m2048.Strat();
m2048.Control(); Console.ReadLine();
}
}
}

Program.CS

Box.CS

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace _031_test
{
/// <summary>
/// 格子
/// </summary>
class Box
{
//格子的坐标
int row;
int col;
public int Row { get { return row; } }
public int Col { get { return col; } }
//格子的值
public int Value { get; set; }
//是否已经合并
public bool IsMerge { get; set; } public Box(int row,int col)
{
this.row = row;
this.col = col;
//初始化默认值为0
this.Value = ;
this.IsMerge = false;
} }
}

Box.CS

Grid.CS

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO; namespace _031_test
{
/// <summary>
/// 网格
/// </summary>
class Grid
{
//网格的长宽
int rows;
int cols;
public int Rows { get { return rows; } }
public int Cols { get { return cols; } } public int score; public int randomTimes = ;//判断游戏是否结束的标识位16结束
Random random;
//存放格子对象
public Box[,] bList;
//是否是第一次,第一次则出现两个数,否则只出现一个数
bool isFirst = true; public Grid(int rows, int cols)
{
this.random = new Random();
this.rows = rows < ? : rows;
this.cols = cols < ? : cols;
bList = new Box[rows, cols];
} //初始化
public void InitGrid()
{
//对网格中的每一个格子进行初始化,并将每一个格子对象存入bList中
for (int i = ; i < bList.GetLength(); i++)
{
for (int j = ; j < bList.GetLength(); j++)
{
Box box = new Box(i, j);
bList[i, j] = box;
}
}
RandomNum();
}
///////////////////////////////////
//随机---包括生成的数字和位置
public void RandomNum()
{
//count表示要生成的数字的个数,进行判断,初始化时候生成两个,否则就一个
int count;
if (isFirst) { count = ; isFirst = false; }
else count = ; int i = ;
while (i < count)
{
//随机出现数字的下标
int r = random.Next(, rows);
int c = random.Next(, cols);
//若随机到的位置已经有值了,则返回重新随机
if (bList[r, c].Value != ) continue;
//随机2和4 出现几率 80% 20%
int valuePercent = random.Next(, );
//将出现的值
int value;
if (valuePercent < ) value = ;
else value = ;
bList[r, c].Value = value;
i++;
//当randomTimes到16时说明所有格子都满了
randomTimes++;
}
} //显示游戏界
public void DisPlay()
{
Console.WriteLine("===============================");
for (var i = ; i < bList.GetLength(); i++)
{
for (var j = ; j < bList.GetLength(); j++)
{
Console.Write(bList[i, j].Value + "\t");
}
Console.WriteLine("\n");
}
Console.WriteLine("===============================");
Console.WriteLine("当前分数:" + score + "历史最高:" + Int32.Parse(File.ReadAllText("score.txt")));
} }
}

Grid.CS

Manager2048.CS

 using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO; namespace _031_test
{
/// <summary>
/// 控制器
/// </summary>
class Manager2048
{
Grid g; public Manager2048()
{
g = new Grid(, );
} //开始游戏 public void Strat()
{
g.InitGrid();
g.DisPlay();
Console.WriteLine("游戏开始,请直接使用方向键进行操作");
} public void Control()
{
while (true)
{
//ConsoleKeyInfo可以直接接受一个字符不需要再按下回车键确认
ConsoleKeyInfo keyInfo = Console.ReadKey();
switch (keyInfo.Key)
{
case ConsoleKey.UpArrow: Up(); break;
case ConsoleKey.DownArrow: Down(); break;
case ConsoleKey.LeftArrow: Left(); break;
case ConsoleKey.RightArrow: Right(); break;
default: Console.WriteLine("按错了"); break;
}
if (g.randomTimes==g.Rows*g.Cols&&!CanWeMergeInFull())
{
Console.WriteLine("游戏结束");
break;
}
}
} public void Up()
{
bool ismove=false;
//遍历每一个box,检测该box是否要移动
for (int i = ; i < g.bList.GetLength(); i++)//向上移动不需要考虑第一行的上移,所以直接i=1
{
for (int j = ; j < g.bList.GetLength(); j++)
{
//如果该box值不是0,说明该box需要移动,否则继续遍历下一个box
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
//从该box的上一行开始一直遍历到最顶上
int k = i - ;
while (k >= )
{
if (g.bList[k, j].Value != || k == ) break;
else k--;
}
//如果碰到了和要移动的box值一样的box,就要把他们合并(IsMerge:当这个box是这一轮合并来的box时,则不能合并)
if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge==false)
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp * ;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.bList[k, j].IsMerge = true;
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge==true)
{
g.bList[i, j].Value = ;
g.bList[k + , j].Value = temp;
//i=k+1表示该box并没有移动
if (i == k + ) ismove = false;
else ismove = true;
}
//值不一样的时候,就把要移动的box放到这个box下面去
else if (g.bList[k, j].Value != )
{
g.bList[i, j].Value = ;
g.bList[k + , j].Value = temp;
if (i == k + ) ismove = false;
else ismove = true;
}
//这种情况是遍历到最顶行的box且该box为0时,直接把要动的box移到这
else
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp;
if (i == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();//当所有格子都满了时就不随机生成数字
else Console.WriteLine("该方向无法移动");
ResetIsMerge();//重置所有box的合并状态为false
g.DisPlay();
} public void Down()
{
bool ismove = false;
//错误写法:for (int i = 0; i < g.bList.GetLength(0) - 1; i++)
//以上写法会导致上层的数先被遍历从而导致先移动完毕,所以要从最后一个数开始遍历
for (int i = g.bList.GetLength() - ; i >= ; i--)
{
for (int j = g.bList.GetLength() - ; j >= ; j--)
{
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
int k = i + ;
while (k <= g.bList.GetLength() - )
{
if (g.bList[k, j].Value != || k == g.bList.GetLength() - ) break;
else k++;
}
if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge == false)
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp * ;
g.bList[k, j].IsMerge = true;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[k, j].Value && g.bList[k, j].IsMerge == true)
{
g.bList[i, j].Value = ;
g.bList[k - , j].Value = temp;
if (i == k - ) ismove = false;
else ismove = true;
}
else if (g.bList[k, j].Value != )
{
g.bList[i, j].Value = ;
g.bList[k - , j].Value = temp;
if (i == k - ) ismove = false;
else ismove = true;
}
else
{
g.bList[i, j].Value = ;
g.bList[k, j].Value = temp;
if (i == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();
else Console.WriteLine("该方向无法移动");
ResetIsMerge();
g.DisPlay();
} public void Left()
{
bool ismove = false;
for (int i = ; i < g.bList.GetLength(); i++)
{
for (int j = ; j < g.bList.GetLength(); j++)
{
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
int k = j - ;
while (k >= )
{
if (g.bList[i, k].Value != || k == ) break;
else k--;
}
if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == false)
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp * ;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.bList[k, j].IsMerge = true;
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == true)
{
g.bList[i, j].Value = ;
g.bList[i, k + ].Value = temp;
if (j == k + ) ismove = false;
else ismove = true;
}
else if (g.bList[i, k].Value != )
{
g.bList[i, j].Value = ;
g.bList[i, k + ].Value = temp;
if (j == k + ) ismove = false;
else ismove = true;
}
else
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp;
if (j == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();
else Console.WriteLine("该方向无法移动");
ResetIsMerge();
g.DisPlay();
} public void Right()
{
bool ismove = false;
//错误写法:for (int i = 0; i < g.bList.GetLength(0) - 1; i++)
//以上写法会导致上层的数先被遍历从而导致先移动完毕,所以要从最后一个数开始遍历
for (int i = g.bList.GetLength() - ; i >= ; i--)
{
for (int j = g.bList.GetLength() - ; j >= ; j--)
{
if (g.bList[i, j].Value != )
{
int temp = g.bList[i, j].Value;
int k = j + ;
while (k <= g.bList.GetLength() - )
{
if (g.bList[i, k].Value != || k == g.bList.GetLength() - ) break;
else k++;
}
if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == false)
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp * ;
g.score += temp * ;
if (g.score > Int32.Parse(File.ReadAllText("score.txt")))
{
File.WriteAllText("score.txt", g.score.ToString());
}
g.bList[k, j].IsMerge = true;
g.randomTimes--;
ismove = true;
}
else if (temp == g.bList[i, k].Value && g.bList[i, k].IsMerge == true)
{
g.bList[i, j].Value = ;
g.bList[i, k - ].Value = temp;
if (j == k - ) ismove = false;
else ismove = true;
}
else if (g.bList[i, k].Value != )
{
g.bList[i, j].Value = ;
g.bList[i, k - ].Value = temp;
if (j == k - ) ismove = false;
else ismove = true;
}
else
{
g.bList[i, j].Value = ;
g.bList[i, k].Value = temp;
if (j == k) ismove = false;
else ismove = true;
}
}
}
}
if (ismove && !IsFull()) g.RandomNum();
else Console.WriteLine("该方向无法移动");
ResetIsMerge();
g.DisPlay();
} //判断网格是否已满
public bool IsFull()
{
for (int i = ; i < g.Rows; i++)
{
for (int j = ; j < g.Cols; j++)
{
if (g.bList[i, j].Value == )
{
return false;
}
}
}
return true;
} //重置所有box合并状态
public void ResetIsMerge()
{
for (int i = ; i < g.Rows; i++)
{
for (int j = ; j < g.Cols; j++)
{
g.bList[i, j].IsMerge = false;
}
}
} //网格满时是否还可以继续合并 true表示还有能合并的
public bool CanWeMergeInFull()
{
for (int i = ; i < g.Rows; i++)
{
for (int j = ; j < g.Cols; j++)
{
//检测上方向
if (i - >= && g.bList[i, j].Value == g.bList[i - , j].Value)
{
return true;
}
//检测下方向
if (i + < g.Rows && g.bList[i, j].Value == g.bList[i + , j].Value)
{
return true;
}
//检测左方向
if (j - >= && g.bList[i, j].Value == g.bList[i, j - ].Value)
{
return true;
}
//检测右方向
if (j + < g.Cols && g.bList[i, j].Value == g.bList[i, j + ].Value)
{
return true;
}
}
}
return false;
} }
}

Manager2048.CS

=================================贼好看的分割线=============

最终效果:

使用C#控制台应用程序完成一个2048小游戏的更多相关文章

  1. 如何在CentOS上安装一个2048小游戏

    如何在centos上安装一个2048小游戏 最近在学习CentOS系统,就琢磨着玩点什么,然后我看到有人在玩2048小游戏,所有我就在想,为啥不装一个2048小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...

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

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

  3. Swift实战之2048小游戏

    上周在图书馆借了一本Swift语言实战入门,入个门玩一玩^_^正好这本书的后面有一个2048小游戏的实例,笔者跟着实战了一把. 差不多一周的时间,到今天,游戏的基本功能已基本实现,细节我已不打算继续完 ...

  4. 基于jQuery的2048小游戏设计(网页版)

    上周模仿一个2048小游戏,总结一下自己在编写代码的时候遇到的一些坑. 游戏规则:省略,我想大部分人都玩过,不写了 源码地址:https://github.com/xinhua6/2048game.g ...

  5. C# 开发2048小游戏

    这应该是几个月前,闲的手痒,敲了一上午代码搞出来的,随之就把它丢弃了,当时让别人玩过,提过几条更改建议,但是时至今日,我也没有进行过优化和更改(本人只会作案,不会收场,嘎嘎),下面的建议要给代码爱好的 ...

  6. 【2048小游戏】——原生js爬坑之封装行的移动算法&事件

    引言:2048小游戏的核心玩法是移动行,包括横行和纵行,玩家可以选择4个方向,然后所有行内的数字就会随着行的移动而向特定的方向移动.这个行的移动是一个需要重复调用的算法,所以这里就要将一行的移动算法封 ...

  7. .NET手撸2048小游戏

    .NET手撸2048小游戏 2048是一款益智小游戏,得益于其规则简单,又和2的倍数有关,因此广为人知,特别是广受程序员的喜爱. 本文将再次使用我自制的"准游戏引擎"FlysEng ...

  8. jQuery实践-网页版2048小游戏

    ▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...

  9. 用Python设计一个经典小游戏

    这是关于Python的第9篇文章,介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习 ...

随机推荐

  1. tcpdf开发文档(中文翻译版)

    2017年5月3日15:06:15 这个是英文翻译版,我看过作者的文档其实不太友善或者不方便阅读,不如wiki方便 后面补充一些,结构性文档翻译 这是一部官方网站文档,剩余大部分都是开发的时候和网络总 ...

  2. CS1704问题汇总

    “/”应用程序中的服务器错误. 编译错误 说明: 在编译向该请求提供服务所需资源的过程中出现错误.请检查下列特定错误详细信息并适当地修改源代码. 编译器错误消息: CS1704: 已经导入了具有相同的 ...

  3. block,inline和inline-block概念和区别(转载)

    转自: http://www.cnblogs.com/KeithWang/p/3139517.html 总体概念 block和inline这两个概念是简略的说法,完整确切的说应该是 block-lev ...

  4. Git环境配置

    1,下载Git-2.16.2-64-bit.exe并安装, 全部为默认设置 下载地址:http://git-scm.com/download/win 2 在开始菜单中,单击Git CMD,执行下面命令 ...

  5. POJ 1986 Distance Queries(LCA Tarjan法)

    Distance Queries [题目链接]Distance Queries [题目类型]LCA Tarjan法 &题意: 输入n和m,表示n个点m条边,下面m行是边的信息,两端点和权,后面 ...

  6. mysql----------mysql5.7如何配置主从数据库

    主库: 1.配置文件里面加入以下两行 server-id=1 log-bin=MySQL-bin 2.创建账户 grant replication client,replication slave o ...

  7. docker构建本地仓库后,无法登陆解决办法(CentOS/Ubuntu)

    docker版本为:Server Version: 1.12.6 从dockerhub上下载最新的registry镜像. 首先.构建registry 1.下载registry镜像 docker pul ...

  8. 前端学习历程--js--原型&闭包

    一.数据类型 1.值类型:undefined, number, string, boolean,不是对象 2.引用类型:函数.数组.对象.null.new Number(10)都是对象 3.引用类型判 ...

  9. Nginx技术研究系列5-动态路由升级版

    前几篇文章我们介绍了Nginx的配置.OpenResty安装配置.基于Redis的动态路由以及Nginx的监控. Nginx-OpenResty安装配置 Nginx配置详解 Nginx技术研究系列1- ...

  10. 初入MEF-IOC导入导出

    DDD,领域驱动开发,听起来高端大气,这本书买回来翻了几下,实在是晦涩难懂