歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 用C++實現的解數獨(Sudoku)程序

用C++實現的解數獨(Sudoku)程序

日期:2017/3/1 9:06:41   编辑:Linux編程

我是一個C++初學者,控制台實現了一個解數獨的小程序。

代碼如下:

//"數獨游戲"V1.0
//李國良於2016年11月11日編寫完成

#include <iostream>
#include <fstream>
#include <string>
#include <Windows.h>

using namespace std;

const int ArSize = 9;

string loadFile(int arr[ArSize][ArSize]);//讀取文件,返回文件名
void printMap(int arr[ArSize][ArSize]);//顯示數獨
void solve(int arr[ArSize][ArSize], int enumer[ArSize], int i, int j);//計算當前單元格的候選數
bool solveV(int arr[ArSize][ArSize], int i, int j);//判斷當前單元格是否可填
bool lopMap(int arr[ArSize][ArSize]);//循環遍歷未解單元格,調用solveV求解
bool loopMap(int arr[ArSize][ArSize]);//暴力求解!!!
void saveFile(int arr[ArSize][ArSize], string str);//保存文件

int main()
{
    SetConsoleTitle("數獨游戲");
    int map[ArSize][ArSize];
    for (auto &row : map)
        for (auto &ival : row)
            ival = -1;
    string name = loadFile(map);
    printMap(map);
    bool surplus = lopMap(map);
    cout << "lopMap()解答完畢" << endl;
    printMap(map);
    if (!surplus)
    {
        loopMap(map);
        cout << "loopMap()解答完畢" << endl;
        printMap(map);
    }
    saveFile(map, name);
    cin.get();
    cin.get();
    return 0;
}

string loadFile(int arr[ArSize][ArSize])
{
    string fileName;
    ifstream inFile;
    cout << "請輸入文件名:" << endl;
    while (true)
    {
        cin >> fileName;
        inFile.open(fileName + ".txt");
        if (!inFile.is_open())
        {
            cout << "文件未能成功打開,請重新輸入文件名:" << endl;
            continue;
        }
        bool judg = true;
        for (int i = 0; i < ArSize; ++i)
        {
            for (int j = 0; j < ArSize; ++j)
            {
                inFile >> arr[i][j];
                if (arr[i][j] < 0 || arr[i][j] > 9)
                    judg = false;
            }
        }
        if (judg)
        {
            cout << "文件\"" << fileName << ".txt" << "\"載入成功!" << endl;
            inFile.close();
            break;
        }
        else
        {
            cout << "文件內容有誤,請重新輸入文件名:" << endl;
            inFile.close();
            continue;
        }
    }
    return fileName;
}

void printMap(int arr[ArSize][ArSize])
{
    cout << endl;
    int num = 0;
    for (int i = 0; i < ArSize; ++i)
    {
        for (int j = 0; j < ArSize; ++j)
        {
            cout << arr[i][j];
            if (j != 8)
                cout << " ";
            if (!arr[i][j])
                num += 1;
        }
        cout << endl;
    }
    cout << num << "剩余單元格!" << endl << endl;
}

void solve(int arr[ArSize][ArSize], int enumer[ArSize], int i, int j)
{
    for (int num = 0; num < ArSize; ++num)
        enumer[num] = num + 1;
    for (int m = 0; m < ArSize; ++m)
    {
        if (arr[m][j])
            enumer[arr[m][j] - 1] = 0;
    }
    for (int n = 0; n < ArSize; ++n)
    {
        if (arr[i][n])
            enumer[arr[i][n] - 1] = 0;
    }
    for (int m = i / 3 * 3; m < i / 3 * 3 + 3; ++m)
    {
        for (int n = j / 3 * 3; n < j / 3 * 3 + 3; ++n)
        {
            if (arr[m][n])
                enumer[arr[m][n] - 1] = 0;
        }
    }
}

