【C++/C】2048小游戏实验报告及心得

这篇具有很好参考价值的文章主要介绍了【C++/C】2048小游戏实验报告及心得。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

****大学

《程序设计课程设计》

报告

1 课程设计需求

编写一个 2048 游戏,且使用图形界面。

游戏规则为:

① 游戏开始时,初始化一个 16 方格的棋盘,并在棋盘内随机出现两个数字,出现的数字只能是 2 或 4。

② 玩家可以选择上下左右四个方向,若棋盘内的数字出现位移或合并,视为有效移动。

③ 玩家选择的方向上若有相同的数字则合并,每次有效移动可以同时合并,但不可以连续合并。

④ 合并所得的所有新生成数字相加即为此次移动的有效得分。

⑤ 玩家选择的方向行或列前方有空格则出现位移。

⑥ 每有效移动一步,棋盘的空位随机出现一个数字(依然为 2 或 4)。

⑦ 棋盘被数字填满,无法进行有效移动,判负,游戏结束。

⑧ 棋盘上出现 2048,判胜,游戏结束。

2设计

(1)总体思路

根据上述需求,先利用随机数调整2和4的出现概率,再在棋盘中随机2个空位填补数字2或4,即初始化棋盘。

采用文件流相关操作记录历史最高分,若玩家从未玩过,则默认最高分为0。游戏过程中需要进行当前分数(Score)和历史最高分(Best)大小比较,以便随时更新历史最高分。

再利用循环结构实现玩家操作(重新开始,退出游戏,移动),移动操作需要实现上移、下移、左移、右移。

重新开始(设定为N或n):需要再次初始化棋盘。

退出游戏(设定为Z或z):结束程序运行进程。

移动操作(设定以W,S,A,D或者键盘自带方向键作为移动方向键):对移动操作是否有效进行判断,有效则累加此次移动的分数,并判断是否出现2048,出现则游戏胜利,否则在棋盘空位随机出现一个数字(依然为 2 或 4);在分数累加后与历史最高分数比较,判断是否更新历史最高分;当棋盘被填满且无法合并数字,即移动操作无效时,游戏结束。

游戏胜利:界面上方出现Win字样。

游戏失败:界面上方出现Lose字样。

(2)具体流程图如下:

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

(3)界面设计

采用easyx绘制图形界面:界面下方是4×4大小的棋盘,并对棋盘填充色彩,且不同数字对应不同色彩;上方是数据显示界面,显示当前分数和历史最高分,以及重新开始和退出游戏的操作提示。

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

表格1不同数字对应颜色

枚举的color数组对应下标

对应的数字

对应的RGB

t0

0

RGB(205, 193,180)

t1

2

RGB(238, 228,218)

t2

4

RGB(237, 224,200)

t3

8

RGB(242, 177,121)

t4

16

RGB(245, 149, 99)

t5

32

RGB(246, 124, 95)

t6

64

RGB(246, 94, 59)

t7

128

RGB(242, 177,121)

t8

256

RGB(237, 204, 97)

t9

512

RGB(255, 0, 128)

t10

1024

RGB(145, 0, 72)

t11

2048

RGB(242, 17, 158)

(4)构思

表格2常量汇总

常量

Row

Col

Width

Gap

数值

4

4

105 px

15 px

描述

棋盘行数

棋盘列数

单独一个正方形格子的边长

格子间的距离

表格3全局变量

全局变量

score

Best

table[Row][Col]

gameOver

类型

int

int

二维数组

bool

初始值

0

0

{ }

false

描述

当前总分

历史最佳分数

棋盘

判断游戏是否继续

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

3 项目实现与运行结果

调试结果和分析:

(1)首次运行,进入游戏:

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

可以看到在棋盘中随机2处出现数字2(因为设定出现2的概率大于4),历史最高分(Best)也是默认为0,因还未移动,所以当前得分(Score)也为0.

(2)移动数次后:

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

