Reputation:
I am new to c++ and fstream (infile) and wanted to know how data is read from a txt file and how can I put that data in an array. Basically I am trying to make this korean game called omok. where the number of times a player gets their move 4 times simultaneously either vertically, horizontally or diagonally.
Input from the txt file
4 4 2 4
2 0 B
0 1 W
3 2 B
1 3 W
Data from the first line means that its is a 4x4 array / table. 2 means that there have been 2 moves from each player and 4 moves in total.
the second line onwards where the number coresponds to the location of the move for eg 2 0 means row 2 col 0.
Output should be:
0 1 2 3
0 . W . .
1 . . . W
2 B . . .
3 . . B .
Can white player win? No
Can black player win? No
This is what I've got so far, what am I supposed to do? I am logically stuck. Could you first explain how the data is read an how I can display it like this?
void PrintBoard(char** board, int num_rows, int num_cols) {
cout << "Print board:" << endl << endl;
for (int i = 0; i < num_cols; i++) {
cout<<" "<<i;
}
cout << endl;
for (int i = 0; i < num_rows; i++) {
cout << " " << i << endl;
}
cout << endl;
/////////////////////////////////////////////////////////////////
// Print
// * " W" to print a white stone, and
// * " B" to print a black stone, and
// * " ." to print an empty cell.
/////////////////////////////////////////////////////////////////
}
/////////////////////////////////////////////////////////////////////
// Add your own functions if you need
bool CheckWhitePlayerWin(int num_rows, int num_cols, char** board, int N) {
return true;
}
bool CheckBlackPlayerWin(int num_rows, int num_cols, char** board, int N) {
return true;
}
void PrintPlayerWinCondition(int num_rows, int num_cols, char** board, int N) {
}
/////////////////////////////////////////////////////////////////////
int main(int argc, char* argv[]) {
if (argc <= 1) {
cout << "Need the input file containing board size, N, and stones." << endl;
return 0;
}
int num_rows;
int num_cols;
int N;
char** board = ReadBoard(argv[1], num_rows, num_cols, N);
PrintBoard(board, num_rows, num_cols);
if(CheckWhitePlayerWin(num_rows, num_cols, board, N))
cout << "Can white player win? Yes" << endl;
else
cout << "Can white player win? No" << endl;
if (CheckBlackPlayerWin(num_rows, num_cols, board, N))
cout << "Can black player win?" << endl;
else
cout << "Can black player win?" << endl;
cout << endl;
cout << "List of winning conditions sorted by the index of top-left stone location:" << endl;
PrintPlayerWinCondition(num_rows, num_cols, board, N);
Thanks in advance!
Upvotes: 0
Views: 190
Reputation: 13075
I agree with Ralph, and some abstraction has already been done in the standard library. It is also important as an engineer to avoid having to reinvent the wheel, this can save a lot of time testing/debugging for your employer. To see what C++ already has for you have a look here : https://en.cppreference.com/w/cpp/header
Example:
#include <iostream>
#include <vector>
using board_t = std::vector<std::vector<char>>;
void print_board(const board_t& board)
{
std::cout << std::endl;
for (const auto& row : board)
{
bool space = false;
for (const auto & value : row)
{
if (space) std::cout << ' ';
std::cout << value;
space = true;
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main()
{
board_t board
{
{ '.', 'W', '.', '.' },
{ '.', '.', '.', 'W' },
{ 'B', '.', '.', '.' },
{ '.', '.', 'B', '.' },
};
print_board(board);
};
Or using std::string as your 'array' for rows :
#include <cassert>
#include <iostream>
#include <vector>
#include <string>
// string can be considered an array of chars.
using board_t = std::vector<std::string>;
void print_board(const board_t& board)
{
std::cout << std::endl;
for (const auto& row : board)
{
bool space = false;
for (const auto & value : row)
{
if (space) std::cout << ' ';
std::cout << value;
space = true;
}
std::cout << std::endl;
}
std::cout << std::endl;
}
int main()
{
board_t board
{
"..W.",
"...W",
"B...",
"..B."
};
assert(board[1][3] == 'W');
print_board(board);
};
Upvotes: 0
Reputation: 1724
In any software project one of the key aspect you have to think about are your data structures: what do you need to store, what is the best format to store it, etc. Very often the data structures will define a lot of the resulting performance and clarity of your software.
In your case you decided to use char**
, which I think is not a good choice. This basically reflects a piece of paper, but as a programmer your main task is abstraction
. You have to re-think problems in terms of best fit for math, numerical solutions, data flow, performance and efficiency. The bad news is: there is no general best solution, it fundamentally depends on the underlying problem to solve. Since I don't know this in your case, I just provide here a way to process the char**
data. And this is probably OK for you here, but in your next, larger, projects keep this in mind.
char** ReadBoard(std::string const& filename, int& num_rows, int& num_cols, int& N) {
int n_player = 0;
std::ifstream file(filename);
file >> num_rows >> num_cols >> n_player >> N;
// create data storage
char** data = new char*[num_rows];
for (int i_row=0; i_row<num_rows; ++i_row) {
data[i_row] = new char [num_cols];
// initialize data
for (int i_col=0; i_col<num_cols; ++i_col) {
data[i_row][i_col] = '.';
}
}
// read data
int x, y;
char player;
while (file >> y >> x >> player) {
if (x>=num_rows || y>=num_cols) {
std::cout << "data out of range" << std::endl;
continue;
}
data[y][x] = player;
}
file.close();
return data;
}
void PrintBoard(char** board, int num_rows, int num_cols)
{
for (int i_row=0; i_row<num_rows; ++i_row) {
for (int i_col=0; i_col<num_cols; ++i_col) {
std::cout << board[i_row][i_col];
}
std::cout<<"\n";
}
}
Upvotes: 1