首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单的“连接4”游戏

简单的“连接4”游戏
EN

Code Review用户
提问于 2019-07-04 09:58:24
回答 1查看 1.5K关注 0票数 0

我做了这个简单的游戏,以提高我的C++。

NoFlickerShowCursor这样的功能是从互联网上复制出来的,但是我自己制作了AlignString,我为此感到骄傲。

函数changeP()交换播放器。在创建此函数和编辑代码之前,我使用了player1pickplayer2pick;现在更清楚了。函数Result(char p)winCheck(pChar)获取ppChar是active player的符号,winCheck()检查其中一种方式是否有4个块,然后返回p作为结果。

main中的第一件事也是从互联网上重标控制台。Setup()在新游戏开始前就把一切都安排好了。Pick()向active player请求列。draw()绘制字段和标记行是关于着色,但它比我想象的更复杂。

代码语言:javascript
复制
#include <iostream>
#include <string>
#include <Windows.h>
#include <conio.h>

using namespace std;


bool gameOver, p1t, p2t;
char p1[25], p2[25], player[25];// , winner[25];
const unsigned short int X = 9, Y=7;
char field[7][8];//7 - lower border, 8 - 2 side borders
int temp[7] = {6,6,6,6,6,6,6};//to know on what lvl next block will be placed
int cPick, pColor;//column pick
char pChar;//player char for later change by players desire


void NoFlicker(short int x, short int y) {  //No flickering fix (Internet)
    COORD pos = { x, y };
    HANDLE output = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleCursorPosition(output, pos);
}//End of NoFlicker
void ShowCursor(bool showFlag) {                //Show the cursor while drawing (Internet)
    HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);

    CONSOLE_CURSOR_INFO     cursorInfo;

    GetConsoleCursorInfo(out, &cursorInfo);
    cursorInfo.bVisible = showFlag; // set the cursor visibility
    SetConsoleCursorInfo(out, &cursorInfo);
}//End of ShowCursor
void AlignString(string text, int y) {      //Aligns strings to the Middle (by me)
    int size;
    size = 60 - (text.length() / 2);
    for (int ent = 0; ent <= y; ent++) {
        cout << "\n";
    }
    for (int gap = 0; gap < size; gap++) {
        cout << " ";
    }
    cout << text;
}//End of AlignString

void draw() {


    NoFlicker(0, 40);
    cout << "\t\t\t\t\t\t\t 1234567 \n";
    for (int i = 0; i < Y; i++) {
        cout << "\t\t\t\t\t\t\t";
        for (int j = 0; j < X; j++) {
            if (i == Y-1 || j == 0 || j == X-1) {
                //SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 9);
                field[i][j] = 219;
                //cout << field[i][j];
            }else if (cPick == j) {
                //SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), pColor);
                field[temp[cPick - 1]][j] = pChar;
                //cout << field[i][j];
            } /*else {
                if (field[i][j] == 1){
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 14);
                    cout << field[i][j];
                } else if(field[i][j] == 2) {
                    SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 4);
                    cout << field[i][j];
                } else {
                    field[i][j] = ' ';
                    cout << field[i][j];
                }*/

            cout << field[i][j];
        }cout << endl;
    }

    /*cout << endl;
    for (int i = 0; i < 7; i++) {
        cout <<temp[i];
    }cout << endl;*/
}

void changeP() {//changes players
    if (p1t) {
        pChar = 1; //current player's symbol
        pColor = 14;
        strcpy_s(player, p1);//googled this function
        p1t = false; //player's 1 turn
        p2t = true;//player's 2 turn
    }
    else if (p2t) {
        pChar = 2;
        pColor = 4;
        strcpy_s(player, p2);
        p1t = true;
        p2t = false;
    }
}

void result(char p) {
    if (p == 1) {
        gameOver = true;
        AlignString(p1, 1);
        AlignString("Won the game! It was fair match", 1);
        AlignString("New game will start in less than 10 seconds!", 10);
    }
    else if (p == 2) {
        gameOver = true;
        AlignString(p2, 1);
        AlignString("Won the game! It was fair match!", 1);
        //strcpy_s(winner, p1);
        AlignString("New game will start in less than 10 seconds!",10);
    }

}

char winCheck(char p) {
    for (int i = 0; i < 7; i++) {
        for (int j = 0; j < 9; j++) {
            if (field[i][j] == p && field[i+1][j + 1] == p && field[i+2][j + 2] == p && field[i+3][j + 3] == p) {//Diagonal Right Down Check
                return p;
            }
            if (field[i][j] == p && field[i][j + 1] == p && field[i][j + 2] == p && field[i][j + 3] == p) {//Horizontal Check
                return p;
            }
            if (field[i][j] == p && field[i-1][j + 1] == p && field[i-2][j + 2] == p && field[i-3][j + 3] == p) {//Diagonal Right Up Check
                return p;
            }
            if (field[i][j] == p && field[i - 1][j] == p && field[i - 2][j] == p && field[i - 3][j] == p) {//Vertical Check
                return p;
            }
        }
    }
}

