C++ 中五子棋游戏的计算机播放器 [关闭]

Posted

技术标签:

【中文标题】C++ 中五子棋游戏的计算机播放器 [关闭]【英文标题】:Computer Player for a Gomoku Game in C++ [closed] 【发布时间】:2020-11-24 19:06:58 【问题描述】:

前段时间我用 C++ 制作了一个类似于Gomoku 的游戏,需要两个玩家参与。

现在我想让它成为 Player vs Computer。 我尝试以最简单的方式做到这一点,通过使计算机功能来选择一个随机单元格,但我仍然没有成功。 我知道为了得到一个随机数,我可以使用 rand() 和这样的字母:

char letters[] = "abcdefghijklmnopqrstuvwxyz";
char x = letters[rand() % 26];

谁能帮我描述一下如何实现电脑播放器? 这是我目前的实现:

#include <iostream>
#include <iomanip>
using namespace std;

void print_table(int x[][15]) 
    system("cls");
    for (int i = 0; i < 15; i++) //the loop that use to print out the english character row
        if (i == 0)
            cout << setw(4) << "A";
        else if (i == 1)
            cout << " B";
        else if (i == 2)
            cout << " C";
        else if (i == 3)
            cout << " D";
        else if (i == 4)
            cout << " E";
        else if (i == 5)
            cout << " F";
        else if (i == 6)
            cout << " G";
        else if (i == 7)
            cout << " H";
        else if (i == 8)
            cout << " I";
        else if (i == 9)
            cout << " J";
        else if (i == 10)
            cout << " K";
        else if (i == 11)
            cout << " L";
        else if (i == 12)
            cout << " M";
        else if (i == 13)
            cout << " N";
        else if (i == 14)
            cout << " O";
        else if (i == 15)
            cout << " P";
    
    cout << endl;
    for (int i = 0; i < 15; i++) 
        cout << setw(2) << i;//print out the row number
        for (int j = 0; j < 15; j++) //print out the board game.
            if (x[i][j] == 0) //the inital value is 0, so when the block is 0 then print out the '.'
                cout << " .";
            
            else if (x[i][j] == 1) //when the player O input the block then the value will adding one then if check the block is one then output the 'o'
                cout << " O";
            
            else if (x[i][j] == 2) //when the player X input the block then the value will adding two then if check the block is two then output the 'x'
                cout << " X";
            
        
        cout << endl;
    

int check_player(int p) 
    if (p == 1) //change the player everytime before the next loop compile
        p++;
    
    else 
        p--;
    
    return p;

void input_value(int &t, int &n, int p, int x[][15]) 
    char eng;
    int number;
    do //the loop that ask for the user input the location.
        cout << "player ";
        if (p == 1) 
            cout << "O";
        
        else 
            cout << "X";
        
        cout << ", make a move: ";
        cin >> eng;//input the location
        cin >> number;
        if (eng == 'A')//change the character to different number
            t = 0;
        else if (eng == 'B')
            t = 1;
        else if (eng == 'C')
            t = 2;
        else if (eng == 'D')
            t = 3;
        else if (eng == 'E')
            t = 4;
        else if (eng == 'F')
            t = 5;
        else if (eng == 'G')
            t = 6;
        else if (eng == 'H')
            t = 7;
        else if (eng == 'I')
            t = 8;
        else if (eng == 'J')
            t = 9;
        else if (eng == 'K')
            t = 10;
        else if (eng == 'L')
            t = 11;
        else if (eng == 'M')
            t = 12;
        else if (eng == 'N')
            t = 13;
        else if (eng == 'O')
            t = 14;
        if (!(eng >= 'A'&&eng <= 'M') || !(number >= 0 && number <= 14) || x[number][t] != 0) //when the input wrong, output the statement to ask anouther input and loop again.
            cout << "Invaid input, Try again!" << endl;
            continue;
        
        else //if no problem then this input loop is break and jump to the next statement
            break;
        
     while (1);//Because it will break as well so the do-while loop is no any requirement
    n = number;

