C# 之 带你玩转命令行版《2048》 -- 附源码分享

  • 一,效果展示
  • 二,玩法说明
  • 三,主要逻辑
  • 四,代码实现
    • 4.1 游戏开始
    • 4.2 随机生成
    • 4.3 数字移动
    • 4.4 判断胜负
    • 4.5 重新开始
  • 五,源码分享

一,效果展示


二,玩法说明

  游戏的规则很简单,你需要控制所有方块向同一个方向运动,两个相同数字方块撞在一起之后合并成为他们的和,每次操作之后会随机生成一个2或者4,最终得到一个“2048”的方块就算胜利了。


三,主要逻辑

  • 4*4的二维数组, 然后遍历里面的元素,统计所有的0,放到一个list里面,然后Random.next(0,list.count)随机一个赋成2.
  • 循环开始,初始化命令行.
  • 键盘输入上下左右 对应四种操作的函数 操作之后先遍历一下有没有空格 如果有就继续 没有空格还得再判断一下能不能再动了 如果不能就死了
  • 只需要写向左和向下的逻辑,向右和向上对应取反即可
  • 如果有任何一个元素是2048 即获胜

四,代码实现

4.1 游戏开始

游戏开始:

  • 随机生成两个2
  • 开启游戏循环
    • 每次校验游戏是够结束
    • 检测用户操作(上下左右)
    • 输出当前状态到控制台
