C语言 多人赌马大赛 小游戏

C语言实现多人赌马大赛游戏

编译环境:vs2019

需求:
多人通过对键盘的输入执行下注、押马等操作累加资金,统计信息。

思路:
首先写出马运动的效果,再根据游戏人数,执行下注、押马功能,统计一系列信息。

做法:
先是让四匹马不停地同时跑动的效果。马的跑动通过内层循环控制让每匹马都走一步,外层无限循环控制让每匹马一直跑即可实现。定义dis数组,内层循环四次(马数)的次数,每次循环这匹马的奔跑距离累加一次一个随机数,dis数组存储这匹马总奔跑的距离,再在每匹马的前面输出每匹马跑的距离的字符,因为内层循环是几乎瞬间执行完毕的,就可以实现看上去四匹马同时跑动的效果。
然后是每匹马的名次判断的问题,在马奔跑的同时判断是否有马奔跑的距离大于了赛道的距离,如果有,让这匹马停在终点处,并通过给一个变量自增来一次确定每匹马的名次。
还有玩家选择下注资金、选择赛马编号的操作。

此外程序里还有很多细节,这里不一一赘述。

难点:
四匹马不停跑动,并判断出先到终点的马。
玩家选择下注资金、选择赛马编号的操作,这些功能实现起来非常简单,但是想要没有bug又非常的麻烦。与我做的一些其他的小游戏相比,不同的是,赌马大赛的原理虽然是最简单的,但统计信息几种信息也较为复杂,也称得上是一个难点。

说明:
首先说明我程序上的问题:
原本给我思路、教会我写多匹马跑动效果的示范代码是单人简易版本的,但是后来我玩游戏时在守望先锋的自定义房间中看到了类似赌马大赛的游戏模式,该模式有着很多人一起玩,并且很好玩,并没有给我一种我想象中的小游戏特有的单调枯燥的感觉。所以我有了将C语言版本的赌马大赛改成可选多人模式的版本的想法。这个想法使原本程序中大部分单个变量就可以表示的数据,必须使用玩家的个数的长度的数组来表示,于是我就用各种循环配合数组写成了多人版本的赌马大赛,并排除了大部分显示上的bug。但是由于改造的大部分代码全是我自己想出来的,受能力限制,该程序肯定有着很多不妥善和不健全的地方。
还有字符游戏界面上的问题:
原本主要用printf、scanf和一个跑马界面就可以完成的程序,我使用了大量的gotoxy(光标定位)、空格清除、清屏写出了一个 半同一界面 程序,这样写有着界面清晰,较为美观的优点。而之所以我没有写成完全同一界面的程序是因为有着以下几点考虑:

  1. 跑马时需要清屏,清屏后再绘制整张游戏界面需要执行的循环太多
  2. 在跑马时还显示着输入赛马编号和下注的信息不符合逻辑且游戏执行步骤不清晰
  3. 多人游戏每轮赌马结束后的结算信息太复杂,没有空间放得开 这样就导致了整个程序没有一个较为统一的界面标准,且代码较为复杂。

注意:
由于这个程序的代码一开始是我在其他编译器写的,文件中所有的scanf最后都没有加 “_s” ,所以要在vs2019中编译运行需要在vs解决方案资源管理器 - 源文件 - 右键属性 - 配置属性 - 常规 - 双击SDL检查。将其关闭即可。

运行效果:
赌马大赛运行效果

代码实现:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>

#define HOUSENUM 4                  //马的数量
#define LG 62                       //跑道的长度

void init();                //初始化游戏人数
void process();             //游戏流程
void scyxjmhye();           //输出游戏界面和玩家余额
void xzhxzhm();             //下注和选择号码
void inmary();              //每轮奖励结算和游戏结束条件
int housenumber(void);      //选择号码
void houserun(int* rank, int* num, int* xes, int n);//马跑动动画函数
void gotoxy(int x, int y);  //光标定位

int n;                      //几人进行游戏,全局变量

int* money = (int*)malloc(sizeof(int) * n);     //余额数组,全局
int* xes = (int*)malloc(sizeof(int) * n);       //下注数组
int* num = (int*)malloc(sizeof(int) * n);       //选择号码数组
int rank[HOUSENUM];                             //每一匹马的名次


