C#游戏项目——飞行棋(附项目源码)

【投稿赢 iPhone 17】「我的第一个开源项目」故事征集:用代码换C位出道! 10w+人浏览 1.6k人参与

前言:项目视频展示

飞行棋

一、项目概述

        本项目是一个基于C#控制台开发的飞行棋游戏,实现了完整的游戏流程和丰富的游戏功能。游戏支持双人对战(玩家vs电脑),包含多种特殊格子效果,提供了良好的用户交互体验。

二、项目结构

1、核心架构

        项目采用场景管理模式,分为三个主要场景
(1)开始场景:游戏主菜单界面
(2)游戏场景:核心游戏玩法界面
(3)结束场景:游戏结果显示界面

2、技术特点

(1)纯控制台界面实现
(2)面向对象编程思想
(3)模块化设计结构
(4)完整的游戏状态管理

三、核心功能模块

1. 场景管理系统

enum E_SceneType
{
    Begin,  // 开始场景
    Game,   // 游戏场景
    End,    // 结束场景
}

2. 游戏地图系统

(1)地图生成:随机生成80个格子
(2)格子类型:
        普通格子(85%概率)
        炸弹格子(5%概率)- 倒退5格
        暂停格子(5%概率)- 暂停一回合
        时空隧道(5%概率)- 随机效果

3. 玩家系统

(1)双玩家支持(玩家和电脑)
(2)玩家状态管理(位置、暂停状态)
(3)可视化表示(不同符号和颜色)

四、游戏规则

1、基本规则

(1)玩家和电脑轮流掷骰子前进
(2)先到达终点的玩家获胜
(3)遇到特殊格子触发相应效果
2、特殊格子效果

(1)炸弹格子:后退5格
(2)暂停格子:暂停一回合
(3)时空隧道:
                30%概率:后退5格
                30%概率:暂停一回合
                40%概率:与对方交换位置

五、界面设计

1、控制台界面布局

(1)游戏区域:顶部主要显示区域
(2)信息区域:底部状态提示区域
(3)围墙装饰:红色方块边界

2、视觉元素

        玩家:★(青色)
        电脑:▲(洋红色)
        重合:◎(深绿色)
格子类型使用不同颜色区分

六、核心算法

1、地图生成思想

// 智能路径生成,自动转向
if (indexX == 10)
{
    y += 1;
    ++indexY;
    if (indexY == 2)
    {
        indexX = 0;
        indexY = 0;
        stepNum = -stepNum; // 反向移动
    }
}

2、游戏逻辑流程

(1)初始化游戏场景
(2)绘制地图和玩家
(3)轮流执行玩家回合
(4)检测游戏结束条件
(5)返回相应场景

七、总结

        本项目展示了一个完整的C#控制台游戏开发案例,涵盖了游戏开发的多个重要方面:场景管理、对象设计、算法实现、用户交互等。代码结构清晰,功能完整,具有良好的可读性和可扩展性,适合作为学习C#游戏开发的参考项目。

八、附录源代码

using System;
namespace 测试
{
    class Program
    {
        static void Main(string[] args)
        {
            #region 1 控制台初始化
            int w = 50;
            int h = 30;
            ConsoleInit(w, h);

            #endregion

            #region 2 场景选择相关
            E_SceneType nowSceneType = E_SceneType.Begin;
            while (true)
            {
                switch (nowSceneType)
                {
                    case E_SceneType.Begin:
                        Console.Clear();
                        BeginOrEndScene(w, h, ref nowSceneType);
                        break;
                    case E_SceneType.Game:
                        Console.Clear();
                        GameScene(w, h, ref nowSceneType);
                        break;
                    case E_SceneType.End:
                        Console.Clear();
                        BeginOrEndScene(w, h, ref nowSceneType);
                        break;
                    default:
                        break;
                }
            }
            #endregion
        }
        #region 1 控制台初始化
        static void ConsoleInit(int w, int h)
        {
            Console.CursorVisible = false;
            Console.SetWindowSize(w, h);
            Console.SetBufferSize(w, h);
        }
        #endregion

