使用C#控制台应用程序完成一个2048小游戏
曾经使用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小游戏的更多相关文章
- 如何在CentOS上安装一个2048小游戏
如何在centos上安装一个2048小游戏 最近在学习CentOS系统,就琢磨着玩点什么,然后我看到有人在玩2048小游戏,所有我就在想,为啥不装一个2048小游戏搞一下嘞,于是乎,我就开始工作啦 由 ...
- c#撸的控制台版2048小游戏
1.分析 最近心血来潮,突然想写一个2048小游戏.于是搜索了一个在线2048玩玩,熟悉熟悉规则. 只谈核心规则:(以左移为例) 1.1合并 以行为单位,忽略0位,每列依次向左进行合并,且每列只能合并 ...
- Swift实战之2048小游戏
上周在图书馆借了一本Swift语言实战入门,入个门玩一玩^_^正好这本书的后面有一个2048小游戏的实例,笔者跟着实战了一把. 差不多一周的时间,到今天,游戏的基本功能已基本实现,细节我已不打算继续完 ...
- 基于jQuery的2048小游戏设计(网页版)
上周模仿一个2048小游戏,总结一下自己在编写代码的时候遇到的一些坑. 游戏规则:省略,我想大部分人都玩过,不写了 源码地址:https://github.com/xinhua6/2048game.g ...
- C# 开发2048小游戏
这应该是几个月前,闲的手痒,敲了一上午代码搞出来的,随之就把它丢弃了,当时让别人玩过,提过几条更改建议,但是时至今日,我也没有进行过优化和更改(本人只会作案,不会收场,嘎嘎),下面的建议要给代码爱好的 ...
- 【2048小游戏】——原生js爬坑之封装行的移动算法&事件
引言:2048小游戏的核心玩法是移动行,包括横行和纵行,玩家可以选择4个方向,然后所有行内的数字就会随着行的移动而向特定的方向移动.这个行的移动是一个需要重复调用的算法,所以这里就要将一行的移动算法封 ...
- .NET手撸2048小游戏
.NET手撸2048小游戏 2048是一款益智小游戏,得益于其规则简单,又和2的倍数有关,因此广为人知,特别是广受程序员的喜爱. 本文将再次使用我自制的"准游戏引擎"FlysEng ...
- jQuery实践-网页版2048小游戏
▓▓▓▓▓▓ 大致介绍 看了一个实现网页版2048小游戏的视频,觉得能做出自己以前喜欢玩的小游戏很有意思便自己动手试了试,真正的验证了这句话-不要以为你以为的就是你以为的,看视频时觉得看懂了,会写了, ...
- 用Python设计一个经典小游戏
这是关于Python的第9篇文章,介绍如何用Python设计一个经典小游戏:猜大小. 在这个游戏中,将用到前面我介绍过的所有内容:变量的使用.参数传递.函数设计.条件控制和循环等,做个整体的总结和复习 ...
随机推荐
- php 检测url
if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@ ...
- android不知不觉偷拍他人功能实现(手机关闭依然拍照)【申明:来源于网络】
android不知不觉偷拍他人功能实现(手机关闭依然拍照)[申明:来源于网络] 地址:http://blog.csdn.net/huangxiaoguo1/article/details/536660 ...
- css学习_css用户界面样式
1.css用户界面样式 a.鼠标样式(记住几个兼容性好的) cursor:default/pointer/move/text; b.轮廓 outline outline:2px solid red: ...
- Java学习:注解,反射,动态编译
狂神声明 : 文章均为自己的学习笔记 , 转载一定注明出处 ; 编辑不易 , 防君子不防小人~共勉 ! Java学习:注解,反射,动态编译 Annotation 注解 什么是注解 ? Annotat ...
- Java ee第五周作业
Applet: Applet是采用Java编程语言编写的小应用程序,该程序可以包含在 HTML(标准通用标记语言的一个应用)页中,与在页中包含图像的方式大致相同. 含有Applet的网页的HTML文件 ...
- Java学习-049-正则工具类
自去年九月份决定再次入学和职业资格进阶,开始备战二者考试至今,以及当下进行中的职称申请,犹如孤独的狼,不断前行在路上,而今凡凡总总的已历8月... 不感慨了,如下为一园友需要的正则工具类,直接上码: ...
- Number 强制类型转换 int 强制转换整型 float 强制转换浮点型 complex 强制转换成复数 bool 强制转换成布尔类型,结果只有两种,要么True 要么 False """bool 可以转换所有的数据类型 everything"""
# ###Number 强制类型转换 var1 = 5 var2 = 4.85 var3 = True var3_2 = False var4 = 3+9j var5 = "888777&q ...
- [LeetCode] 33. Search in Rotated Sorted Array_Medium tag: Binary Search
Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...
- 用python写多线程
import threading #首先导入threading 模块,这是使用多线程的前提 from time import ctime,sleep def music(func): ): print ...
- 深入理解Java虚拟机5-chap7-斗者2星
一.类加载机制 1.类加载机制:虚拟机把描述类的数据从Class文件加载到内存,并对数据进行校验.转换解析和初始化,最终形成可以被虚拟机直接使用的Class文件加载到内存,这就是类加载机制. 2.类型 ...