移动过程中分数一直变化,因为移动后Score>Best始终成立,所以Best随时跟随Score变化。

(3)游戏失败时,得分为660分(注:最后一次滑动是向右滑动):

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

因为此次滑动是向右边滑动,所以虽然上下方向可以合并2个16,但因为右滑,无法进行数字合并,而且棋盘已满,故游戏判负,显示Lose字样。

(4)再重新开始游戏:

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

重开后,棋盘也照样在随机2处出现数字。且历史最高分(Best)变为之前的660分,而当前得分(Score)为0.

(5)再次移动数次:

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

移动过程中,因为Score暂时未超过Best,所以Best不变,而Score变化。

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

当Score超过Best后,Best会随着Score一同增加。

(6)在中途时,选择重新开始:

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

在上一步得到880分后,重新开始(键入N或者n)后,棋盘随机2处出现数字,Best是之前的最高分880,Score为0.

(7)移动数次后再退出游戏:

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

进行数次移动操作后,Score为252分,然后退出游戏(键入Z或z),游戏关闭,并调出控制台(因为调试程序时,选择不关闭控制台;若想退出游戏后,直接退出所有程序,则需要在initgraph(500, 630)函数中传入第3个参数1,因为默认第三个参数为0,表示退出游戏后调出控制台)。

c语言2048游戏课程总结,课设,c++,c语言,游戏程序,Powered by 金山文档

(8)游戏胜利时:

由于技术水平有限,暂时无法提供通关截屏。

至此,已基本将所有调试做完。

4 课程设计过程问题分析

(1)怎样利用easyx绘制图形化界面?