        #region 3 开始场景逻辑 + 8 结束场景逻辑
        static void BeginOrEndScene(int w, int h, ref E_SceneType nowSceneType)
        {
            Console.ForegroundColor = ConsoleColor.Blue;
            Console.SetCursorPosition(nowSceneType == E_SceneType.Begin ? w / 2 - 9 : w / 2 - 4, 8);
            Console.Write(nowSceneType == E_SceneType.Begin ? "软件黑马王子飞行棋" : "游戏结束");
            int nowSelIndex = 0;
            bool isQuitBegin = false;
            while (true)
            {
                Console.SetCursorPosition(nowSceneType == E_SceneType.Begin ? w / 2 - 4 : w / 2 - 5, 13);
                Console.ForegroundColor = nowSelIndex == 0 ? ConsoleColor.Red : ConsoleColor.White;
                Console.Write(nowSceneType == E_SceneType.Begin ? "开始游戏" : "回到主菜单");

                Console.SetCursorPosition(w / 2 - 4, 15);
                Console.ForegroundColor = nowSelIndex == 1 ? ConsoleColor.Red : ConsoleColor.White;
                Console.Write("退出游戏");

                switch (Console.ReadKey(true).Key)
                {
                    case ConsoleKey.W:
                        --nowSelIndex;
                        if (nowSelIndex < 0)
                        {
                            nowSelIndex = 0;
                        }
                        break;
                    case ConsoleKey.S:
                        ++nowSelIndex;
                        if (nowSelIndex > 1)
                        {
                            nowSelIndex = 1;
                        }
                        break;
                    case ConsoleKey.J:
                        if (nowSelIndex == 0)
                        {
                            nowSceneType = nowSceneType == E_SceneType.Begin ? E_SceneType.Game : E_SceneType.Begin;
                            isQuitBegin = true;
                        }
                        else
                        {
                            Environment.Exit(0);
                        }
                        break;
                }
                if (isQuitBegin)
                {
                    break;
                }
            }
        }
        #endregion

        #region 游戏场景逻辑
        static void GameScene(int w, int h, ref E_SceneType nowSceneType)
        {
            DrawWall(w, h);
            Map map = new Map(14, 3, 80);
            map.Draw();
            Player player = new Player(0, E_PlayerType.Player);
            Player computer = new Player(0, E_PlayerType.Computer);
            DrawPlayer(player, computer, map);

            bool isGameOver = false;
            while (true)
            {
                if (PlayerRandoMove(w, h, ref player, ref computer, map, ref nowSceneType))
                {
                    break;
                }
                if (PlayerRandoMove(w, h, ref computer, ref player, map, ref nowSceneType))
                {
                    break;
                }
            }
        }

        static bool PlayerRandoMove(int w, int h, ref Player p, ref Player otherP, Map map, ref E_SceneType nowSceneType)
        {
            Console.ReadKey(true);
            bool isGameOver = RandomMove(w, h, ref p, ref otherP, map);
            map.Draw();
            DrawPlayer(p, otherP, map);
            if (isGameOver)
            {
                Console.ReadKey(true);
                nowSceneType = E_SceneType.End;
            }
            return isGameOver;
        }

        #endregion

        #region 4 绘制不变内容(红墙 提示等等)
        static void DrawWall(int w, int h)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            for (int i = 0; i < w; i += 2)
            {
                Console.SetCursorPosition(i, 0);
                Console.Write("■");
                Console.SetCursorPosition(i, h - 1);
                Console.Write("■");

                Console.SetCursorPosition(i, h - 6);
                Console.Write("■");
                Console.SetCursorPosition(i, h - 11);
                Console.Write("■");
            }
            for (int i = 0; i < h; i++)
            {
                Console.SetCursorPosition(0, i);
                Console.Write("■");
                Console.SetCursorPosition(w - 2, i);
                Console.Write("■");
            }

            Console.ForegroundColor = ConsoleColor.White;
            Console.SetCursorPosition(2, h - 10);
            Console.Write("□:普通格子");

            Console.ForegroundColor = ConsoleColor.Blue;
            Console.SetCursorPosition(2, h - 9);
            Console.Write("‖:暂停,一回合不懂");

            Console.ForegroundColor = ConsoleColor.Red;
            Console.SetCursorPosition(26, h - 9);
            Console.Write("●:炸弹,倒退5格");

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.SetCursorPosition(2, h - 8);
            Console.Write("¤:时空隧道,随机倒退,暂停,换位置");

            Console.ForegroundColor = ConsoleColor.Cyan;
            Console.SetCursorPosition(2, h - 7);
            Console.Write("★:玩家");

            Console.ForegroundColor = ConsoleColor.Magenta;
            Console.SetCursorPosition(12, h - 7);
            Console.Write("▲:电脑");