void pick() {
    AlignString(player, 1);
    AlignString("you can pick your column --> ",1);
    cin >> cPick;
    if (cPick > 7 || cPick < 1) {
        AlignString("nIllegal pick. Try again!", 1);
        pick();
    } else {
        temp[cPick - 1] -= 1;
        if (temp[cPick - 1] < 0) {
            AlignString("This column is full. Try another one!",1);
            pick();
        }
        system("cls");
    }
}

void setup() {
    ShowCursor(false);
    gameOver = false;
    p1t = true;
    p2t = false;
    AlignString("Player 1, write your name or how you wanna be called here --> ",5);
    //cout << "\n\t\t\t\";
    cin.getline(p1, 25);
    AlignString("Ok now, Player 2, write your name or how you wanna be called here --> ",1);
    cin.getline(p2, 25);

    system("cls");
    draw();
}

void main() {

    HWND console = GetConsoleWindow();
    RECT r;
    GetWindowRect(console, &r); //stores the console's current dimensions
    MoveWindow(console, r.left, r.top, 900, 900, TRUE); // 800 width, 100 height

    setup();
    while (!gameOver) {
        changeP();
        pick();
        draw();
        result(winCheck(pChar));
    }
    Sleep(10000);
    main();

}
EN

回答 1

Code Review用户

发布于 2019-07-04 14:27:15

main()的用法

在C++ main()中,只能由操作系统调用从不受程序本身的影响,它是从操作系统进入程序的入口点。对…的定义main()是整数,这样它就可以将程序的状态返回给任何调用它的程序。

由于在此程序中使用main()的递归性质,可能会发生堆栈溢出,并可能在运行此程序的计算机上造成安全风险。堆栈溢出也可能会对其他不希望的侧产生影响。

正如@TobySpeight在main()程序中调用c++程序所指出的那样,编辑会导致未定义的行为。这意味着它几乎可以做任何事情,任何事情都是不可预料的,而且很可能是一件坏事。例如,程序中的数据可能被破坏。当我开始编程时,它可能会引起内核恐慌,从而关闭计算机。在main()中有一个非常好的循环来执行游戏,运行另一个游戏--把游戏循环和睡眠语句放到一个外部循环中。

这是一个main()的例子,没有调用它自己,它编译,我不知道它是否工作:

代码语言:javascript
复制
int main() {

    HWND console = GetConsoleWindow();
    RECT r;
    GetWindowRect(console, &r); //stores the console's current dimensions
    MoveWindow(console, r.left, r.top, 900, 900, TRUE); // 800 width, 100 height
    string playAgain("no");

    do {
        setup();
        while (!gameOver) {
            changeP();
            pick();
            draw();
            result(winCheck(pChar));
        }
        std::cout << "Enter yes to play again";
        std::getline(std::cin, playAgain);
    } while (playAgain.compare("yes") == 0);

}

使用命名空间std

使用此语句可能会导致函数名和变量之间的冲突,最好使用std::cinstd::coutstd::string,而不是在代码中使用该语句。将此语句保存在头文件中可能会导致更多的混乱。当您编写更复杂的面向对象的程序时,您可能会发现自己为对象定义了cincout,以便它们可以被输入或输出。

全局变量

全局变量的使用使得编写和调试代码更加困难。程序中的任何地方都可以修改全局变量,而对变量的更改可能很难跟踪。

幻数

代码中的数值常量有时被称为幻数幻数,因为它不清楚它们是什么或它们的意思。

代码中使用了许多数字常量,如0、1、2、4、14、40和219。这使得代码更难阅读和理解。不清楚pColor = 4pColor = 14在做什么,也不清楚这条声明在做什么field[i][j] = 219;

您可以使用const int PLAYER_ONE = 1;const int FIELD_HEIGHT = 7; const int FIELD_WIDTH = 8;来定义符号常量,而不是数字。这将使代码更容易阅读,如果您需要更改字段的大小,只需要在一个位置而不是多个位置进行编辑。它还将使您更容易理解任何通过field矩阵移动的for循环。

字符串与C样式字符串

代码已经包含了C++ string类,如果p1、p2和player被定义为字符串而不是C风格的字符数组,可能会更好。内置的std::cinstd::cout已经知道如何处理string类。

使用结构或类

可能有一个表示玩家的结构或类。它可以有字段int id;string name;int color;。这将减少每个玩家的变量数。

代码语言:javascript
复制
    std::cin >> p1.name;

    std::cin >> p2.name;

或者,结构或类可以包含获取用户名的函数。

票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/223493

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档