数字华容道(C++)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

各位,今天我突发奇想变了一个数字华容道。


一、这玩意则么玩

在这个游戏里会有一个 4*4 的表格,每个网格中有一个1~15之间的数。
可以选择 w、s、a、d,上下左右的滑动,移动数。
"当按大小顺序从左到右、从上到下排列好所有的数,游戏结束!。

二、使用图例

游戏截图

三、源代码

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <termio.h>
#include <iomanip>
#define clear() cout << "\033c" << flush
using namespace std;

int num[10][10];
int rd, tme;
bool validMove;

int getch() // 不回显函数
{
    struct termios nts, ots;
    // 得到当前终端(0表示标准输入)的设置
    if (tcgetattr(0, &ots) < 0) return EOF;
    // 设置终端为Raw原始模式,该模式下所有的输入数据以字节为单位被处理
    nts = ots;
    cfmakeraw(&nts); 
    // 设置上更改之后的设置
    if (tcsetattr(0, TCSANOW, &nts) < 0) return EOF;
    // 设置还原成老的模式
    int cr;
    cr = getchar();
    if (tcsetattr(0, TCSANOW, &ots) < 0)  return EOF;
    return cr;
}

void intro() // 游戏规则展示
{
    cout << "***********************************************************" << endl;
    cout << "欢迎来到 数字华容道 游戏~" << endl;
    cout << "在这个游戏里会有一个 4*4 的表格,每个网格中有一个1~15之间的数" << endl;
    cout << "可以选择 w、s、a、d,上下左右的滑动,移动数" << endl;
    cout << "当按大小顺序从左到右、从上到下排列好所有的数,游戏结束!" << endl; 
    cout << "点击【ENTER】开始游戏" << endl;
    cout << "点击【ESC】退出游戏" << endl;
    cout << "***********************************************************" << endl;
}

void init() // 初始化网格
{
    int a[20] = {};
    for (int i = 1; i <= 15; i++)
    {
        a[i] = i;
    }
    srand(time(0));
    random_shuffle(a + 1, a + 15 + 1);
    int cnt = 0;
    for (int i = 1; i <= 15; i++)
    {
        for (int j = i+1; j <= 15; j++)
        {
            if (a[i] > a[j]) // 逆序数对个数
            {
                cnt++;
            }
        }
    }
    if (cnt % 2 == 1) // 逆序数对为奇数无解,减少一个
    {
        for (int i = 1; i <= 14; i++)
        {
            if (a[i] > a[i+1])
            {
                swap(a[i], a[i+1]);
                break;
            }
        }
    }
    for (int i = 1; i <= 4; i++)
    {
        for (int j = 1; j <= 4; j++)
        {
            num[i][j] = a[(i-1)*4+j];
        }
    }
}

void drawBoard() // 打印当前表格
{
    // 输出上边框
    cout << "  ╔";
    for (int i = 1; i <= 4 - 1; i++) cout << "════╤";
    cout << "════╗\n";
    // 输出中间部分
    for (int i = 1; i <= 4; i++) // 行
    {
        cout << "  ║";
        for (int j = 1; j <= 4; j++) // 列
        {
            if (num[i][j] >= 10)
                cout << " " << num[i][j] << " "; 
            else if (num[i][j] != 0)
                cout << "  " << num[i][j] << " ";
            else
                cout << "    ";
            if (j != 4)
                cout << "│";
            else
                cout << "║";
        }
        cout << " \n";
        // 输出下边框
        if (i != 4)
        {
            cout << "  ╟";
            for (int i = 1; i <= 4 - 1; i++) cout << "────┼";
            cout << "────╢\n";
        }
        else
        {
            cout << "  ╚";
            for (int i = 1; i <= 4 - 1; i++) cout << "════╧";
            cout << "════╝\n";
        }
    }
}

bool gameOver()
{
    int a[20];
    for (int i = 1; i <= 4; i++)
    {
        for (int j = 1; j <= 4; j++)
        {
            a[(i-1)*4+j] = num[i][j];
        }
    }
    for (int i = 1; i <= 15; i++)
    {
        if (a[i] != i)
        {
            return false;
        }
    }
    return true;
}

