问题
Alright so my problem is that I have no idea where to go in my situation with my Sudoku Program. As of right now I have multiple programs that work together to create my Sudoku program which is SUPPOSED to take input of 9 lines with 9 characters each whether it be just spaces or numbers. example:
53 7
6 195
98 6
8 6 3
4 8 3 1
7 2 6
6 28
419 5
8 79
What the program would yield would be:
534678912
672195348
198342567
859761423
426853791
713924856
961537284
287419635
345286179
My current programs consist of the files stack.h, stack.cc, sudokuboard.h sudokuboard.cc, sudoku.cc, and Makefile, as well as test.txt(consists the example of input i had above)
the programs stack.h:
struct Node {
StackElementType data;
Node *next;
};
class Stack {
public:
Stack(); //constructor
~Stack(); //deconstructor
Stack(const Stack & orig); // copy constructor
void output(ostream & ostr) const; //output method
bool empty() const; // if empty returns true
void push(const StackElementType & item); // puts new item on top of stack
void pop(); // removes top element of nonempty stack
StackElementType top() const; // returns copy of top element of a stack
private:
Node*first;
size_t _size;
}
Note that there may be misspellings in this due to having to being unable to copy my code directly so most of this is freshly typed out.
My stack.cc is
#include "stack.h"
#include <cstdlib>
#include <cassert>
void destroy(Node *p)
{
// delete all nodes dominated by p.
while (p != NULL) {
Node *old = p;
p = p->next;
delete old;
}
}
Node *copy(Node *p)
{
// Make a deep copy of linked list dominated by p.
Node *result = NULL;
if (p != NULL) {
result = new Node;
Node *last = result;
while (p != NULL) {
// invariant: last points to a node ready to receive p's data.
last->data = p->data;
last->next = NULL;
p = p->next;
if (p != NULL) {
// there's going to more to this copy. Get it ready.
last->next = new Node;
last = last->next;
}
}
}
return result;
}
Stack::Stack()
{
first = NULL;
}
Stack::~Stack()
{
destroy(first);
}
Stack::Stack(const Stack & orig)
{
first = copy(orig.first);
}
Stack & Stack::operator=(const Stack & rhs)
{
if (this != &rhs)
first = copy(rhs.first);
return *this;
}
void Stack::output(ostream & ostr) const
{
ostr << "<";
for(Node *p = first;p;p=p->next) {
ostr << p->data;
if (p->next)
ostr << ", ";
}
ostr << ">";
}
void Stack::push(const ElementType & item)
{
Node *born = new Node;
born->data = item;
born->next = first;
first = born;
}
void Stack::pop()
{
assert(!empty());
Node *rest = first->next;
delete first;
first = rest;
}
ElementType Stack::top() const
{
assert(!empty());
return first->data;
}
bool Stack::empty() const
{
return first==NULL;
}
So this is simply what I am using for my stack
My sudokuboard.h:
#include <iostream>
#define SDIM 9
class SudokuBoard {
public:
//------------------------------------------------------------------------
SudokuBoard();
// Construct a blank sudoku board
//------------------------------------------------------------------------
//------------------------------------------------------------------------
void print(std::ostream & ostr) const;
// display it. duh.
//------------------------------------------------------------------------
//------------------------------------------------------------------------
void place(size_t r, size_t c, char digit);
// PRE: safe(r,c,digit)
//------------------------------------------------------------------------
//------------------------------------------------------------------------
void remove(size_t r, size_t c, char digit);
// PRE: get(r,c) == digit
//------------------------------------------------------------------------
//------------------------------------------------------------------------
char get(size_t r, size_t c) const;
// Return the digit at (r,c) on the board. or ' ' if blank.
//------------------------------------------------------------------------
//------------------------------------------------------------------------
bool safe(size_t r, size_t c, char digit) const;
//
//------------------------------------------------------------------------
//------------------------------------------------------------------------
bool done() const;
// Return true iff every cell has a number
//------------------------------------------------------------------------
private:
std::string rows[SDIM];
};
While my sudokuboard.cc
#include <iostream>
#include <cassert>
#include "sudokuboard.h"
#define ASSERTBOUNDS assert(0 <= r and r < SDIM and 0 <= c and c < SDIM)
SudokuBoard::SudokuBoard()
{
for (size_t i = 0;i<SDIM;i++) {
rows[i] = "";
for (size_t j=0;j<SDIM;j++)
rows[i] += ' ';
}
}
void SudokuBoard::place(size_t r, size_t c, char digit)
{
ASSERTBOUNDS;
assert(safe(r,c,digit));
}
void SudokuBoard::remove(size_t r, size_t c, char digit)
{
ASSERTBOUNDS;
assert(get(r,c)==digit);
rows[r][c] = ' ';
}
char SudokuBoard::get(size_t r, size_t c) const
{
ASSERTBOUNDS;
return rows[r][c];
}
void SudokuBoard::print(std::ostream & ostr) const
{
for (size_t i=0;i<SDIM;i++)
ostr << rows[i] << std::endl;
}
bool SudokuBoard::safe(size_t r, size_t c, char digit) const
{
for(size_t r=0; r<SDIM; r++)
for(size_t c=0; c<SDIM; c++)
if (get(r,c) == digit)
return false;
for(size_t c=0; c<SDIM; c++)
for(size_t r=0; r<SDIM; r++)
if (get(r,c) == digit)
return false;
return true;
}
bool SudokuBoard::done() const
{
for (size_t r=0;r<SDIM;r++)
for (size_t c=0;c<SDIM;c++)
if (rows[r][c]==' ')
return false;
return true;
}
My sudoku.cc right now is pretty much blank because I have only a general idea on how to pursue my goal. The way I am going to fill in the empty spaces is that I am going to take to take a single area and put in the smallest possible number in its current row/column and if there is a higher number in its row/column is goes up +1. I then go down the column and so on.
My question is how do i integrate the following programs of sudokuboard.cc and stack.cc in my sudoku.cc. I know I have to get the input of test.txt some how and convert each of the lines to the empty board, but I don't know how to phrase the cin input for that at all!
In other words I am looking for any help to get my sudok.cc started and how should I approach it?
sudoku.cc
#include <iostream>
#include <cassert>
#include "sudokuboard.h"
#include "stack.h"
int main()
{
}
I just want to say thank you who gave me these answers, now my lab is well on its way thanks to you guys! I cannot give any of you points b/c my rep is too low but otherwise i would!
回答1:
The method I would use to read the text file:
//Code here
std::ifstream infile("test.txt", std::ios::binary);
if(infile.is_open())
{
char szFileData[32]; //I think we can assume that each line won't be above 32 bytes
infile.getline(szFileData, 32);
do
{
//Set the cells to the data you just pulled
infile.getline(szFileData, 32);
}while(infile.good());
}
else
{
std::cout<<"Unable to open file!"<<std::endl;
}
回答2:
To read in a file, look at fstream. You can read from a file stream as you would from std::cin.
You could then read the whole file and store it in a std::vector<std::string>
or something else, it's up to you. Find the container that suits you the most to use.
std::vector<std::string> data;
std::string line;
std::fstream file("test.txt", std::in);
if (file.good())
{
while (file.eof() == false)
{
getline(file, line);
data.push_back(line);
}
}
You can then access the data by doing data[r][c]
.
I can't test it right now so there may be some slight errors, but it's the general idea
回答3:
My first question is why you even have a Stack
class. You have a
stack for free if you use a recursive function.
With regards to your question: I'd use std::getline
to read the lines.
Whether you ignore characters beyond the 9th, to allow comments, or
whether you treat them as a format error on input is up to you. From
experience, however, I'd at least allow additional trailing whitespace.
Once you have the line, the easiest solution is probably to force it up
to a minimum of 9 characters (function resize
on the string), adding
trailing blanks. I'd then check that all of the characters are either
digits or the space character (std::find_if
, with an appropriate
predicate). It might also be simpler if you converted spaces into '0':
if your internal representation uses 0
for an empty square (the most
logical choice, IMHO), you can then simply subtrace '0'
from each
character and assign it to the appropriate square.
Assuming the most logical representation of the board (vector<int>
), this
would give something like:
struct TransformInputForSudoku
{
int operator()( char ch ) const
{
if ( ch == ' ' ) {
return 0;
} else if ( ! isdigit( static_cast<unsigned char>( ch ) ) ) {
return ch - '0';
} else {
throw std::runtime_error( "Illegal character" ) ;
}
}
};
std::vector<int>
getBoard( std::istream& source )
{
std::vector<int> results;
while ( results.size() < 81 ) {
std::string line;
if ( ! std::getline( source, line ) ) {
throw std::runtime_error( "Input error" );
}
line.resize( 9, ' ' ); // extra char's are comments
std::transform( line.begin(),
line.end(),
std::back_inserter( results ),
TransformInputForSudoku() );
}
return results;
}
(This code combines input validation and conversion in a single functional object.)
来源:https://stackoverflow.com/questions/12722392/how-to-get-input-from-another-file-for-my-sudoku-game-c-using-a-txt-file