int main() 
    const int num = 15;//the number for constant the array row and column value
    char check_e;//for the user input the column
    int R[num][num] =  0 , check_n, player = 1, buger = 0, transfer, playerO_win = 0, playerX_win = 0, draw = 0, check_draw;//the variable that for user input or checking the game statment
    do //launch the loop for the user input again and again
        check_draw = 0;//reset the checking of draw
        print_table(R);
        input_value(transfer, check_n, player, R);
        R[check_n][transfer] += player;//change the value according the player's input and the player name.
        for (int i = 0; i < num; i++) 
            for (int j = 0; j < num; j++) 
                if (i <= 8 && R[j][i] != 0 && (R[j][i] == R[j][i + 1] && R[j][i] == R[j][i + +2] && R[j][i] == R[j][i + 3] && R[j][i] == R[j][i + 4])) //the checking for the row bingo
                    if (R[j][i] == 1) 
                        playerO_win++;
                        break;
                    
                    else 
                        playerX_win++;
                        break;
                    
                
                else if (j <= 8 && R[j][i] != 0 && (R[j][i] == R[j + 1][i] && R[j][i] == R[j + 2][i] && R[j][i] == R[j + 3][i] && R[j][i] == R[j + 4][i])) //the checking for the column bingo
                    if (R[j][i] == 1) 
                        playerO_win++;
                        break;
                    
                    else 
                        playerX_win++;
                        break;
                    
                
                else if (j <= 8 && i <= 8 && R[j][i] != 0 && (R[j][i] == R[j + 1][i + 1] && R[j][i] == R[j + 2][i + 2] && R[j][i] == R[j + 3][i + 3] && R[j][i] == R[j + 4][i + 4])) //the checking for the \ situation.
                    if (R[j][i] == 1) 
                        playerO_win++;
                        break;
                    
                    else 
                        playerX_win++;
                        break;
                    
                
                else if ((j >= 4 || i >= 4 || i <= 8) && R[j][i] != 0 && (R[j][i] == R[j - 1][i + 1] && R[j][i] == R[j - 2][i + 2] && R[j][i] == R[j - 3][i + 3] && R[j][i] == R[j - 4][i + 4])) //the checking for the / situation
                    if (R[j][i] == 1) 
                        playerO_win++;
                        break;
                    
                    else 
                        playerX_win++;
                        break;
                    
                
                for (int i = 0; i < num; i++) //the loop for checking the draw
                    for (int j = 0; j < num; j++) //this loop will check for every time compilation.
                        if (R[j][i] == 0)//when there are any empty block then the check_draw will adding, the draw situation is the check_draw be 0
                            check_draw++;
                    
                
                if (check_draw == 0) //when the check_draw equal to 0 which mean the situation is no empty block
                    draw++;
                    break;
                

            
            if (playerO_win != 0 || playerX_win != 0 || draw == 1)//break the second loop
                break;
        
        if (playerO_win == 1 && playerX_win == 0) // when the player win print the block game again and print out the win statement
            print_table(R);
            cout << "player O wins!" << endl;
            break;
        
        else if (playerX_win == 1 && playerO_win == 0) //the other player win the game
            print_table(R);
            cout << "player X wins!" << endl;
            break;
        
        else if (draw == 1) //the draw block game print
            print_table(R);
            cout << "Draw game!" << endl;
            break;
        
        player = check_player(player);

     while (1);//in fact it is no need for the loop statement, because most of the situation will have a break statement for out of the loop
    return 0;

【问题讨论】:

【参考方案1】:

以下是我可能会根据您的初始实现来实现它的方式:

#include <iostream>
#include <iomanip>
#include <cstdlib>

using namespace std;

#define SIZE 10
#define LINE_LENGTH 4
#define COMPUTER_O_PLAYER true
#define COMPUTER_X_PLAYER false

void print_board(unsigned char x[SIZE][SIZE]) 
    cout << "   ";
    for (int i = 0; i < SIZE; i++)  // The loop that use to print out the english character row.
        cout << (char) ('A' + i) << " ";
    
    cout << endl;
    for (int i = 0; i < SIZE; i++) 
        cout << setw(2) << i; // Print out the row number.
        for (int j = 0; j < SIZE; j++) //print out the board game.
            if (x[i][j] == 0)  // Unoccupied tile.
                cout << " .";
             else if (x[i][j] == 1)  // The tile belongs to X.
                cout << " X";
             else  // The tile belongs to O.
                cout << " O";
            
        
        cout << endl;
    


