0

好吧,所以我的问题是我不知道在我的数独程序中该去哪里。截至目前,我有多个程序共同创建我的数独程序,该程序应该输入 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;
}

请注意,由于无法直接复制我的代码,因此可能存在拼写错误,因此其中大部分都是新输入的。

我的 stack.cc 是

#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;
}

所以这只是我用于我的堆栈的东西

我的数独板.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!

4

3 回答 3

0

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

于 2012-10-04T07:44:50.517 回答
0

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;
}
于 2012-10-04T07:51:43.860 回答
0

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.)

于 2012-10-04T08:10:45.733 回答