Итак, моя проблема в том, что я понятия не имею, куда идти в моей ситуации с моей программой Судоку. На данный момент у меня есть несколько программ, которые работают вместе, чтобы создать мою программу Судоку, которая ПРЕДЛАГАЕТСЯ вводить 9 строк по 9 символов в каждой, будь то пробелы или цифры.
пример:
53 7
6 195
98 6
8 6 3
4 8 3 1
7 2 6
6 28
419 5
8 79
Что программа даст:
534678912
672195348
198342567
859761423
426853791
713924856
961537284
287419635
345286179
Мои текущие программы состоят из файлов stack.h, stack.cc, sudokuboard.h sudokuboard.cc, sudoku.cc и Makefile, а также test.txt (содержит пример ввода, который у меня был выше)
программы 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;
}
Обратите внимание, что в этом могут быть ошибки из-за невозможности напрямую скопировать мой код, поэтому большая часть этого текста только что напечатана.
Мой стек
#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;
}
Так что это просто то, что я использую для своего стека
Мой 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];
};
Пока мой 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;
}
Мой sudoku.cc сейчас довольно пустой, потому что у меня есть только общее представление о том, как преследовать мою цель. То, как я собираюсь заполнить пустые места, так это то, что я собираюсь взять одну область и ввести наименьшее возможное число в ее текущей строке / столбце, и если в ее строке / столбце есть большее число, до +1. Затем я иду вниз по колонне и так далее.
Мой вопрос заключается в том, как мне интегрировать следующие программы sudokuboard.cc и stack.cc в мой sudoku.cc. Я знаю, что мне нужно как-то получить входные данные test.txt и преобразовать каждую строку в пустую доску, но я вообще не знаю, как сформулировать входные данные cin для этого!
Другими словами, я ищу любую помощь, чтобы начать мой sudok.cc и как я должен приблизиться к этому?
sudoku.cc
#include <iostream>
#include <cassert>
#include "sudokuboard.h"#include "stack.h"
int main()
{}
Я просто хочу сказать спасибо, кто дал мне эти ответы, теперь моя лаборатория успешно работает благодаря вам, ребята! Я не могу дать никому из вас баллы, потому что мой представитель слишком низкий, но в противном случае я бы сделал это!
Метод, который я бы использовал для чтения текстового файла:
//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;
}
Чтобы прочитать в файле, посмотрите на fstream. Вы можете читать из файлового потока так же, как из std :: cin.
Затем вы можете прочитать весь файл и сохранить его в std::vector<std::string>
или что-то еще, это зависит от вас. Найдите контейнер, который подходит вам больше всего.
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);
}
}
Вы можете получить доступ к данным, выполнив data[r][c]
,
Я не могу проверить это прямо сейчас, поэтому могут быть небольшие ошибки, но это общая идея
Мой первый вопрос, почему у вас даже есть Stack
учебный класс. У тебя есть
стек бесплатно, если вы используете рекурсивную функцию.
Что касается вашего вопроса: я бы использовал std::getline
читать строки.
Игнорируете ли вы символы за пределами 9-го, чтобы разрешить комментарии, или
Относитесь ли вы к ним как к ошибке формата при вводе, зависит от вас. От
опыт, однако, я бы, по крайней мере, разрешил дополнительные пробелы.
Как только у вас есть линия, самое простое решение, вероятно, это заставить ее
минимум 9 символов (функция resize
на строку), добавив
концевые заготовки. Затем я бы проверил, что все персонажи
цифры или пробел (std::find_if
с соответствующим
сказуемое). Это также может быть проще, если вы конвертируете пробелы в ‘0’:
если ваше внутреннее представительство использует 0
для пустого квадрата (наиболее
логичный выбор, имхо) тогда можно просто вычесть '0'
с каждого
характер и назначить его на соответствующий квадрат.
Предполагая наиболее логичное представление доски (vector<int>
), этот
дал бы что-то вроде:
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;
}
(Этот код объединяет проверку ввода и преобразование в одном
функциональный объект.)