int main()
{
    init();                         //游戏初始化函数,选择几人进行游戏

    for (int i = 1; i <= n; i  )    //将余额数组初始化,每个人开局一百块钱
        money[i] = 100;

    process();                      //游戏流程

    return 0;
}

void init()                         //游戏初始化函数
{
    system("title 多人赌马大赛");   //更改控制台标题
    gotoxy(10, 42);
    printf("=====请选择您想进行几人游戏=====\n");

    gotoxy(12, 57);
    scanf("%d", &n);                //选择几人游戏

    if (n > 8)                      //选择人数过多,无实际意义容易造成程序卡死,故判断后重新选择
    {
        gotoxy(10, 40);
        printf("=====选择人数过多请重新选择 n<8=====\n");
        gotoxy(12, 57);
        printf("      ");
        gotoxy(12, 57);
        scanf("%d", &n);
    }

    system("cls");                  //选择完几人游戏后清屏

    gotoxy(12, 48);
    printf("您已选择- 人游戏", n);

    system("cls");
    gotoxy(13, 54);
    printf("开始");
    Sleep(800);

    system("cls");
}

void scyxjmhye()                //输出游戏界面和玩家余额
{
    {                           //因为这里只是输出一个形式,使用局部代码块  输出下注和选择号码时的赌马场地
        gotoxy(2, 0);
        printf("========欢迎来到黄金赌马场========\n\n");
        printf("马匹已准备就位");
        gotoxy(7, 0);
        printf(" 1号马 q\n 2号马 w\n 3号马 e\n 4号马 r\n");
    }

    gotoxy(21, 1);              
    int mca = 0;                //输出选择区边界
    while (mca < 29)
    {
        printf("——");
        mca  ;
    }

    gotoxy(23, 3);
    for (int i = 1, d = 0; i <= n; i  )                 //选择区左区输出玩家余额
    {
        if (n > 3) d = 1;
        printf("玩家 %d 余额:%d 元   ", i, money[i]);

        if (d == 0)
            printf("\n\n   ");
        else
        {
            if (i % 3 == 0)
                printf("\n\n   ");
        }
    }
}

int housenumber()                                       //选择赛马号码
{
    int num = 0;                                        //if判断后通过大量空格清除输入错误的值
    gotoxy(26, 78);
    printf("                             ");
    gotoxy(26, 78);
    printf("请选择赛马编号:(1-%d)", HOUSENUM);

    while (1)       
    {
        gotoxy(27, 78);
        printf("                             ");
        gotoxy(27, 78);
        scanf("%d", &num);

        gotoxy(26, 78);
        if (num < 1 || num > HOUSENUM)
        {
            printf("                               ");
            gotoxy(26, 78);
            printf("错误请重新选择编号:(1-%d)", HOUSENUM);
        }
        else
        {
            gotoxy(26, 78);
            printf("                            ");
            gotoxy(27, 78);
            printf("                            ");
            gotoxy(24, 78);
            printf("                                ");
            break;
        }
    }
    return num;
}

void xzhxzhm()                      //下注和选择号码
{
    for (int i = 1; i <= n; i  )                            //因为有多名玩家,用到的每名玩家的循环
    {
        gotoxy(23, 78);
        printf("d号玩家 请下注(最低10元):\n\n", i);   //每名玩家下注
        gotoxy(24, 78);
        scanf("%d", &xes[i]);

        while (1)                                           //循环判断每名玩家下注后判断下注金额是否正确
        {
            if (xes[i] > money[i])                          //使用空格清除输入错误和重复的提示信息
            {
                gotoxy(23, 78);
                printf("                            ");
                gotoxy(23, 78);

                printf("%d号 资金不足,请重新下注", i);

                gotoxy(24, 78);
                printf("                            ");
                gotoxy(24, 78);
                scanf("%d", &xes[i]);
            }
            else if (xes[i] < 10)
            {
                gotoxy(23, 78);
                printf("                            ");
                gotoxy(23, 78);

                printf("%d号 最低下注10元,请重新下注", i);

                gotoxy(24, 78);
                printf("                            ");
                gotoxy(24, 78);
                scanf("%d", &xes[i]);
            }
            else
                break;
        }

        money[i] -= xes[i];       //余额

        num[i] = housenumber();             //选择号码
    }
}