void get_position(int &x, int &y, bool player, unsigned char board[SIZE][SIZE]) 
    char eng;

    // The loop that ask for the user input the location.
    do 
        cout << "Player " << (player ? "X" : "O") << ", make a move: ";
        cin >> eng;
        y = toupper(eng) - 'A';
        cin >> x;
        if (!(x >= 0 && x < SIZE) || !(y >= 0 && y < SIZE) || board[x][y] != 0) 
            // When the input wrong, output the statement to ask another input and loop again.
            cout << "Invalid input, Try again!" << endl;
            continue;
         else  // If no problem then this input loop is break and jump to the next statement.
            break;
        
     while (true);


void get_random_position(int &x, int &y, bool player, unsigned char board[SIZE][SIZE]) 
    do 
        x = rand() % SIZE;
        y = rand() % SIZE;
     while ((!(x >= 0 && x < SIZE) || !(y >= 0 && y < SIZE) || board[x][y] != 0));
    cout << "Player " << (player ? "X" : "O") << " chose: " << (char) ('A' + y) << x << endl;


unsigned int
count_in_direction(unsigned char board[SIZE][SIZE], unsigned int x, unsigned int y, short int m_x, short int m_y) 
    unsigned int count = 0;
    unsigned char tile = board[x][y];

    while (((x + m_x >= 0) && (x + m_x < SIZE)) && ((y + m_y >= 0) && (y + m_y < SIZE)) &&
           (board[x + m_x][y + m_y] == tile)) 
        x += m_x;
        y += m_y;
        count++;
    

    return count;


bool full_line(unsigned char board[SIZE][SIZE], unsigned int x, unsigned int y) 
    const short int directions[4][2] = 1, 0,
                                        1, -1,
                                        0, 1,
                                        1, 1;
    for (const auto &direction : directions) 
        if (LINE_LENGTH - 1 <= (count_in_direction(board, x, y, direction[0], direction[1]) +
                                count_in_direction(board, x, y, -direction[0], -direction[1])))
            return true;
    

    return false;


int main() 
    // The variable that for user input or checking the game state.
    unsigned char board[SIZE][SIZE] = 0;
    int x, y;
    bool player = true;
    bool draw;

    srand(time(nullptr));

    // Run the game.
    do 
        print_board(board);
        if ((player && COMPUTER_X_PLAYER) || (!player && COMPUTER_O_PLAYER)) 
            get_random_position(x, y, player, board);
         else 
            get_position(x, y, player, board);
        
        board[x][y] = player ? 1 : 2;
        if (full_line(board, x, y)) 
            print_board(board);
            cout << "player " << (player ? "X" : "O") << " wins!" << endl;
            break;
        

        draw = true;
        for (int k = 0; (k < SIZE) && draw; k++) 
            for (int l = 0; (l < SIZE) && draw; l++) 
                if (board[k][l] == 0) draw = false;
            
        

        if (draw) 
            print_board(board);
            cout << "Draw game!" << endl;
            break;
        
        player = !player;

     while (true);

    return 0;

请深入了解此实现并内化其方法,它还支持作为用户、用户和计算机的玩家,以及两者的计算机。

一些见解:

如果有更简单的方法,请不要使用长 if ... else。 为变量使用正确的数据类型。 使用指示性变量命名。 尽可能使用循环,同样,不要太长if ... else。 保持代码格式正确。 使用#define 定义要使用的全局常量,以便以后更轻松地进行更改并提高可读性。 确实可以使用rand,但是不需要获取字符,直接获取索引就可以避免转换。

【讨论】:

感谢 mate 让它变得更干净,但现在它没有读取一个玩家的输入:) 是的,我仍在尝试了解如何使其成为玩家与计算机))

以上是关于C++ 中五子棋游戏的计算机播放器 [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何在c ++中播放声音[关闭]

Python游戏开发,pygame模块,Python实现五子棋联机对战小游戏

播放音频的库? - C++ [关闭]

将播放给所有班级的游戏应用程序的背景音乐[关闭]

C++实现五子棋小游戏

用C++基础语句写一个五子棋游戏