编辑:填写一列而不覆盖C ++

我正在尝试构建一个2人游戏,程序要掷骰子,玩家必须从12列中选择要玩的列。

我的问题是骰子滚动时(例如:5),玩家1选择他们的专栏。 工作正常,直到播放器2选择同一列并覆盖播放器1在该列中的内容,而不是在其上方的可用空间中播放。

这是我的代码:

#include <iostream>
#include <windows.h>
#include <ctime>
#include <iomanip>
#include <algorithm>
#include "TheRebuild.h"

using namespace std;
int k = 0;
auto dice = 0;
int col_in = 0;
int col_space = 0;
int x = 0;
int y = 0;
int counter = 0;
char space = '-';

char board[gridrow][gridcol];

    //accessors
    string Players::getname(Users play[],int k) const {
        return play[k].name;
    }

    char Players::gettoken(Users play[],int k) const {
        return play[k].token;
    }

    int Players::getscore(Users play[],int k) const {
        return play[k].score;
    }

    //mutator
    void Players::RecInfo(Users play[],int k,string id,char piece,int scr) {
        play[k].name = id;
        play[k].token = piece;
        play[k].score = scr;

    }

    Players::Players() {
        for (int k = 0; k < arrsize; k++) {
            play[k].name = "";
            play[k].token = ' ';
            play[k].score = 0;
        }
    }


void Players::askUser(Players::Users *play)
{
    string id = " ";
    char piece = ' ';
    int scr = 0;

    //cin.get();
    for (int k = 0; k <= arrsize; k++) {

        cout << "Player " << k + 1 << "! Enter your Name: ";
        getline(cin,id);

        cout << "Player " << k + 1 << " Enter a character to play with: ";
        cin >> piece;

        cout << endl;

        system("pause");

        RecInfo(play,k,id,piece,scr);
        system("cls");
        cin.get();
    }
}

int Players::DiceRoll()
{
    int dice = 0;
    srand(time(nullptr));
    dice = (rand() % 6) + 1;
    return dice;
}

void Players::Player1() {
    dice = DiceRoll();
    cout << "Dice stopped rolling at: " << dice << endl;
    cout << play[0].name <<" Enter column to play in: ";
    cin >> col_in;

    if ((col_in < 1) && (col_in > 12)) // failsafe - player does not play anything out of 1-12 range
    {
        cin.get();
        cout << "Turn lost!";
        return;
    }
    else
    {
        col_space = col_in-1;
    }

    if (board[x][gridcol] != space)
    {
            x++;
            for (x = gridcol; x > gridcol - (dice +1); x--) // this loop allows player pieces to start at "11" of the board rather than at the "0"
            {
                board[x][col_space] = play[0].token;
                Sleep(50);
            }
    }
    else
    {
        for (x = gridcol; x > gridcol - (dice +1); x--) // this loop allows player pieces to start at "11" of the board rather than at the "0"
        {
            board[x][col_space] = play[0].token;
            Sleep(50);
        }
    }

}

void Players::Player2() {
    dice = DiceRoll();
    cout << "Dice stopped rolling at: " << dice << endl;
    cout << play[1].name <<" Enter column to play in: ";
    cin >> col_in;

    if ((col_in < 1) && (col_in > 12)) // failsafe - player does not play anything out of 1-12 range
    {
        cin.get();
        cout << "Turn lost!";
        return;
    }
    else
    {
        col_space = col_in - 1;
    }

    for (x = gridcol; x > gridcol-(dice +1); x--) // this loop allows player pieces to start at the bottom of the board rather than at the top
    {
        board[x][col_space] = play[1].token;
        Sleep(50);
    }
}

void Players::Header() {
    //---------------------------- Print --------------------------------
    // this prints the board with all the changes made by the player... this is OK
    string border(48,'-');
    system("cls");

    cout << border << endl
         << "|                 Fill 'Em Up                  | \n"
         << border << endl
         << "  1   2   3   4   5   6   7   8   9  10  11  12  \n"
         << border << endl; // header for the board
}

void Players::Sub_UI() {
    //Basic UI elements - Displays Player Name,Their Score (number of tokens on the board),and the token they chose
    // I plan to add colors for player 1 and player 2 tokens,but the gameplay is more important

    string sub(15,'^');
    cout << endl << sub << "\t\t\t " << sub << endl; // top boarder for player information
    cout << "Player: " << play[0].name << "\t\t\t" << " Player: " << play[1].name << endl; // names of players
}

bool Players::endgame() {
    return false;
}