void MoveUp() // 向上移动
{   
    int x, y;
    for (int i = 1; i <= 4; i++)
    {
        for (int j = 1; j <= 4; j++)
        {
            if (num[i][j] == 0)
            {
                x = i;
                y = j;
            }
        }
    }
    if (x == 4) validMove = false;
    else
    {
        validMove = true;
        swap(num[x][y], num[x+1][y]);
    }
}

void MoveDown() // 向下移动
{   
    int x, y;
    for (int i = 1; i <= 4; i++)
    {
        for (int j = 1; j <= 4; j++)
        {
            if (num[i][j] == 0)
            {
                x = i;
                y = j;
            }
        }
    }
    if (x == 1) validMove = false;
    else
    {
        validMove = true;
        swap(num[x][y], num[x-1][y]);
    }
}

void MoveLeft() // 向左移动
{   
    int x, y;
    for (int i = 1; i <= 4; i++)
    {
        for (int j = 1; j <= 4; j++)
        {
            if (num[i][j] == 0)
            {
                x = i;
                y = j;
            }
        }
    }
    if (y == 4) validMove = false;
    else
    {
        validMove = true;
        swap(num[x][y], num[x][y+1]);
    }
}

void MoveRight() // 向右移动
{   
    int x, y;
    for (int i = 1; i <= 4; i++)
    {
        for (int j = 1; j <= 4; j++)
        {
            if (num[i][j] == 0)
            {
                x = i;
                y = j;
            }
        }
    }
    if (y == 1) validMove = false;
    else
    {
        validMove = true;
        swap(num[x][y], num[x][y-1]);
    }
}

void Win() // 玩家获胜
{
    cout << "**********************************" << endl;
    cout << "——————————— ROUND:" << rd << " ————————————" << endl;
    cout << "——————————— TIME:" << tme << " s———————————" << endl;
    cout << "——————————— 玩家获胜! ————————————" << endl;
    cout << "**********************************" << endl << endl;
    exit(0);
}

void game() // 开始游戏
{
    cout << "\033c" << flush;
    cout << "**********************************" << endl;
    cout << "—————————— Ready Go~ ————————————" << endl;
    cout << "**********************************" << endl;
    drawBoard(); // 打印棋盘
    
    char ch = 0;
    int sta = time(0);
    while (!gameOver()) // 当游戏没结束时
    {
        tme = time(0) - sta;
        // 按键 操作数 时间
        cout << "Key:" << ch << " Round:" << rd << " Time:" << tme << endl;
        cout << "Tips:" << endl;
        cout << "w —— 上移" << endl;
        cout << "s —— 下移" << endl;
        cout << "a —— 左移" << endl;
        cout << "d —— 右移" << endl;
        cout << "e —— 退出游戏" << endl;
        cout << "r —— 开始新游戏" << endl;
        cout << "选择以上指令!" << endl;
        
        ch = getch(); // 输入操作指令
        if (ch == 'w') MoveUp();
        else if (ch == 's') MoveDown();
        else if (ch == 'a') MoveLeft();
        else if (ch == 'd') MoveRight();
        else if (ch == 'e') exit(0);
        else if (ch == 'r') // 开始新游戏
        {
            sta = time(0); // 清空开始时间
            rd = 0; // 清空操作次数
            memset(num, 0, sizeof(num)); // 清空表格数据
            return; 
        }
        else
        {
            cout << endl << "———————输入有误,请重新输入指令!———————" << endl << endl;
            continue;
        }
        cout << "\033c" << flush;
        drawBoard(); // 打印棋盘
        if (validMove) rd++; // 记录操作次数
    }
    Win();
}