            Console.ForegroundColor = ConsoleColor.DarkGreen;
            Console.SetCursorPosition(22, h - 7);
            Console.Write("◎:玩家和电脑重合");

            Console.ForegroundColor = ConsoleColor.White;
            Console.SetCursorPosition(2, h - 5);
            Console.Write("按任意键开始扔色子");
        }
        #endregion

        #region 7 绘制玩家
        static void DrawPlayer(Player player, Player computer, Map map)
        {
            if (player.nowIndex == computer.nowIndex)
            {
                Grid grid = map.grids[player.nowIndex];
                Console.SetCursorPosition(grid.pos.x, grid.pos.y);
                Console.ForegroundColor = ConsoleColor.DarkGreen;
                Console.Write("◎");
            }
            else
            {
                player.Draw(map);
                computer.Draw(map);
            }
        }
        #endregion

        #region 8 扔色子 函数
        static void ClearInfo(int h)
        {
            Console.SetCursorPosition(2, h - 5);
            Console.Write("                                   ");
            Console.SetCursorPosition(2, h - 4);
            Console.Write("                                   ");
            Console.SetCursorPosition(2, h - 3);
            Console.Write("                                   ");
            Console.SetCursorPosition(2, h - 2);
            Console.Write("                                   ");
        }

        static bool RandomMove(int w, int h, ref Player p, ref Player otherP, Map map)
        {
            ClearInfo(h);
            Console.ForegroundColor = p.type == E_PlayerType.Player ? ConsoleColor.Cyan : ConsoleColor.Magenta;

            if (p.isPause)
            {
                Console.SetCursorPosition(2, h - 5);
                Console.Write("处于暂停状态,{0}需要暂停一回合", p.type == E_PlayerType.Player ? "你" : "电脑");
                Console.SetCursorPosition(2, h - 4);
                Console.Write("请按任意键,让{0}开始扔色子", p.type == E_PlayerType.Player ? "电脑" : "你");
                p.isPause = false;
                return false;
            }

            Random r = new Random();
            int randomNum = r.Next(1, 7);
            p.nowIndex += randomNum;

            Console.SetCursorPosition(2, h - 5);
            Console.Write("{0}扔出的点数为:{1}", p.type == E_PlayerType.Player ? "你" : "电脑", randomNum);

            if (p.nowIndex >= map.grids.Length - 1)
            {
                p.nowIndex = map.grids.Length - 1;
                Console.SetCursorPosition(2, h - 4);
                if (p.type == E_PlayerType.Player)
                {
                    Console.Write("恭喜你,你率先到达了终点");
                }
                else
                {
                    Console.Write("很遗憾,电脑率到达了终点");
                }
                Console.SetCursorPosition(2, h - 3);
                Console.Write("请按任意键结束游戏");
                return true;
            }
            else
            {
                Grid grid = map.grids[p.nowIndex];

                switch (grid.type)
                {
                    case E_Grid_Type.Normal:
                        Console.SetCursorPosition(2, h - 4);
                        Console.Write("{0}到了一个安全位置", p.type == E_PlayerType.Player ? "你" : "电脑");
                        Console.SetCursorPosition(2, h - 3);
                        Console.Write("请按任意键,让{0}开始扔色子", p.type == E_PlayerType.Player ? "电脑" : "你");
                        break;
                    case E_Grid_Type.Boom:
                        p.nowIndex -= 5;
                        if (p.nowIndex < 0)
                        {
                            p.nowIndex = 0;
                        }
                        Console.SetCursorPosition(2, h - 4);
                        Console.Write("{0}踩到了炸弹,退后5格", p.type == E_PlayerType.Player ? "你" : "电脑");
                        Console.SetCursorPosition(2, h - 3);
                        Console.Write("请按任意键,让{0}开始扔色子", p.type == E_PlayerType.Player ? "电脑" : "你");
                        break;
                    case E_Grid_Type.Pause:
                        p.isPause = true;
                        Console.SetCursorPosition(2, h - 4);
                        Console.Write("{0}到达了暂停点,你需要暂停一回合", p.type == E_PlayerType.Player ? "你" : "电脑");
                        Console.SetCursorPosition(2, h - 3);
                        Console.Write("请按任意键,让{0}开始扔色子", p.type == E_PlayerType.Player ? "电脑" : "你");
                        break;
                    case E_Grid_Type.Tunnel:

                        Console.SetCursorPosition(2, h - 4);
                        Console.Write("{0}踩到了时空隧道", p.type == E_PlayerType.Player ? "你" : "电脑");

                        randomNum = r.Next(1, 91);
                        if (randomNum <= 30)
                        {
                            p.nowIndex -= 5;
                            if (p.nowIndex < 0)
                            {
                                p.nowIndex = 0;
                            }
                            Console.SetCursorPosition(2, h - 3);
                            Console.Write("触发倒退5格");
                        }
                        else if (randomNum <= 60)
                        {
                            p.isPause = true;
                            Console.SetCursorPosition(2, h - 3);
                            Console.Write("触发暂停一回合");
                        }
                        else
                        {
                            int temp = p.nowIndex;
                            p.nowIndex = otherP.nowIndex;
                            otherP.nowIndex = temp;
                            Console.SetCursorPosition(2, h - 3);
                            Console.Write("惊喜,惊喜,双方交换位置");
                        }

                        Console.SetCursorPosition(2, h - 2);
                        Console.Write("请按任意键,让{0}开始扔色子", p.type == E_PlayerType.Player ? "电脑" : "你");
                        break;
                }
            }

            return false;
        }
        #endregion
    }
    #region 2 场景选择相关
    enum E_SceneType
    {
        Begin,
        Game,
        End,
    }
    #endregion

    #region 5 格子结构体和格子枚举
    enum E_Grid_Type
    {
        Normal,
        Boom,
        Pause,
        Tunnel,
    }

    struct Vector2
    {
        public int x;
        public int y;

        public Vector2(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }

    struct Grid
    {
        public E_Grid_Type type;
        public Vector2 pos;

        public Grid(int x, int y, E_Grid_Type type)
        {
            pos.x = x;
            pos.y = y;
            this.type = type;
        }

        public void Draw()
        {
            Console.SetCursorPosition(pos.x, pos.y);
            switch (type)
            {
                case E_Grid_Type.Normal:
                    Console.ForegroundColor = ConsoleColor.White;
                    Console.Write("□");
                    break;
                case E_Grid_Type.Boom:
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.Write("●");
                    break;
                case E_Grid_Type.Pause:
                    Console.ForegroundColor = ConsoleColor.Blue;
                    Console.Write("‖");
                    break;
                case E_Grid_Type.Tunnel:
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.Write("¤");
                    break;
            }
        }
    }
    #endregion

    #region 6 地图结构体
    struct Map
    {
        public Grid[] grids;

        public Map(int x, int y, int num)
        {
            grids = new Grid[num];

            int indexX = 0;
            int indexY = 0;
            int stepNum = 2;

            Random r = new Random();
            int randomNum;
            for (int i = 0; i < num; i++)
            {
                randomNum = r.Next(0, 101);

                if (randomNum < 85 || i == 0 || i == num - 1)
                {
                    grids[i].type = E_Grid_Type.Normal;
                }
                else if (randomNum >= 85 && randomNum < 90)
                {
                    grids[i].type = E_Grid_Type.Boom;
                }
                else if (randomNum >= 90 && randomNum < 95)
                {
                    grids[i].type = E_Grid_Type.Pause;
                }
                else
                {
                    grids[i].type = E_Grid_Type.Tunnel;
                }

                grids[i].pos = new Vector2(x, y);

                if (indexX == 10)
                {
                    y += 1;
                    ++indexY;
                    if (indexY == 2)
                    {
                        indexX = 0;
                        indexY = 0;
                        stepNum = -stepNum;
                    }
                }
                else
                {
                    x += stepNum;
                    ++indexX;
                }

            }
        }

        public void Draw()
        {
            for (int i = 0; i < grids.Length; i++)
            {
                grids[i].Draw();
            }
        }
    }
    #endregion

    #region 7 玩家枚举和玩家结构体
    enum E_PlayerType
    {
        Player,
        Computer,
    }

    struct Player
    {
        public E_PlayerType type;
        public int nowIndex;
        public bool isPause;

        public Player(int index, E_PlayerType type)
        {
            nowIndex = index;
            this.type = type;
            isPause = false;
        }

        public void Draw(Map mapInfo)
        {
            Grid grid = mapInfo.grids[nowIndex];
            Console.SetCursorPosition(grid.pos.x, grid.pos.y);
            switch (type)
            {
                case E_PlayerType.Player:
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.Write("★");
                    break;
                case E_PlayerType.Computer:
                    Console.ForegroundColor = ConsoleColor.Magenta;
                    Console.Write("▲");
                    break;
            }
        }
    }
    #endregion
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值