美文网首页
2.G2048方法的具体实现 && 控制台调用

2.G2048方法的具体实现 && 控制台调用

作者: 半半百 | 来源:发表于2019-03-28 15:53 被阅读0次

方法的具体实现

newBlock()

生成一个新方块

        private Random random = new Random();

        /// <summary>
        /// 生成一个新的方块
        /// </summary>
        private void newBlock()
        {
            //按空方块的总数量随机出此次新增的方块索引
            int r = random.Next(0, Row * Colum - blockCount);
            int value = random.Next(0, 10);
            //随机到0-7时值为2,8或9时值为4
            value = value >= 8 ? 4 : 2;
            //按照索引找到目标方块
            for (int i = 0; i < Row; i++)
            {
                for (int j = 0; j < Colum; j++)
                {
                    if (Map[i, j] == 0)
                    {
                        if (r == 0)
                        {
                            Map[i, j] = value;
                            //更新不为空的方块数量
                            blockCount++;
                            //加个标记
                            LastBlockPoint = new Point(i, j);
                            return;
                        }
                        r--;
                    }
                }
            }
        }
singleMove(Point[] points)

一行或一列坐标的移动,分解为每个坐标向前移动
2,2,4,4 >> 4,0,4,4 >> 4,4,0,4>>4,8,0,0

具体实现如下

        /// <summary>
        /// 一行或一列坐标的移动
        /// </summary>
        /// <param name="points"></param>
        private void singleMove(Point[] points)
        {
            int cur = 0;
            for (int i = 1; i < points.Length; i++)
            {
                int iValue = getMapValue(points[i]);
                if (iValue == 0)
                {
                    continue;
                }
                cur += fall(points, i, cur);
            }
        }

        /// <summary>
        /// 在一行或一列坐标中,索引为i1的向i2落去
        /// </summary>
        /// <param name="points">坐标集合</param>
        /// <param name="i1"></param>
        /// <param name="i2">下落目标点坐标</param>
        /// <returns>下落是否产生了融合 0:是 1:否</returns>
        private int fall(Point[] points, int i1, int i2)
        {
            int value1 = getMapValue(points[i1]);
            int value2 = getMapValue(points[i2]);
            if (value1 == value2)
            {
                setMapValue(points[i2], value2 * 2);
                setMapValue(points[i1], 0);
                //有方块位置发生了变化,记录变化的位置
                Moved.Add(points[i1], points[i2]);
                blockCount--;
                Score += value2 * 2;
                return 1;
            }
            if (value2 == 0)
            {
                setMapValue(points[i2], value1);
                setMapValue(points[i1], 0);
                Moved.Add(points[i1], points[i2]);
                return 0;
            }
            if (i2 + 1 != i1)
            {
                setMapValue(points[i2 + 1], value1);
                setMapValue(points[i1], 0);
                Moved.Add(points[i1], points[i2 + 1]);
            }
            return 1;

        }

        public int getMapValue(Point p)
        {
            return Map[p.X, p.Y];
        }

        private void setMapValue(Point p, int value)
        {
            Map[p.X, p.Y] = value;
        }

       
bool Operate(Direction direction)

一次操作,返回操作是否有效
只需要按方向生成坐标的数组,再分别调用singleMove即可。

        /// <summary>
        /// 向某个方向移动
        /// </summary>
        /// <param name="direction"></param>
        /// <returns>是否是有效的操作(游戏是否产生了变化)</returns>
        public bool Operate(Direction direction)
        {
            if (isGameOver())
            {
                GameOvered();
                return false;
            }
            Moved = new Dictionary<Point, Point>();
            switch (direction)
            {
                case Direction.Up:
                    {
                        for (int c = 0; c < Colum; c++)
                        {
                            Point[] points = new Point[Row];
                            for (int r = 0; r < Row; r++)
                            {
                                points[r] = new Point(r, c);
                            }
                            singleMove(points);
                        }
                    }
                    break;
                case Direction.Down:
                    {
                        for (int c = 0; c < Colum; c++)
                        {
                            Point[] points = new Point[Row];
                            for (int r = 0; r < Row; r++)
                            {
                                points[Row - 1 - r] = new Point(r, c);
                            }
                            singleMove(points);
                        }
                    }
                    break;
                case Direction.Left:
                    {
                        for (int r = 0; r < Row; r++)
                        {
                            Point[] points = new Point[Colum];
                            for (int c = 0; c < Colum; c++)
                            {
                                points[c] = new Point(r, c);
                            }
                            singleMove(points);
                        }
                    }
                    break;
                case Direction.Right:
                    {
                        for (int r = 0; r < Row; r++)
                        {
                            Point[] points = new Point[Colum];
                            for (int c = 0; c < Colum; c++)
                            {
                                points[Colum - 1 - c] = new Point(r, c);
                            }
                            singleMove(points);
                        }
                    }
                    break;
                default:
                    return false;
            }
            //如果所有方块都没有移动(Moved.Count==0),此次操作无效
            bool isChange = Moved.Count == 0 ? false : true;
            if (isChange)
            {
                StepNum++;
                newBlock();
                //如果游戏结束,调用委托
                if (isGameOver())
                {
                    GameOvered?.Invoke();
                }
            }         
            return isChange;
        }
