曾经使用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. GitLab上传项目到新的分支

    多人协同开发,GitLab上的group仓库里的master分支作为开发分支(最终从dev提交的代码),dev分支作为每个人的代码测试后合并的分支,每个人需要定期merge request自己的分支到 ...

  2. VS code -python 使用笔记本

    1--使用虚拟环境 |----setting->search: python.venv->设置  venv path (你创建的虚拟环境文件夹所在路径,此处我的是 - 目录下) |---- ...

  3. stm8 iar开发

    1.一份官方库基本是通用的. 2.尽量依托cubex for stm8 依托理由: 1.不同型号,不同后缀的芯片,将会被配置不同的外设.比如stm8s103k3系列可能有的是串口1,但是stm8s10 ...

  4. LeetCode 12 - 整数转罗马数字 - [简单模拟]

    题目链接:https://leetcode-cn.com/problems/integer-to-roman/ 题解: 把 $1,4,5,9,10,40,50, \cdots, 900, 1000$ ...

  5. redis问题与解决思路

    问题现象: 集群状态 1主 2从,主没有开启bgsave,从开启bgsave.现象所有redis可以访问,进行操作.主不断开始bgsave 1从停止bgsave. 主日志报错# Connection ...

  6. (在命名空间 public 中)存在冲突

    解决方案: http://www.wastedpotential.com/flash-as3-stop-using-automatically-declare-stage-instances/ 修复错 ...

  7. C++11 使用异步编程std::async和std::future

    先说明一点:std::asyanc是std::future的高级封装, 一般我们不会直接使用std::futrue,而是使用对std::future的高级封装std::async. 下面分别说一下. ...

  8. BeanUtils工具类

    用对象传参,用JavaBean传参. BeanUtils可以优化传参过程. 学习框架之后,BeanUtils的功能都由框架来完成. 一.为什么用BeanUtils? 每次我们的函数都要传递很多参数很麻 ...

  9. day014 模块

    # 1.用于多种语言交互 编程语言通用数据 # 内置的 不需要安装 直接导入使用 import json # 导入一个json模块 # dumps loads# dump load 有持久化的功能 # ...

  10. 【Data Structure】-NO.117.DS.1 -【Tree-23树】

    [Data Structure]-NO.117.DS.1 -[Tree-23树] Style:Mac Series:Java Since:2018-09-10 End:2018-09-10 Total ...