通过网上查询资料,主要在网站EasyX文档(https://docs.easyx.cn/zh-cn/reference),再浏览主要的绘制函数,包括填充背景色彩、设置字体颜色,大小、显示字符串等,一步步学以致用,并通过结合网站提供的实例,逐渐掌握使用的方法。

(2)完成数据的收集,以及构思整个程序如何书写。

主要是需要搜集每个数字对应颜色,可以直接上网收集每个数字所对应的颜色,但我选择使用色彩吸取相关工具,在实践中逐步掌握色彩吸取工具的用法,并越发熟练。然后是构思程序设计,在多次阅读完题设需求后,最好在画图工具上一步步梳理题干;理清程序的进行步骤,明白程序的进程;该用何种方式才能完成题目要求;在使用这种方法时,是否需要一个变量来跟进程序运行进程,以便对实现某些操作:比如此次课设,要随时检验移动的有效性以及游戏是否结束,所以我采用创建一个变量来控制,如果移动无效,该变量改变后,就可满足游戏结束的条件。

最终理清程序该如何进行后,得出具体的流程图,对书写程序有很大帮助。

(3)如何具体实现移动操作?

在实现移动操作的过程中,因为各种原因,导致程序异常、运行失败、崩溃等问题。主要在于如何实现合并数字的操作,而且不能在一次移动中连续合并数字。因为上移,下移,左移,右移都是一个原理,所以先挑选右移入手,其他的移动便不攻自破。

当数字下移时,需要考虑如下场景:相邻位置数字相同时的合并操作,如[2,2,4,4]à[0,4,0,8]这种情况;数字无法合并时,如[0,2,0,8]à[0,0,2,8]这种情况。

所以选择下面这种解法:

void moveRight()

{

for (int i = Row - 1; i >= 0;i--)

{

int t = Row - 1;

for (int next = Col - 2; next >= 0;next--)

{

if (table[i][next] !=0)

{

if (table[i][t] == 0)

{

table[i][t]= table[i][next];

table[i][next]= 0;

}

else if (table[i][next] ==table[i][t])

{

table[i][t]*= 2;

score+= table[i][t];

table[i][next]= 0;

t--;

}

else

{

table[i][t- 1] = table[i][next];

if (t - 1 != next)

{

table[i][next]= 0;

}

t--;

}

}

}

}

}

通过前后两个变量是否为0,是否相等,考虑各种情况下的右移合并操作。

5 总结与心得体会

通过本次课程设计,对C++语言的应用以及实操有了更多的了解,提高了自身的逻辑思维能力;在查找资料的过程中,逐渐学会如何自学,自学能力进一步加强;在此基础上,还学会了如何运用esayx工具绘制简易游戏界面,以及熟练掌握了色彩吸取相关工具的快捷使用方法;能通过些许代码实现需求,程序每次运行成功总能带来不少喜悦,加强了继续下去,不断攻克难题的信心。

具体代码:文章来源地址https://www.toymoban.com/news/detail-520741.html

#define _CRT_SECURE_NO_WARNINGS 1  // VS高版本编译器需要
#include<iostream>
#include<stdio.h>
#include<string>
#include<math.h>
#include<ctime>
#include <stdlib.h>
#include<easyx.h> // 图形化界面采用easyx
#include <conio.h>
#include<fstream>
using namespace std;

#define Row 4        // 行数
#define Col 4        // 列数
#define Width 105    // 格子边长
#define Gap 15       // 格子间距

enum color           // 枚举相应颜色
{
    t0 = RGB(205, 193, 180), // 0
    t1 = RGB(238, 228, 218), // 2
    t2 = RGB(237, 224, 200), // 4
    t3 = RGB(242, 177, 121), // 8
    t4 = RGB(245, 149, 99),  // 16
    t5 = RGB(246, 124, 95),  // 32
    t6 = RGB(246, 94, 59),   // 64
    t7 = RGB(242, 177, 121), // 128
    t8 = RGB(237, 204, 97),  // 256
    t9 = RGB(255, 0, 128),   // 512
    t10 = RGB(145, 0, 72),   // 1024
    t11 = RGB(242, 17, 158)  // 2048
};
color colors[] = { t0,t1,t2,t3,t4,t5,t6,t7,t8,t9,t10,t11 }; // 对应数字的背景颜色
int table[Row][Col] = {};
int score = 0; // 当前总分
int Best = 0;  // 历史最佳分数

void over();            // 判断是否出现2048获胜
bool gameOver = false;  // 判断游戏是否继续
void startagain();      // 是否重新开始
bool find0();           // 确认有无空位
int random();          // 出现随机数字2或4
void init(int n);       // 数字出现的个数

void display();         // 展示
void record();          // 记录最高分
void update();          // 更新最高分

void move();            // 移动
void moveUp();
void moveDown();
void moveLeft();
void moveRight();

int main()
{
    initgraph(500, 630); // 窗口分辨率 
    init(2); // 初始化棋盘
    update();
    do {
        while (!gameOver)
        {
            display();
            move();
            over();
            update();
        }
        if (gameOver)
        {
            startagain();
        }
    } while (!gameOver);
    closegraph();
    return 0;
}

int random()
{
    srand((unsigned int)time(NULL));
    if (rand() % 10 > 6)  // 调整2和4出现概率
    {
        return 4;
    }
    else
    {
        return 2;
    }
}
bool find0() // 确认有无空位增加
{
    for (int j = 0; j < Row; j++)
    {
        for (int t = 0; t < Col; t++)
        {
            if (table[j][t] == 0)
            {
                return true;
            }
        }
    }
    settextcolor(RGB(252, 85, 49));
    settextstyle(100, 0, _T("微软雅黑"));
    outtextxy(Width * 2 - Gap * 3, Gap * 4, _T("Lose"));
    gameOver = true;
    return false;
}
void init(int n) // 数字出现的个数
{
    srand((unsigned int)time(NULL));
    int init_row = 0;
    int init_col = 0;
    if (find0() == true)
    {
        for (int i = 0; i < n; )
        {
            init_row = rand() % Row;
            init_col = rand() % Col;
            if (table[init_row][init_col] == 0)
            {
                table[init_row][init_col] = random();
                i++;
            }
        }
    }
}

void over()  // 判断是否2048获胜
{
    for (int i = 0; i < Row; i++)
    {
        for (int j = 0; j < Col; j++)
        {
            if (table[i][j] == 2048)
            {
                settextcolor(RGB(252, 85, 49));
                settextstyle(100, 0, _T("微软雅黑"));
                outtextxy(Width * 2 - Gap * 3, Gap * 4, _T("Win"));
                gameOver = true;
            }
        }
    }
}
void startagain() // 是否重新开始
{
    char key = _getch();
    switch (key)
    {
        case 'N':
        case 'n':
        {
            for (int i = 0; i < Row; i++)
            {
                for (int j = 0; j < Col; j++)
                {
                    table[i][j] = 0;
                }
            }
            init(2); // 初始化
            score = 0;
            graphdefaults(); // 设置默认字体
            display();
            gameOver = false;
            break;
        }
        default:
        {
            break;
        }
    }
}

void display() // 展示
{
    setbkcolor(RGB(187, 173, 160)); // 设置背景颜色
    cleardevice();
    for (int i = 0; i < Row; i++)
    {
        for (int j = 0; j < Col; j++)
        {    
            // 计算每个格子左上角坐标
            int x = Gap + (Width + Gap) * j;    // 横坐标
            int y = 130 + Gap + (Width + Gap) * i;    // 纵坐标
            int index = table[i][j] ? log2(table[i][j]) : 0; // 取color数组下标
            setfillcolor(colors[index]); // 填充格子颜色
            solidroundrect(x, y, x + Width, y + Width, 10, 10); // 绘制格子
            if (table[i][j])
            {
                TCHAR s[5];
                _stprintf(s, _T("%d"), table[i][j]);
                LOGFONT f;
                gettextstyle(&f);
                f.lfHeight = 60;  
                f.lfWeight = 600;
                _tcscpy(f.lfFaceName, _T("Microsoft Yahei"));
                f.lfQuality = ANTIALIASED_QUALITY;          
                settextstyle(&f);
                setbkmode(TRANSPARENT);
                int widthspace = (Width - textwidth(s)) / 2;   // 格子内左右间隔,以实现数字居中
                int heightspace = (Width - textheight(s)) / 2; // 格子内上下间隔
                outtextxy(x + widthspace, y + heightspace, s);
            }
        }
    }
    settextstyle(20, 0, _T("微软雅黑"));
    outtextxy(Width * 3 + Width / 2, Width - Gap, _T("重新开始:N"));
    outtextxy(Width * 3 + Width / 2, Width, _T("退出游戏:Z"));

    TCHAR s1[5], s2[5];
    _stprintf(s1, _T("%d"), score); // 展示分数
    _stprintf(s2, _T("%d"), Best);
    settextstyle(37, 0, _T("微软雅黑"));
    setbkmode(TRANSPARENT);

    outtextxy(Gap, Gap * 3, s1);
    outtextxy(Gap, 0, _T("Score"));

    outtextxy(Gap+Width*3, Gap * 3, s2);
    outtextxy(Gap + Width * 3, 0, _T("Best"));
}

void moveUp()
{
    for (int i = 0; i < Col; i++)
    {
        int t = 0;
        for (int next = 1; next < Row; next++)
        {
            if (table[next][i] != 0)
            {
                if (table[t][i] == 0)
                {
                    table[t][i] = table[next][i];
                    table[next][i] = 0;
                }
                else if (table[next][i] == table[t][i])
                {
                    table[t][i] *= 2;
                    score += table[t][i];
                    table[next][i] = 0;
                    t++;
                }
                else
                {
                    table[t + 1][i] = table[next][i];
                    if (t + 1 != next)
                    {
                        table[next][i] = 0;
                    }
                    t++;
                }
            }
        }
    }
}
void moveDown()
{
    for (int i = Col - 1; i >= 0; i--)
    {
        int t = Col - 1;
        for (int next = Row - 2; next >= 0; next--)
        {
            if (table[next][i] != 0)
            {
                if (table[t][i] == 0)
                {
                    table[t][i] = table[next][i];
                    table[next][i] = 0;
                }
                else if (table[next][i] == table[t][i])
                {
                    table[t][i] *= 2;
                    score += table[t][i];
                    table[next][i] = 0;
                    t--;
                }
                else
                {
                    table[t - 1][i] = table[next][i];
                    if (t - 1 != next)
                    {
                        table[next][i] = 0;
                    }
                    t--;
                }
            }
        }
    }
}
void moveLeft()
{
    for (int i = 0; i < Row; i++)
    {
        int t = 0;
        for (int next = 1; next < Col; next++)
        {
            if (table[i][next] != 0)
            {
                if (table[i][t] == 0)
                {
                    table[i][t] = table[i][next];
                    table[i][next] = 0;
                }
                else if (table[i][next] == table[i][t])
                {
                    table[i][t] *= 2;
                    score += table[i][t];
                    table[i][next] = 0;
                    t++;
                }
                else
                {
                    table[i][t + 1] = table[i][next];
                    if (t + 1 != next)
                    {
                        table[i][next] = 0;
                    }
                    t++;
                }
            }
        }
    }
}
void moveRight()
{
    for (int i = Row - 1; i >= 0; i--)
    {
        int t = Row - 1;
        for (int next = Col - 2; next >= 0; next--)
        {
            if (table[i][next] != 0)
            {
                if (table[i][t] == 0)
                {
                    table[i][t] = table[i][next];
                    table[i][next] = 0;
                }
                else if (table[i][next] == table[i][t])
                {
                    table[i][t] *= 2;
                    score += table[i][t];
                    table[i][next] = 0;
                    t--;
                }
                else
                {
                    table[i][t - 1] = table[i][next];
                    if (t - 1 != next)
                    {
                        table[i][next] = 0;
                    }
                    t--;
                }
            }
        }
    }
}

void move()
{
    char key = _getch();
    switch (key)
    {
        case 'N':
        case 'n':
        {
            for (int i = 0; i < Row; i++)
            {
                for (int j = 0; j < Col; j++)
                {
                    table[i][j] = 0;
                }
            }
            init(2); // 初始化
            score = 0;
            break;
        }
        case 'Z':
        case 'z':
        {
            gameOver = true;
            return;
        }
        case 'w':
        case 'W':
        case 72:
        {
            moveUp();
            init(1);
            break;
        }
        case 's':
        case 'S':
        case 80:
        {
            moveDown();
            init(1);
            break;
        }
        case 'a':
        case 'A':
        case 75:
        {
            moveLeft();
            init(1);
            break;
        }
        case 'd':
        case 'D':
        case 77:
        {
            moveRight();
            init(1);
            break;
        }
        default:
        {
            break;
        }
    }
}

void record() // 记录最高分
{
    ofstream ofs("BestScore.text", ios::trunc);
    Best = score;
    ofs << Best << endl;
    ofs.close();
}
void update() // 更新最高分
{
    ifstream ifs("BestScore.text", ios::in|ios::binary);
    if (!ifs.is_open()) // 判断文件是否存在
    {
        ofstream ofs("BestScore.text", ios::out);
        ofs << 0 << endl;
        ofs.close();
        Best = 0;
        return;
    }
    char bestchar[8];
    ifs.getline(bestchar, 8);
    string t = bestchar;
    Best = stoi(t);
    if (Best < score)
    {
        ifs.close();
        record();
    }
}

到了这里,关于【C++/C】2048小游戏实验报告及心得的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • python小游戏毕设 2048小游戏设计与实现 (源码)

    🔥 Hi,各位同学好呀,这里是L学长! 🥇今天向大家分享一个今年(2022)最新完成的毕业设计项目作品 python小游戏毕设 2048小游戏设计与实现 (源码) 🥇 学长根据实现的难度和等级对项目进行评分(最低0分,满分5分) 难度系数:3分 工作量:3分 创新点:4分 项目获取: https://

    2024年02月12日
    浏览(47)
  • 2048小游戏成品源码

    2048小游戏,可以自选背景颜色,方框颜色,音乐播放。 还可以展示当前玩家的排名,动态排名,及历史玩家的排名。 前期需求: 使用pygame加载目录音乐。MP3文件: 看下运行后的效果图: =========参数设置: =========背景设置: =========方块设置: ==========源码分享:

    2024年02月16日
    浏览(47)
  • Qt--2048小游戏

    2048 1.功能 上下左右控制数字格子的移动 WASD 4*4 格子移动操作,加操作 开始游戏的按钮,重新游戏按钮 得分计算 判断游戏是否结束 2.源程序 代码如下(示例): MainWindow.h Main.cpp MainWindow.cpp 5.结果 以上是今天要讲的内容,练习了2048小游戏。

    2024年01月25日
    浏览(50)
  • c++制作小游戏2048

    完整代码来自于爱编程的柚子《【C语言/C++游戏项目】:2048小游戏,超详细教程教会你写这个小游戏。》 这个游戏用到了#include graphics.h,思路比较简单。 首先做出游戏页面,然后画出4*4的格子,利用map二维数组,依据数字{0,2,4,8,16,32,64,128,256,512,1024,2048}找到对应颜色在固定位

    2024年02月13日
    浏览(47)
  • 基于C#的2048小游戏

    最近在玩过2048这个小游戏后感觉很有意思,想着正在学C#的winfrom的我能不能自己写一个2048游戏呢?于是就有了这个:   目录 1.实现思路; 2.代码实现; 1.初始化地图表示的数组; 2.绘制游戏的边框; 3.设置每个数值对应的颜色(可省略); 4.添加控件; 5.四个方向的移动;

    2024年02月08日
    浏览(46)
  • Android期末项目2048小游戏

    Android期末项目2048小游戏。 2048属于益智类小游戏,它做到了娱乐性、趣味性、教育性相统一。益智类的游戏即是需要去开动大脑去思考从而获得游戏的胜利。简单的益智类游戏可以使玩家在娱乐中不断的开发大脑。这样一来就实现了在娱乐中学习。每次可以选择上下左右其中

    2024年02月06日
    浏览(59)
  • python快速实现2048小游戏

    《2048》是一款比较流行的数字游戏,最早于2014年3月20日发行。原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台。这款游戏是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。 操作指南: 每次可以选择上下左右其中一个方向去滑动,每滑动

    2024年02月11日
    浏览(41)
  • 【Android Studio】图形化数字游戏,小游戏2048。

    手机中的小游戏是一种在日常生活中应用广泛的休闲软件,无论是在超市商店,还是在办公室,或是家庭都有着它的身影。随着移动互联网和智能手机的不断发展和进步,当今市场上已经出现了多种简单轻松的小游戏,几乎每一位智能手机的使用者都会在种类繁多的App网站上

    2024年02月03日
    浏览(46)
  • 2048小游戏 java版(代码+注释)

            一个纯纯小白,想写点什么,也想学习一下怎么在这里写东西,就简单的写个2048小游戏。写的不好,大佬就不用看了,希望和大家交流学习,有写的不好或有更好的建议也欢迎提出来。(需要用的可直接粘贴复制)(轻喷) 目录 游戏展示 讲解  代码        

    2024年02月09日
    浏览(52)
  • 用Python做一个2048小游戏

    2048的逻辑无非是操作 4 × 4 4times4 4 × 4 的方格,每个方格中有一个数,这些数可以移动,如果两个相同的数字在移动时相撞了,就可以彼此合并。 而这个 4 × 4 4times4 4 × 4 的方格,无非是一个矩阵。只需设计好移动逻辑,再用PyGame将这个方格表现出来就算大功告成。 2048只有

    2024年01月17日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包