bool isGameOver()

判断游戏是否结束
当所有方块与其右侧下侧值都不同,游戏结束

        /// <summary>
        /// 是否GameOver
        /// </summary>
        /// <returns>res</returns>
        private bool isGameOver()
        {
            if (blockCount != Row * Colum)
            {
                return false;
            }
            for (int i = 0; i < Row; i++)
            {
                for (int j = 0; j < Colum; j++)
                {
                    if (i + 1 < Row && Map[i, j] == Map[i + 1, j])
                    {
                        return false;
                    }
                    if (j + 1 < Colum && Map[i, j] == Map[i, j + 1])
                    {
                        return false;
                    }

                }
            }
            return true;

        }

控制台调用

framework里带的Point类坐标为double型,用不到,所以封装了个简单的,够用就行

public class Point
    {
        public int X { get; set; }
        public int Y { get; set; }
        public Point(int x, int y)
        {
            X = x;
            Y = y;
        }

        public override string ToString()
        {
            return "(" + X + "," + Y + ")";
        }
    }

之后会实现WPF版本,所以UI实现和逻辑还是分开比较好
将G2048类和Point类放一起生成动态库BizLogic.dll
新建控制台程序添加引用,调用即可

using BizLogic;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApp
{
    class Program
    {
        static void Main(string[] args)
        {
            G2048 g = new G2048();
            g.GameOvered += GGWP;
            Console.WriteLine(g.ToString());
            while (true)
            {
                int i = 0;
                try
                {
                    i = Convert.ToInt16(Console.ReadLine());
                    g.Operate((G2048.Direction)i);
                    Console.WriteLine(g.ToString());
                }
                catch { }             
            }
        }
        //游戏结束的实现
        static void GGWP()
        {
            Console.WriteLine("GGWP");
        }
    }
}

相关文章

  • 2.G2048方法的具体实现 && 控制台调用

    方法的具体实现 newBlock() 生成一个新方块 singleMove(Point[] points) 一行或...

  • 链式调用原理

    常规写法: 链式调用: 实现原理: 调用方法之后返回自己,以实现链式调用 具体代码:

  • iOS swap 操作的三种写法

    要点:传递地址,操作指针 方法一: 方法二:调用方法和控制台打印同方法一 方法三:调用方法和控制台打印同方法一 错...

  • Dev-007、IDEA快捷键

    1、方法相关的 Ctrl+Alt+B:查看当前方法的具体实现 Ctrl+B:从被调用的当前方法跳到其方法的具体实现...

  • OC琐碎点汇总(一)

    - (void)方法名:(参数类型)参数名 方法名:(参数类型)参数名 { 具体实现代码 } *方法的调用 [对象...

  • 4.1Spring源码解析——getBean方法的实现

    在这5个类中AbstractBeanFactory完成了getBean()方法的具体实现  这几个方法最终调用的是...

  • oc 基础自定义构造方法

    生命属性和构造方法 方法实现并赋值 调用已有的方法 简化代码 赋值第二种写法 具体实例化赋值 调用结果 最后总结 ...

  • 使用python播放wav语音

    实现的方法可能有很多种,这里我主要使用的是wave+pyAudio来实现。阻塞调用方式 回调调用方式 具体参考文档...

  • iOS - 自定义 下弹框

    具体封装代码 具体的调用方法: 直接调用打开下拉弹框方法[self openPopTopViewAction];或...

  • 自动生成属性的模型

    利用 KVC 实现的自动生成属性的模型 调用下面的方法 在输出控制台输出属性模型, 利用kvc 属性名字与字典的 ...

网友评论

      本文标题:2.G2048方法的具体实现 && 控制台调用

      本文链接:https://www.haomeiwen.com/subject/hpyqbqtx.html