bool solveV(int arr[ArSize][ArSize], int i, int j)
{
    int enumeration[ArSize];
    int ation[ArSize];
    solve(arr, enumeration, i, j);
    int x = 0;
    int y;
    for (int i = 0; i < ArSize; ++i)
    {
        if (enumeration[i])
        {
            y = i;
            x += 1;
        }
    }
    if (x == 1)
    {
        arr[i][j] = enumeration[y];
        return true;
    }
    else
    {
        for (y = 0; y < ArSize; ++y)
        {
            if (enumeration[y])
            {
                for (int m = 0; m < ArSize; ++m)
                {
                    if (arr[m][j] == 0 && m != i)
                    {
                        solve(arr, ation, m, j);
                        if (ation[y])
                        {
                            break;
                        }
                    }
                }
                if (!ation[y])
                {
                    arr[i][j] = enumeration[y];
                    return true;
                }
                for (int n = 0; n < ArSize; ++n)
                {
                    if (arr[i][n] == 0 && n != j)
                    {
                        solve(arr, ation, i, n);
                        if (ation[y])
                        {
                            break;
                        }
                    }
                }
                if (!ation[y])
                {
                    arr[i][j] = enumeration[y];
                    return true;
                }
                bool judge = false;
                for (int m = i / 3 * 3; m < i / 3 * 3 + 3; ++m)
                {
                    for (int n = j / 3 * 3; n < j / 3 * 3 + 3; ++n)
                    {
                        if (arr[m][n] == 0 && (m != i || n != j))
                        {
                            solve(arr, ation, m, n);
                            if (ation[y])
                            {
                                goto label;
                            }
                        }
                    }
                }
                label:
                if (!ation[y])
                {
                    arr[i][j] = enumeration[y];
                    return true;
                }
            }
        }
    }
    return false;
}

bool lopMap(int arr[ArSize][ArSize])
{
    int num = 0;
    while (true)
    {
        int number = 0;
        for (int i = 0; i < ArSize; ++i)
        {
            for (int j = 0; j < ArSize; ++j)
            {
                if (!arr[i][j])
                {
                    if (!solveV(arr, i, j))
                    {
                        number += 1;
                    }
                }
            }
        }
        if (!number || num == number)
        {
            num = number;
            break;
        }
        num = number;
    }
    return num == 0 ? true : false;
}

bool loopMap(int arr[ArSize][ArSize])
{
    for (int i = 0; i < ArSize; ++i)
    {
        for (int j = 0; j < ArSize; ++j)
        {
            if (!arr[i][j])
            {
                int enumer[ArSize];
                solve(arr, enumer, i, j);
                for (int n = 0; n < ArSize; ++n)
                {
                    if (enumer[n])
                    {
                        int maps[ArSize][ArSize];
                        for (int x = 0; x < ArSize; ++x)
                        {
                            for (int y = 0; y < ArSize; ++y)
                            {
                                maps[x][y] = arr[x][y];
                            }
                        }
                        maps[i][j] = enumer[n];
                        if (lopMap(maps))
                        {
                            for (int x = 0; x < ArSize; ++x)
                            {
                                for (int y = 0; y < ArSize; ++y)
                                {
                                    arr[x][y] = maps[x][y];
                                }
                            }
                            return true;
                        }
                        else
                        {
                            bool judge = true;
                            for (int i = 0; i < ArSize; ++i)
                            {
                                for (int j = 0; j < ArSize; ++j)
                                {
                                    if (!maps[i][j])
                                    {
                                        int num = 0;
                                        int enumerat[ArSize];
                                        solve(maps, enumerat, i, j);
                                        for (auto n : enumerat)
                                        {
                                            num += n;
                                        }
                                        if (!num)
                                        {
                                            judge = false;
                                        }
                                    }
                                }
                            }
                            if (judge)
                            {
                                if (loopMap(maps))
                                {
                                    for (int x = 0; x < ArSize; ++x)
                                    {
                                        for (int y = 0; y < ArSize; ++y)
                                        {
                                            arr[x][y] = maps[x][y];
                                        }
                                    }
                                    return true;
                                }
                            }
                        }
                    }
                }
                return false;
            }
        }
    }
}

void saveFile(int arr[ArSize][ArSize], string str)
{
    ofstream outFile;
    outFile.open(str + "answer.txt");
    if (!outFile.is_open())
    {
        cout << "文件保存失敗!" << endl;
        return;
    }
    for (int i = 0; i < ArSize; ++i)
    {
        for (int j = 0; j < ArSize; ++j)
        {
            outFile << arr[i][j];
            if (j != 8)
                outFile << " ";
        }
        outFile << endl;
    }
    cout << "文件\"" << str << "answer.txt" << "\"保存成功!" << endl;
    outFile.close();
}

loopMap()函數使用了遞歸,遞歸函數寫的非常傷腦筋,感覺這個函數寫的不好,目前還沒找到改進的辦法,姑且能用。

Copyright © Linux教程網 All Rights Reserved