Puzzle UVA - 227

對迷宮的移動進行模擬。需要注意的是輸入緩衝區殘留問題和輸出格式問題。

  1. 輸出案例之間隔一個空行,可以使用第一個輸出後沒有空行,之後的每個輸出前都輸出空行。這樣就保證所有輸出之間的空行
  2. 棄用fflush和gets函數,gets函數無限制的讀取,stream指向stdin,fflush函數的行爲不確定,而且fflush函數可移植性不好
  3. 使用自定義flush緩存處理函數。

介紹一下緩衝區

緩衝區又稱爲緩存,它是內存空間的一部分。也就是說,在內存空間中預留了一定的存儲空間,這些存儲空間用來緩衝輸入或輸出的數據,這部分預留的空間就叫做緩衝區。緩衝區根據其對應的是輸入設備還是輸出設備,分爲輸入緩衝區和輸出緩衝區。

爲什麼要引入緩衝區

比如我們從磁盤裏取信息,我們先把讀出的數據放在緩衝區,計算機再直接從緩衝區中取數據,等緩衝區的數據取完後再去磁盤中讀取,這樣就可以減少磁盤的讀寫次數,再加上計算機對緩衝區的操作大大快於對磁盤的操作,故應用緩衝區可大大提高計算機的運行速度

又比如,我們使用打印機打印文檔,由於打印機的打印速度相對較慢,我們先把文檔輸出到打印機相應的緩衝區,打印機再自行逐步打印,這時我們的CPU可以處理別的事情。

現在您基本明白了吧,緩衝區就是一塊內存區,它用在輸入輸出設備和CPU之間,用來緩存數據。它使得低速的輸入輸出設備和高速的CPU能夠協調工作,避免低速的輸入輸出設備佔用CPU,解放出CPU,使其能夠高效率工作。

當程序調用getchar()函數時,程序就等着用戶按鍵,用戶輸入的字符被存放在鍵盤緩衝區中,直到用戶按回車爲止(回車字符也放在緩衝區中)。當用戶鍵入回車之後,getchar()函數纔開始從鍵盤緩衝區中每次讀入一個字符。也就是說,後續的getchar()函數調用不會等待用戶按鍵,而直接讀取緩衝區中的字符,直到緩衝區中的字符讀完後,才重新等待用戶按鍵。

這裏說一下,題目第二個樣例和第三個樣例的輸入行的空格顯示不出來

#include <cstdio>
#include <cstring>
#include <ctype.h>
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
char maze[5][5];
//標記空格位置
int x, y;
/**
* 將(x1, y1)按dir方向移動
* @prama x1, y1 待移動的空格
* @prama dir 移動方向
* @return 返回是否移動成功
*/
bool move(int x1, int y1, char dir)
{
    int nx = x1, ny = y1;
    if (dir == 'L')
    {
        ny--;
    }
    else if (dir == 'B')
    {
        nx++;
    }
    else if (dir == 'A')
    {
        nx--;
    }
    else if (dir == 'R')
    {
        ny++;
    }
    //檢測是否合法
    if (nx >= 0 && nx < 5 && ny >= 0 && ny < 5)
    {
        char tmp;
        maze[x1][y1] = maze[nx][ny];
        maze[nx][ny] = ' ';
        x = nx, y = ny;
        return true;
    }
    else
    {
        return false;
    }
}
void print()
{
    _for (i, 0, 5)
    {
        _for (j, 0, 5)
        {
            if (j == 0)
            {
                printf("%c", maze[i][j]);
            }
            else
            {
                printf(" %c", maze[i][j]);
            }
        }
        printf("\n");
    }
}
/**
* 自定義輸入流殘存處理函數
*/
void flush()
{
    char ch;
    while ((ch = getchar()) != '\n' && ch != 'EOF') ;
}
int main()
{
    char s[10];
    //記錄案例個數
    int cnt = 0;
    while (1)
    {
    	//移動合法爲true,反之
        bool moveflg = true;
        _for (i, 0, 5)
        {
            fgets(s, 7, stdin);
            _for (j, 0, 5)
            {
                if (s[0] == 'Z')
                {
                    return 0;
                }
                maze[i][j] = s[j];
                if (maze[i][j] == ' ' || maze[i][j] == '\n')
                {
                    maze[i][j] = ' ';
                    x = i;
                    y = j;
                }
            }
        }
        int ch;
        //讀入移動方向字符
        while ((ch = getchar()) != '0')
        {
            if (ch == 'A' || ch == 'B' || ch == 'L' || ch == 'R')
            {
                if (!move(x, y, ch))
                    moveflg = false;
            }
            //換行符空格不做處理
        }
        //清空緩存殘留
        flush();
        if (cnt++) printf("\n");
        printf("Puzzle #%d:\n", cnt);
        if (moveflg)
        {
            print();
        }
        else
        {
            printf("This puzzle has no final configuration.\n");
        }
    }
    return 0;
}