/// <summary>
/// 游戏开始
/// </summary>
public void GameStart()
{Add2();Add2();Output();while (true){// 用于遍历检测按下按键之后和之前有没有区别用的bool型变量bool flag = false;// 胜利条件 遍历foreach (int item in arr)     {if (item == 2048){Console.WriteLine("\n(ノ´▽`)ノ♪ ------ 游戏胜利 ------ (ノ´▽`)ノ♪");Last();}}// 这是用于检测按下按键之后和之前有没有区别用的备份数组​int[,] arrtmp = new int[4, 4];// 遍历给备份数组赋值for (int i = 0; i < 4; i++)    {for (int j = 0; j < 4; j++){arrtmp[i, j] = arr[i, j];}}// 获取用户操作 --> 上下左右ConsoleKeyInfo info = Console.ReadKey(true);  switch (info.Key){case ConsoleKey.UpArrow:MoveUp();break;case ConsoleKey.DownArrow:MoveDown();break;case ConsoleKey.LeftArrow:MoveLeft();break;case ConsoleKey.RightArrow:MoveRight();break;}// 遍历检测 按下方向键前的状态 和  按下方向键之后的状态是不是完全一样的for (int i = 0; i < 4; i++)        {for (int j = 0; j < 4; j++){if (arrtmp[i, j] != arr[i, j]){// 一旦有任意一个元素在之前之后不一样  那么falg改为trueflag = true;          }}}if (flag){// 如果falg是true 说明变了, 如果变了 就刷一个2出来,  // 反之就什么也不干Add2();    }// 输出到控制台Output();// 检测按下方向键之后死没死if (!End())   {Console.WriteLine("\n(;´д`)ゞ  ------ 游戏失败 ------ (;´д`)ゞ");Last();}}
}

4.2 随机生成

遍历非零元素 随机把一个赋为2

public void Add2()
{listOfCoo.Clear();// 遍历所有零元素的坐标for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (arr[i, j] == 0){// 把遍历到的坐标 当成参数 实例化CoordinateTools coo = new CoordinateTools(i, j);// 把实例化的结果add到list里listOfCoo.Add(coo);}}}// 如果列表里一个元素都没存进来 说明表里没有空格了 直接退出if (listOfCoo.Count == 0){return;}// 从表里随机取一个位置 ​int cooPlus = rd.Next(0, listOfCoo.Count);// 把这个位置赋值改写为2arr[listOfCoo[cooPlus].x, listOfCoo[cooPlus].y] = 2;
}

4.3 数字移动

已向下移动为例:

  • 非0数向下移动,遇到非0数,相同则累加,不同则保存到当前位置;
  • 向上移动的话,再翻转一下就可以了
public void MoveDown()
{for (int j = 0; j < 4; j++){for (int i = 2; i >= 0; i--){if (arr[i, j] == 0) continue;for (int k = i + 1; k < 4; k++){if (arr[k, j] != 0){if (arr[i, j] == arr[k, j]){arr[k, j] += arr[i, j];arr[i, j] = 0;break;}else if (arr[i, j] != arr[k, j] && k - 1 != i){arr[k - 1, j] = arr[i, j];arr[i, j] = 0;break;}else if (arr[i, j] != arr[k, j] && k - 1 == i){break;}}if (k == 3){arr[k, j] = arr[i, j];arr[i, j] = 0;break;}}}}
}

4.4 判断胜负

判断游戏结束:

  • 遍历数组 有任何一个空元素都说明不可能死
  • 从2开始到2048进行遍历;目的是检测 每一个数字 他上下左右相邻有没有和他一样的数字
// 判断游戏结束
public bool End()
{// 遍历数组 有任何一个空元素都说明不可能死foreach (int item in arr){if (item == 0)return true;}// 从2开始到2048进行遍历   // 目的是检测 每一个数字 他上下左右相邻有没有和他一样的数字 for (int num = 2; num <= 2048; num *= 2){List<CoordinateTools> listOfget2 = new List<CoordinateTools>();for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (arr[i, j] == num){// 先把所有值为NUM的元素的下标 存到list里CoordinateTools coo = new CoordinateTools(i, j);  listOfget2.Add(coo);}}}// 如果这个list 是空的  就说明当前表里没有num 回到FOR继续if (listOfget2 == null)   {continue;}// 从列表里的第一个元素开始 (每一个元素存的都是一组下标x,y)foreach (CoordinateTools item in listOfget2){foreach (CoordinateTools item2 in listOfget2){// 判断 同一行的是不是列坐标差的绝对值是1  同一列的是不是行坐标差的绝对值是1if ((item.y == item2.y && Math.Abs(item.x - item2.x) == 1) || (item.x == item2.x && Math.Abs(item.y - item2.y) == 1))  {// 如果有一个 就不用再循环了 肯定没死return true;    }}}}// 全遍历完了 就说明已经死了 返回falsereturn false;
}

4.5 重新开始

判断游戏结束后,提示用户是“退出”还是“重玩”,根据用户选择进行逻辑处理

/// <summary>
/// 胜利或失败之后的选择
/// </summary>
public void Last()
{Console.WriteLine("\n输入X退出 输入R重新开始\n");while (true){string str = Console.ReadLine();if (str == "x"){Environment.Exit(0);}//重新开始 --> 初始化if (str == "r"){for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){arr[i, j] = 0;}}GameStart();}}
}

五,源码分享

using System;
using System.Collections.Generic;namespace CSharp_2048
{class Program{static void Main(string[] args){Class2048 class2048 = new Class2048();class2048.GameStart();}/// <summary>/// 游戏类2048/// </summary>class Class2048{public int[,] arr = new int[4, 4];public Random rd = new Random();public List<CoordinateTools> listOfCoo = new List<CoordinateTools>();/// <summary>/// 输出当前状态/// </summary>public void Output(){string str = "    ";Console.Clear();Console.WriteLine("┏┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┳┉┉┉┉┉┉┉┉┓");Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┋ {0}   ┋  {1}  ┋  {2}  ┋  {3}  ┋",arr[0, 0] == 0 ? str : arr[0, 0].ToString().PadLeft(4, ' '),arr[0, 1] == 0 ? str : arr[0, 1].ToString().PadLeft(4, ' '), arr[0, 2] == 0 ? str : arr[0, 2].ToString().PadLeft(4, ' '),arr[0, 3] == 0 ? str : arr[0, 3].ToString().PadLeft(4, ' '));Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫");Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┋  {0}  ┋  {1}  ┋  {2}  ┋  {3}  ┋", arr[1, 0] == 0 ? str : arr[1, 0].ToString().PadLeft(4, ' '),arr[1, 1] == 0 ? str : arr[1, 1].ToString().PadLeft(4, ' '),arr[1, 2] == 0 ? str : arr[1, 2].ToString().PadLeft(4, ' '),arr[1, 3] == 0 ? str : arr[1, 3].ToString().PadLeft(4, ' '));Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫");Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┋  {0}  ┋  {1}  ┋  {2}  ┋  {3}  ┋",arr[2, 0] == 0 ? str : arr[2, 0].ToString().PadLeft(4, ' '),arr[2, 1] == 0 ? str : arr[2, 1].ToString().PadLeft(4, ' '), arr[2, 2] == 0 ? str : arr[2, 2].ToString().PadLeft(4, ' '),arr[2, 3] == 0 ? str : arr[2, 3].ToString().PadLeft(4, ' '));Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┣┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉╋┉┉┉┉┉┉┉┉┫");Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┋  {0}  ┋  {1}  ┋  {2}  ┋  {3}  ┋",arr[3, 0] == 0 ? str : arr[3, 0].ToString().PadLeft(4, ' '),arr[3, 1] == 0 ? str : arr[3, 1].ToString().PadLeft(4, ' '),arr[3, 2] == 0 ? str : arr[3, 2].ToString().PadLeft(4, ' '),arr[3, 3] == 0 ? str : arr[3, 3].ToString().PadLeft(4, ' '));Console.WriteLine("┋        ┋        ┋        ┋        ┋");Console.WriteLine("┗┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┻┉┉┉┉┉┉┉┉┛");Console.WriteLine("\n<<命令行版2048>> 请按上下左右(↑←↓→)方向键操作");}/// <summary>/// 遍历非零元素 随机把一个赋为2/// </summary>public void Add2(){listOfCoo.Clear();// 遍历所有零元素的坐标for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (arr[i, j] == 0){// 把遍历到的坐标 当成参数 实例化CoordinateTools coo = new CoordinateTools(i, j);// 把实例化的结果add到list里listOfCoo.Add(coo);}}}// 如果列表里一个元素都没存进来 说明表里没有空格了 直接退出if (listOfCoo.Count == 0){return;}// 从表里随机取一个位置 ​int cooPlus = rd.Next(0, listOfCoo.Count);// 把这个位置赋值改写为2arr[listOfCoo[cooPlus].x, listOfCoo[cooPlus].y] = 2;}/// <summary>/// 游戏开始/// </summary>public void GameStart(){Add2();Add2();Output();while (true){// 用于遍历检测按下按键之后和之前有没有区别用的bool型变量bool flag = false;// 胜利条件 遍历foreach (int item in arr)     {if (item == 2048){Console.WriteLine("\n(ノ´▽`)ノ♪ ------ 游戏胜利 ------ (ノ´▽`)ノ♪");Last();}}// 这是用于检测按下按键之后和之前有没有区别用的备份数组​int[,] arrtmp = new int[4, 4];// 遍历给备份数组赋值for (int i = 0; i < 4; i++)    {for (int j = 0; j < 4; j++){arrtmp[i, j] = arr[i, j];}}// 获取用户操作 --> 上下左右ConsoleKeyInfo info = Console.ReadKey(true);  switch (info.Key){case ConsoleKey.UpArrow:MoveUp();break;case ConsoleKey.DownArrow:MoveDown();break;case ConsoleKey.LeftArrow:MoveLeft();break;case ConsoleKey.RightArrow:MoveRight();break;}// 遍历检测 按下方向键前的状态 和  按下方向键之后的状态是不是完全一样的for (int i = 0; i < 4; i++)        {for (int j = 0; j < 4; j++){if (arrtmp[i, j] != arr[i, j]){// 一旦有任意一个元素在之前之后不一样  那么falg改为trueflag = true;          }}}if (flag){// 如果falg是true 说明变了, 如果变了 就刷一个2出来,  // 反之就什么也不干Add2();    }// 输出到控制台Output();// 检测按下方向键之后死没死if (!End())   {Console.WriteLine("\n(;´д`)ゞ  ------ 游戏失败 ------ (;´д`)ゞ");Last();}}}#region 核心逻辑 --> 向四个方向移动的控制/// <summary>/// 向下 非0数向下移动,遇到非0数,相同则累加,不同则保存到当前位置/// </summary>public void MoveDown(){for (int j = 0; j < 4; j++){for (int i = 2; i >= 0; i--){if (arr[i, j] == 0) continue;for (int k = i + 1; k < 4; k++){if (arr[k, j] != 0){if (arr[i, j] == arr[k, j]){arr[k, j] += arr[i, j];arr[i, j] = 0;break;}else if (arr[i, j] != arr[k, j] && k - 1 != i){arr[k - 1, j] = arr[i, j];arr[i, j] = 0;break;}else if (arr[i, j] != arr[k, j] && k - 1 == i){break;}}if (k == 3){arr[k, j] = arr[i, j];arr[i, j] = 0;break;}}}}}/// <summary>/// 向上移动: 先把数组上下翻转 然后向下移动  移动完了再翻转回来/// </summary>public void MoveUp(){for (int i = 0; i < 2; i++){for (int j = 0; j < 4; j++){int tmp = 0;tmp = arr[i, j];arr[i, j] = arr[3 - i, j];arr[3 - i, j] = tmp;}}MoveDown();for (int i = 0; i < 2; i++){for (int j = 0; j < 4; j++){int tmp = 0;tmp = arr[i, j];arr[i, j] = arr[3 - i, j];arr[3 - i, j] = tmp;}}}/// <summary>/// 向左移动/// </summary>public void MoveLeft(){for (int i = 0; i < 4; i++){for (int j = 1; j < 4; j++){if (arr[i, j] == 0) continue;for (int k = j - 1; k >= 0; k--){if (arr[i, k] != 0){if (arr[i, j] == arr[i, k]){arr[i, k] += arr[i, j];arr[i, j] = 0;break;}else if (arr[i, j] != arr[i, k] && k + 1 != j){arr[i, k + 1] = arr[i, j];arr[i, j] = 0;break;}else if (arr[i, j] != arr[i, k] && k + 1 == j){break;}}if (k == 0){arr[i, k] = arr[i, j];arr[i, j] = 0;break;}}}}}/// <summary>/// 向右移动: 先把数组左右翻转 然后向左移动  移动完了再翻转回来/// </summary>public void MoveRight(){for (int j = 0; j < 2; j++){for (int i = 0; i < 4; i++){int tmp = 0;tmp = arr[i, j];arr[i, j] = arr[i, 3 - j];arr[i, 3 - j] = tmp;}}MoveLeft();for (int j = 0; j < 2; j++){for (int i = 0; i < 4; i++){int tmp = 0;tmp = arr[i, j];arr[i, j] = arr[i, 3 - j];arr[i, 3 - j] = tmp;}}}#endregion/// <summary>/// 判断是否失败/// </summary>/// <returns></returns>public bool End(){// 遍历数组 有任何一个空元素都说明不可能死foreach (int item in arr){if (item == 0)return true;}// 从2开始到2048进行遍历   // 目的是检测 每一个数字 他上下左右相邻有没有和他一样的数字 for (int num = 2; num <= 2048; num *= 2){List<CoordinateTools> listOfget2 = new List<CoordinateTools>();for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){if (arr[i, j] == num){// 先把所有值为NUM的元素的下标 存到list里CoordinateTools coo = new CoordinateTools(i, j);  listOfget2.Add(coo);}}}// 如果这个list 是空的  就说明当前表里没有num 回到FOR继续if (listOfget2 == null)   {continue;}// 从列表里的第一个元素开始 (每一个元素存的都是一组下标x,y)foreach (CoordinateTools item in listOfget2){foreach (CoordinateTools item2 in listOfget2){// 判断 同一行的是不是列坐标差的绝对值是1  同一列的是不是行坐标差的绝对值是1if ((item.y == item2.y && Math.Abs(item.x - item2.x) == 1) || (item.x == item2.x && Math.Abs(item.y - item2.y) == 1))  {// 如果有一个 就不用再循环了 肯定没死return true;    }}}}// 全遍历完了 就说明已经死了 返回falsereturn false;  }/// <summary>/// 胜利或失败之后的选择/// </summary>public void Last(){Console.WriteLine("\n输入X退出 输入R重新开始\n");while (true){string str = Console.ReadLine();if (str == "x"){Environment.Exit(0);}//重新开始 --> 初始化if (str == "r"){for (int i = 0; i < 4; i++){for (int j = 0; j < 4; j++){arr[i, j] = 0;}}GameStart();}}}}/// <summary>/// 工具类 用于存储搜索到的数组的下标/// </summary>class CoordinateTools{public int x { set; get; }public int y { set; get; }public CoordinateTools(int i, int j){this.x = i;this.y = j;}}}
}

C# 之 带你玩转命令行版《2048》 -- 附源码分享相关推荐

  1. java编辑2048小游戏_Java 制作命令行版 2048小游戏

    Java 命令行版 2048小游戏(2020年8月14日) 制作背景 大二即将开学,从头开始学习了一个多月的java,对二维数组的操作稍微熟悉了一些.于是想做一个简单的2048来试一试. 众所周知,2 ...

  2. Python嘎嘎涨知识的7个小游戏,玩过的都爱不释手(附源码,直接运行就可)

    前言 今天星期七,是一个快乐的日子.上班族不用上班,学生不用学习.我也不想分享太多的知识去为难大家,就给大家七个小游戏 吧,从周一玩到周日的那种,学会了记得来找我PK- 1.消消乐 玩法:三个相连就能 ...

  3. 教你用300万共享单车出行数据,预测骑行目的地 !(附源码)

    点击有惊喜 摩拜单车在北京的单车投放量已经超过40万.用户可以直接在人行道上找到停放的单车,用手机解锁,然后骑到目的地后再把单车停好并锁上.因此,为了更好地调配和管理这40万辆单车,需要准确地预测每个 ...

  4. 后渗透——内网转发之借助WinRAR软件用命令行打包压缩网站源码

    WinRAR是一个强大的压缩文件管理工 具.它能备份你的数据,减少你的E-mail附件的大小,解压缩从Internet上下载的RAR.ZIP和其他格式的压缩文件 本章主要讲解怎样用命令行实现对目录文件 ...

  5. 白话生成对抗网络 GAN,50 行代码玩转 GAN 模型!【附源码】

    红色石头的个人网站:redstonewill.com 今天,红色石头带大家一起来了解一下如今非常火热的深度学习模型:生成对抗网络(Generate Adversarial Network,GAN).G ...

  6. 手把手教你生成对抗网络 GAN,50 行代码玩转 GAN 模型!(附源码)

    来源:AI有道 本文约2820字,建议阅读12分钟. 本文为大家介绍了生成对抗网络(Generate Adversarial Network,GAN),以最直白的语言来讲解它,最后实现一个简单的 GA ...

  7. 【数据结构】带你细致理解十大排序(附源码)

    文章目录 前言 一. 冒泡排序 前一个数跟后一个数比较 后一个数跟前一个数比较 优化 复杂度与稳定性 二. 插入排序 初始化条件从第一个元素开始 初始化条件从第二个元素开始 复杂度与稳定性 三. 选择 ...

  8. 【pygame游戏】用Python实现一个蔡徐坤大战篮球的小游戏,可还行?【附源码】

    Python制作坤坤打篮球小游戏 序言 准备工作 开发环境 效果预览 开始界面 游戏规则 结束游戏 代码实现 序言 话说在前面,我不是小黑子~ 我是超级大黑子

  9. 【Python小游戏】一只大猩猩“刷”爆了朋友圈?敢玩这个游戏不?(附源码)

    前言 如果让你模仿大猩猩,你会怎么做?一个典型的动作就是用两只手轮流快速拍打胸口,敲出嘭 嘭嘭打鼓一般的声音.对就是这样

  10. Visual C C++ studio2019 自制鼠标点击器,窗口版和命令行版 210325

    一 窗口版 1.h和cpp h: DesktopMouseClick1.h #pragma once#include "resource.h" #include <threa ...

最新文章

  1. 【Android 安装包优化】WebP 图片格式性能测试 ( 测试 WebP 图片解码速度 | 测试 WebP 图片编码速度 )
  2. 求数组的子数组之和的最大值IV
  3. 【题解】Luogu SP1435 PT07X - Vertex Cover
  4. linux安装python_VTK:华为笔记本电脑+深度deepin-linux+python下安装和入门
  5. oracle 备份教研归档失败,归档日志丢失造成Rman备份失败解决办法
  6. android.mk ndk编译选项优化,Android NDK 编译脚本分析 之一
  7. c语言数组冒泡排序程序的解释,c语言指针数组冒泡排序代码
  8. UiAutomator喷射事件的源代码分析
  9. 知识分享:如何用插件实现操作校验
  10. manjaro Linux下使用腾讯会议
  11. Ubuntu各版本下载安装知网论文阅读神器CAJViewer,并添加快捷图标启动方式
  12. Python词频统计
  13. 安川工业机器人实训心得_安川MOTOMAN工业机器人编程与操作(3)
  14. Chrom浏览器安装CRX插件
  15. 迷茫的程序员和中国软件业
  16. 浏览器怎么录制网页视频?3种网页视频录制方法
  17. 八大经典排序算法(java版)
  18. 抖音短视频买的粉丝是真的吗?多少人懂这点
  19. JdbcTemplate报空指针异常 已解决
  20. 产品管理包括什么和什么_什么是产品管理?

热门文章

  1. 不会打字学计算机难吗,你知道你为什么学不会五笔吗 五笔难学吗
  2. 戴尔710服务器网卡型号怎么查,怎么看网卡驱动有问题_怎么看网卡驱动型号
  3. GitHub下载 无法分配请求的地址_百度网盘破限速软件PanDownload复活了!60MB/s!附下载地址...
  4. python中扑克牌类设计_创建扑克牌类Python
  5. 定时监控服务端口是否正常 发送邮件
  6. win10无限蓝屏_WIN10无限重启怎么解决,现在开不了机
  7. 摆脱五彩斑斓的黑,成为七彩程序员!
  8. QT3D场景快速绘制入门学习
  9. Java8 jdk1.8新特性
  10. 附解决方案,小程序用户昵称突然变成了“微信用户”,而且头像也显示不了?