int main()
{
    while (true)
    {
        intro(); // 游戏规则展示
        char ch = getch(); // 不回显函数,当用户按下某个字符时,函数自动读取,无需按回车
        if (ch == 13) // CR回车的ascii是13
        {
            init(); //初始化方格数据
            game(); // 开始游戏
        }
        else if (ch == 27) // ESC的ascii是27
        {
            cout << "退出游戏!" << endl;
            break;
        }
        else  cout << "输入有误,请再次输入!" << endl;
    }
    return 0;
}

  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
数字华容道是一个经典的拼图游戏,也被称为“拼图游戏中的魔方”。在这个游戏中,有一个 $4\times 4$ 的方格,其中有 $15$ 个数字方块和一个空格,玩家需要通过移动数字方块,使得它们按照从 $1$ 到 $15$ 的顺序排列,空格则是用来移动数字方块的。 数字华容道的实现可以使用 C++ 的面向对象特性,将方格和方块抽象为对象,实现它们的移动和交换操作。以下是一个简单的实现示例。 ```c++ #include <iostream> using namespace std; // 数字方块类 class NumberBlock { private: int value; // 方块上的数字 int row; // 方块所在的行号 int col; // 方块所在的列号 public: NumberBlock(int value, int row, int col) { this->value = value; this->row = row; this->col = col; } // 获取方块上的数字 int getValue() { return value; } // 获取方块所在的行号 int getRow() { return row; } // 获取方块所在的列号 int getCol() { return col; } // 设置方块所在的行号和列号 void setPosition(int row, int col) { this->row = row; this->col = col; } }; // 数字华容道类 class DigitalHuRongDao { private: NumberBlock* blocks[4][4]; // 数字方块的二维数组 int emptyRow; // 空格所在的行号 int emptyCol; // 空格所在的列号 public: DigitalHuRongDao() { // 初始化数字方块 for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { int value = i * 4 + j + 1; if (value == 16) { blocks[i][j] = nullptr; emptyRow = i; emptyCol = j; } else { blocks[i][j] = new NumberBlock(value, i, j); } } } } // 输出数字华容道的当前状态 void print() { for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (blocks[i][j] == nullptr) { cout << " "; } else { cout << blocks[i][j]->getValue() << " "; } } cout << endl; } cout << endl; } // 移动数字方块 bool move(int row, int col) { if (row < 0 || row > 3 || col < 0 || col > 3) { return false; } if (blocks[row][col] != nullptr) { return false; } if (row == emptyRow && col == emptyCol) { return false; } NumberBlock* block = blocks[emptyRow][emptyCol]; blocks[emptyRow][emptyCol] = blocks[row][col]; blocks[row][col] = block; if (blocks[emptyRow][emptyCol] != nullptr) { blocks[emptyRow][emptyCol]->setPosition(emptyRow, emptyCol); } emptyRow = row; emptyCol = col; return true; } // 判断数字华容道是否已经完成 bool isCompleted() { int value = 0; for (int i = 0; i < 4; i++) { for (int j = 0; j < 4; j++) { if (blocks[i][j] != nullptr) { if (blocks[i][j]->getValue() != value + 1) { return false; } value++; } } } return true; } }; int main() { DigitalHuRongDao dh; dh.print(); while (!dh.isCompleted()) { int row, col; cout << "请输入要移动的数字方块的行号和列号(用空格分隔):"; cin >> row >> col; if (dh.move(row, col)) { dh.print(); } else { cout << "无效的移动,请重新输入!" << endl; } } cout << "恭喜你,完成了数字华容道!" << endl; return 0; } ``` 在这个示例代码中,`NumberBlock` 类表示数字方块,它有一个数字和一个位置(行号和列号)属性,并且可以获取和设置这些属性。`DigitalHuRongDao` 类表示数字华容道,它有一个 $4\times 4$ 的数字方块二维数组和一个空格位置属性,可以初始化数字方块、输出当前状态、移动数字方块和判断是否已经完成。在 `main` 函数中,首先创建一个数字华容道对象,然后进入一个循环,不断接受用户输入的移动指令,直到数字华容道被完成为止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HellowZheng

老铁,您的打赏是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值