對於字符串的處理C++string容器比C語言的使用效果更好。C++STL幫助我們簡單的完成代碼實現。
相對來說,C++輸入更方便,輸出格式不如C好控制。我們因根據情況選擇合適的方法幫助我們解題。
程序設計 = 思維+實現,程序設計希望我們把重心放在思維上,儘量使用C++解題
進階模板代碼,二維幾何運算

#include <cstdio>
#include <cstring>
#include <ctype.h>
#include <vector>
#include <string>
#include <iostream>
#include <map>
#define _for(i, a, b) for (int i = (a); i < (b); ++i)
using namespace std;

//二維幾何運算類
struct Point 
{
  int x, y;
  Point(int x=0, int y=0):x(x),y(y) {}
};
typedef Point Vector;

Vector operator+ (const Vector& A, const Vector& B) { return Vector(A.x+B.x, A.y+B.y); }
Vector operator- (const Point& A, const Point& B) { return Vector(A.x-B.x, A.y-B.y); }
Vector operator* (const Vector& A, int p) { return Vector(A.x*p, A.y*p); }
Vector operator/ (const Vector& A, int p) { return Vector(A.x/p, A.y/p); }
bool operator== (const Point& a, const Point &b) { return a.x == b.x && a.y == b.y; }
bool operator< (const Point& p1, const Point& p2) { return p1.x < p2.x || (p1.x == p2.x && p1.y < p2.y); }

const int Gsize = 5;
vector<string> grid;
map<char, Vector> DIRS;
Vector epos;

bool valid(const Point& p)
{
    return p.x >= 0 && p.y >= 0 && p.x < Gsize && p.y < Gsize;
}

void printGrid()
{
    _for (i, 0, Gsize)
    {
        _for (j, 0, Gsize)
        {
            if (j)
            {
                cout << ' ';
            }
            cout << grid[i][j];
        }
        cout << endl;
    }
}

bool tryMove(char cmd)
{
    if (!DIRS.count(cmd)) return false;
    Point p = epos + DIRS[cmd];
    if (!valid(p)) return false;
    swap(grid[p.x][p.y], grid[epos.x][epos.y]);
    epos = p;
    return true;
}

int main()
{
    int t = 1;
    string line;
    DIRS['A'] = Vector(-1, 0);
    DIRS['B'] = Vector(1, 0);
    DIRS['L'] = Vector(0, -1);
    DIRS['R'] = Vector(0, 1);
    while (true)
    {
        grid.clear();
        epos.x = -1, epos.y = -1;
        _for (i , 0, Gsize)
        {
            getline(cin, line);
            if (line == "Z")
            {
                return 0;
            }
            _for (j, 0, Gsize)
            {
                if (line[j] == ' ')
                {
                    epos.x = i;
                    epos.y = j;
                }
            }
            grid.push_back(line);
        }
        string moves;
        while (true)
        {
            getline(cin, line);
            bool end = *(line.rbegin()) == '0';
            if (!end) moves.append(line);
            else moves.append(line, 0, line.size() - 1);
            if (end)
                break;
        }
        bool legal = true;
        _for (i, 0, moves.size())
        {
            if (!tryMove(moves[i]))
            {
                legal = false;
                break;
            }
        }
        if (t > 1)  cout << endl;
        cout << "Puzzle #" << t++ << ":" << endl;
        if (legal) printGrid();
        else cout << "This puzzle has no final configuration.\n";
    }
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章