void houserun(int* rank, int* num, int* xes, int n)     //跑马函数
{
    int i, j, w = 1;
    int index = 1;        //名次
    int dis[HOUSENUM] = { 0 };   //每一匹马走过的距离
    char ch[HOUSENUM] = { 'q','w','e','r' };

    while (index <= HOUSENUM)
    {
        system("cls");
        printf("\n========欢迎来到黄金赌马场========\n\n");

        for (int i = 1; i <= n; i  )
            printf("\n%d号玩家 已选择 %d 号马\t您已下注资金:%d元 \n\n", i, num[i], xes[i]);
        printf("\n");

        for (i = 0; i < HOUSENUM;   i)
        {
            dis[i]  = rand() % 5;           //每匹赛马已经跑出的距离=每匹已跑出的距离 一个随机数 **

            if (dis[i] >= LG)               //如果每匹马已经走的距离超过了跑道的距离,则每匹马走的距离等于跑道的距离
            {
                dis[i] = LG;
                if (rank[i] == 0)           //如果每匹马跑到了终点,且这匹马没有重复到达终点则每匹马的名次等于1自增
                    rank[i] = index  ;
            }

            printf(" %d号马 ", i   1);      //标明每匹马的序号

            for (j = 0; j < dis[i];   j)    //每一匹马走过的距离,输出一个字符 **
                printf("_");



            if (rank[i])                    //如果每匹马到终点了,把输出的代表马的字符改为这匹马的名次
                printf("%d\n", rank[i]);
            else
                printf("%c\n", ch[i]);
        }
        Sleep(200);
    }
    printf("\n");
}

void inmary()                               //每轮奖励结算和游戏结束条件
{
    for (int i = 1; i <= n; i  )
    {
        if (rank[num[i] - 1] == 1)
        {
            printf("\n%d号 你获得了第一名!!五倍奖金!!\n", i);
            money[i]  = (xes[i] * 5);
        }
        else if (rank[num[i] - 1] == 2)
        {
            printf("\n%d号 你获得了第二名!三倍奖金!\n", i);
            money[i]  = (xes[i] * 3);
        }
        else
        {
            printf("\n%d号 您只获得了第%d名,资金扣除\n", i, rank[num[i] - 1]);
            money[i]  = 0;
        }
        printf("\n");

        //游戏结束条件
        if (money[i] < 10)     //有玩家的资金少于10
        {
            for (int i = 1; i <= n; i  )
                printf("\n%d号 您的余额为:%d\n", i, money[i]);

            printf("\n有玩家的资金不足10元,游戏结束\n\n");

            printf("----统计----\n");

            int* z111 = (int*)malloc(sizeof(int) * n);  //排名数组记录每一位玩家游戏与余额的顺序

            for (int i = 1; i <= n; i  )
            {
                printf("%d号玩家:余额:%d\n\n", i, money[i]);
            }

            int maxk = 1;                           //最大值
            for (int i = 1; i <= n; i  )
            {
                if (money[maxk] < money[i])
                    maxk = i;
            }

            printf("\n\n%d号玩家获胜!!!\n\n", maxk);


            exit(0);
        }
    }

    for (int i = 0; i < HOUSENUM; i  )      //每匹马的名次归0
        rank[i] = 0;

    for (int i = 1; i <= n; i  )
        printf("\n%d号 您的余额为:%d\n\n", i, money[i]);

    printf("\n---请按任意键开始下一轮下注---\n\n\n");
    system("pause");
    system("cls");
}

void process()              //游戏流程
{
    while (1)                       
    {
        scyxjmhye();                //输出游戏界面和玩家余额
        
        xzhxzhm();                  //下注和选择号码

        houserun(rank, num, xes, n);//跑马主函数

        inmary();                   //每轮奖励结算和游戏结束条件
    }
}


void gotoxy(int x, int y)
{
    COORD pos = { y,x };
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
}

不足之处:
游戏字符界面没有一个统一的标准,较为凌乱,代码较为繁琐。
多人版本赛马的想法和实现都是我自己想出来的,由于能力限制,肯定有很多用法规范、代码复用性、运行效率上的问题。


作为一名c语言新手,我对未知的知识始终抱有学习和谦卑的态度。
在这里我对所有愿意支持我、对我提出建议和批评的人表示最真挚的感谢!

发布了6 篇原创文章 · 获赞 5 · 访问量 2409

猜你喜欢

转载自blog.csdn.net/qq_46239972/article/details/104128875