void Players::mainStage(Players::Users *play) {

    for(x = 0; x <gridrow; x++){
        for (y = 0; y < gridcol; y++){
            board[x][y] = space;
        }
    }

    do // loop for the whole game - see "while" at the end
    {
        Header();

        for (x = 0; x < gridrow; x++)  // actual grid being printed x is row,y is col,just like a normal x and y axis
        {
            for (y = 0; y < gridcol; y++) {
                cout << "  " << board[x][y] << " ";
            }
            cout << endl;
        }

        //Token Counter
        int count1 = count(*board,*board+144,play[0].token); // used to count how many tokens on the board belong to Player 1
        int count2 = count(*board,play[1].token); // used to count how many tokens on the board belong to Player 2

        //Small UI elements
        Sub_UI();
        cout << "Score: " << count1 << " -> " << play[0].token << "\t\t\t" << " Score: " << count2 << " -> " << play[1].token << endl << endl; // scores and tokens respectively

        //Player1
        if (counter % 2 == 0)
        {
           Player1();
        }
        else //Player2
        {
            Player2();
        }counter++;


    }while(!endgame());
}


有人对此有任何想法吗?

完成后应该看起来像这样

------------------------------------------------
|                 Game Title                   |
------------------------------------------------
  1   2   3   4   5   6   7   8   9  10  11  12
------------------------------------------------
  -   -   -   -   -   -   -   -   -   -   -   -
  -   -   -   -   -   -   -   -   -   -   -   -
  -   -   -   -   -   -   -   -   -   -   -   -
  -   -   -   -   -   -   -   -   -   -   -   -
  -   -   -   -   -   -   -   -   -   -   -   -
  -   -   -   -   -   -   -   -   -   -   -   -
  -   -   -   -   -   -   -   -   -   -   -   -
  -   $   -   -   -   -   -   -   $   -   -   -
  -   $   -   -   -   -   -   -   $   -   -   -
  -   $   -   -   -   -   -   -   $   -   -   -
  -   $   -   -   -   -   -   -   @   -   -   @
  -   $   -   -   -   -   -   -   @   -   -   @

^^^^^^^^^^^^^^^                  ^^^^^^^^^^^^^^^
Player: Player1                  Player: Player2
Score: 4 -> @                    Score: 8 -> $

Dice stopped rolling at: 2
Player1 Enter column to play in:

请注意玩家2如何输入上方 3个令牌,而不是覆盖它们

zhxru 回答:编辑:填写一列而不覆盖C ++

首先,我发现代码中存在错误:

if ((col_in < 1) && (col_in > 12)) 

数字永远不能小于1 不能大于12。您需要在此处使用||


您将代码重构为较小的函数,这很好,但是您将所有这些函数都放在了一个巨型类中。我重新编写了更多类的代码。每个人都有自己的工作。这是我使用的类:

  • game_board管理董事会
  • die掷骰子的简单类(使用较新的随机函数)
  • player保留播放器数据。将有2个此类的物品-每个玩家1个物品
  • game处理所有游戏逻辑的主类

其他一些注意事项:

  • 创建了一个辅助函数,以从int中读取charcin。这样可以确保用户输入正确的类型,并且会消耗掉多余的字符-包括换行符
  • 我使用std::vector而不是数组

这是我的代码。请注意,这并不意味着它是最好的或唯一的方法。但是希望它将显示出将代码分解成较小的段的优势。

#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <random>
#include <limits>
#include <stdexcept>
#include <sstream>

using std::cout;
using std::endl;
using std::string;
using std::vector;

// Helper function to get user inputs. Keeps trying until the right type is entered
// Also clears any extra chars
template<typename T>
T get_input()
{
    T i{};
    while (!(std::cin >> i)) {
        std::cin.clear();
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
    }
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
    return i;
}

class column
{
protected:
    vector<char> data;

public:
    static const char SPACE_CHAR = '-';

    column(int rows) :
        data(rows,SPACE_CHAR)
    {}

    bool is_full() const
    {
        return data[0] != SPACE_CHAR;
    }

    void add(char token)
    {
        auto result = std::find_if(data.rbegin(),data.rend(),[this](char c) { return c == SPACE_CHAR; });
        if (data.rend() == result) {
            cout << "ERROR";
            return;
        }
        *result = token;
    }

    int free_spaces() const
    {
        auto result = std::find_if(data.begin(),data.end(),[this](char c) { return c != SPACE_CHAR; });
        return std::distance(data.begin(),result);
    }

    int count_tokens(char token) const
    {
        return std::count(data.begin(),token);
    }

    int num_rows() const { return data.size(); }

    // Needed for std::max_element
    bool operator<(const column& other) const { return data.size() < other.data.size(); }

    // Index operator. Does not throw on index out of bounds.
    char operator[](int i) const { return i < data.size() ? data[i] : ' '; }
};

class game_board
{
protected:
    vector<column> board;

public:
    game_board(int rows,int cols)
    {
        for (int c = 0; c < cols; c++) {
            board.push_back(column(rows));
        }
    }

    void print() const
    {
        ::system("CLS");
        for (int c = 1; c <= board.size(); c++) {
            cout << std::right << std::setw(3) << c << ' ';
        }
        cout << endl;

        static char c1 = 0;

        // The game currently supports columns with different sizes
        // For printing,need to know max number of rows
        int rows = (*std::max_element(board.begin(),board.end())).num_rows();

        for (int r = 0; r < rows; r++) {
            for (auto c : board) {
                cout << "  " << c[r] << ' ';
            }
            cout << endl;
        }
    }

    bool column_is_full(int col) const
    {
        return board[col].is_full();
    }

    // Adds a token to the vector in the column given
    void add_to_col(int col,char token)
    {
        board[col].add(token);
    }

    bool is_full()
    {
        auto result = std::find_if(board.begin(),board.end(),[this](column& c) { return !c.is_full(); });
        return result == board.end();
    }

    int free_spaces(int col) const
    {
        return board[col].free_spaces();
    }

    // Get a complete count of all tokens on the board
    int get_count(char token) const
    {
        int count = 0;
        for (auto c : board) {
            count += c.count_tokens(token);
        }
        return count;
    }

    int get_num_rows(int col) const { return board[col].num_rows(); }
    int get_num_cols() const { return board.size(); }
};

class die {
protected:
    std::random_device rd;
    std::mt19937 mt;
    std::uniform_real_distribution<double> dist;

public:
    die(int num_sides) :
        mt(rd()),dist(1,num_sides + 1)
    {
    }

    int roll() {
        return (int)dist(mt);
    }
};

class player
{
protected:
    string name;
    char token;

public:
    player(int id)
    {
        cout << "Player " << id << "! Enter your Name: ";
        std::getline(std::cin,name);
        cout << "Player " << id << " Enter a character to play with: ";
        token = get_input<char>();
    }

    string get_name() const { return name; }
    char get_token() const { return token; }
};

class game
{
protected:
    player player1,player2;
    game_board board;
    die the_die;

    // Take one players turn
    void player_turn(player& p)
    {
        int dice = the_die.roll();
        cout << "Dice stopped rolling at: " << dice << endl;

        // Keep trying until the player selects a column that is not full
        while (true) {
            cout << p.get_name() << " Enter column to play in: ";
            int col_in = get_input<int>() - 1;

            // If the choose a column outside of the board,end turn
            if ((col_in < 0) || (col_in >= board.get_num_cols()))
            {
                cout << "Turn lost!" << endl;
                return;
            }
            // Only play if column is not full
            //if (!board.column_is_full(col_in)) {
            if (board.free_spaces(col_in) >= dice) {
                // Fill in the column with the player's token
                // Note: this allows to use a column with less than dice number of free spaces
                //   Ex: column has 3 open spaces,but dice roll is 5. Will fill column to top
                for (int i = 0; !board.column_is_full(col_in) && i < dice; i++) {
                    board.add_to_col(col_in,p.get_token());
                }
                return;
            }
            cout << "Not enough space. Try again..." << endl;
        }
    }

    void print_score() const
    {
        const player players[] = { player1,player2 };
        for (int i = 0; i < 2; i++) {
            cout << "Player: " << std::left << std::setw(12) << players[i].get_name();
        }
        cout << endl;

        for (int i = 0; i < 2; i++) {
            std::stringstream ss;
            ss << "Score: " << players[i].get_token() << " -> " << board.get_count(players[i].get_token());
            cout << std::left << std::setw(20) << ss.str();
        }
        cout << endl;
    }

public:
    game(int rows,int cols) :
        player1(1),player2(2),board(rows,cols),the_die(6)
    {
    }

    void play_game()
    {
        // Keep playing until board is full
        while (!board.is_full()) {
            board.print();
            print_score();
            player_turn(player1);
            if (!board.is_full()) {
                board.print();
                print_score();
                player_turn(player2);
            }
        }
        cout << endl << "Final Score:" << endl;
        print_score();
    }
};

int main() {
    game g(12,12);
    g.play_game();

    return 0;
}


本文链接:https://www.f2er.com/2968661.html

大家都在问