您好,登錄后才能下訂單哦!
這篇文章主要介紹“C語言如何實現數獨程序”,在日常操作中,相信很多人在C語言如何實現數獨程序問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”C語言如何實現數獨程序”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
隨機生成數獨的算法見力扣上對應題目的題解,我用的是遞歸回溯法
力扣原題
先隨機放入 11 個數就能生成一個數獨然后求數獨的解最后選擇要顯示的數字再顯示出來。這里還用到了洗牌算法選擇要隨機顯示的數字。
TCW_GUI.h
// 程序:數獨 // 編譯環境:Visual Studio 2019,EasyX_20211109 #pragma once #include<graphics.h> #include<string> #include<list> #include<functional> #include<stdio.h> #pragma comment( lib, "MSIMG32.LIB") #define TCW_GUI_BUTTON_MYSELF 0 #ifdef UNICODE #define STRING std::wstring #define SPRINTF swprintf_s #define SSCANF swscanf_s #else #define STRING std::string #define SPRINTF sprintf #define SSCANF sscanf #endif // UNICODE namespace TCW_GUI { enum class State { general = 0, touch = 1, press = 2, release = 3, forbidden = 4 }; enum class DrawDecision { text = 0, graph = 1 }; class Vec2 { public: double x, y; Vec2() :x(0), y(0) {} Vec2(double xx, double yy) :x(xx), y(yy) {}; Vec2 operator+(Vec2 num) { return Vec2(x + num.x, y + num.y); } Vec2 operator-(Vec2 num) { return Vec2(x - num.x, y - num.y); } Vec2 operator/(double num) { return Vec2(x / num, y / num); } Vec2 operator*(double num) { return Vec2(x * num, y * num); } }; class Rect { public: Rect() :size(), position() {} Rect(Vec2 position, Vec2 size) :size(size), position(position) {} Vec2 size; Vec2 position; bool isInRect(Vec2 point) { Vec2 left_top = position - size / 2.0; Vec2 right_buttom = position + size / 2.0; if (point.x >= left_top.x && point.y >= left_top.y && point.x <= right_buttom.x && point.y <= right_buttom.y)return true; return false; } }; class Button { private: double textsize = 20; double textareasize = 0.9; Vec2 defaultsize; Vec2 defaulttext; State nowstate = State::general; DrawDecision drawdecision = DrawDecision::text; void DrawButton_General(); void DrawButton_Touch(); void DrawButton_Press(); void DrawButton_Forbidden(); bool isPress = false; public: Button() :boundingbox(), buttontext() { settextstyle(textsize, 0, TEXT("微軟雅黑")); Vec2 defaultsize = Vec2(textwidth(TEXT("...")) / textareasize, textheight(TEXT("...")) / textareasize); Vec2 defaulttext = Vec2(textwidth(TEXT("...")), textheight(TEXT("..."))); } Button(Rect boundingbox, STRING buttontext, std::function<int(void*)> releaseFunc, void* releaseParam) : boundingbox(boundingbox), buttontext(buttontext), releaseFunc(releaseFunc), releaseParam(releaseParam) { drawdecision = DrawDecision::text; settextstyle(textsize, 0, TEXT("微軟雅黑")); Vec2 defaultsize = Vec2(textwidth(TEXT("...")) / textareasize, textheight(TEXT("...")) / textareasize); Vec2 defaulttext = Vec2(textwidth(TEXT("...")), textheight(TEXT("..."))); } Button(Rect boundingbox, STRING graphsrc_normal, STRING graphsrc_touch, STRING graphsrc_press, std::function<int(void*)> releaseFunc, void* releaseParam) : boundingbox(boundingbox), graphsrc_normal(graphsrc_normal), graphsrc_touch(graphsrc_touch), graphsrc_press(graphsrc_press), releaseFunc(releaseFunc), releaseParam(releaseParam) { drawdecision = DrawDecision::graph; } STRING buttontext; STRING graphsrc_normal; STRING graphsrc_touch; STRING graphsrc_press; Rect boundingbox; std::function<int(void*)> releaseFunc = nullptr; void* releaseParam = nullptr; void DrawButton(); void DrawButton_Text(State state); void DrawButton_Graph(State state); void receiver(ExMessage* msg); void ForbidButton() { this->nowstate = State::forbidden; } // 禁用按鈕 void RefreshButton() { this->nowstate = State::general; } // 恢復按鈕 void SetTextSize(double size) { textsize = size; defaultsize = Vec2(textsize * 1.5 / textareasize, textsize / textareasize); defaulttext = Vec2(textsize * 1.5, textsize); } void SetTextAreaSize(double size) { textareasize = size; defaultsize = Vec2(textsize * 1.5 / textareasize, textsize / textareasize); defaulttext = Vec2(textsize * 1.5, textsize); } }; class ButtonManager { std::list<Button> buttonlist; public: Button* AddButton(Button button); void ReceiveMessage(ExMessage* msg); void DrawButton(); }; void Rectangle_TCW(Vec2 left_top, Vec2 right_buttom) { rectangle(left_top.x, left_top.y, right_buttom.x, right_buttom.y); } void Fillrectangle_TCW(Vec2 left_top, Vec2 right_buttom) { fillrectangle(left_top.x, left_top.y, right_buttom.x, right_buttom.y); } void Outtextxy_TCW(Vec2 position, const TCHAR* str) { outtextxy(position.x, position.y, str); } void Button::DrawButton_Text(State state) { LOGFONT log; COLORREF textcol; COLORREF linecol; COLORREF fillcol; int bkmode; gettextstyle(&log); bkmode = getbkmode(); textcol = gettextcolor(); linecol = getlinecolor(); fillcol = getfillcolor(); // 默認數值 settextstyle(textsize, 0, TEXT("微軟雅黑")); settextcolor(BLACK); setbkmode(TRANSPARENT); setlinecolor(BLACK); setfillcolor(WHITE); switch (state) { case TCW_GUI::State::general: break; case TCW_GUI::State::touch: setfillcolor(RGB(240, 240, 240)); break; case TCW_GUI::State::press: setfillcolor(RGB(240, 240, 240)); break; case TCW_GUI::State::release: break; case TCW_GUI::State::forbidden: settextcolor(RGB(128, 128, 128)); break; default: break; } Vec2 size_button = Vec2(this->boundingbox.size * textareasize); Vec2 size_text = Vec2(textwidth(this->buttontext.c_str()), textsize); if (boundingbox.size.x > defaultsize.x && boundingbox.size.y > defaultsize.y) // 比最小值大 { Rectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0, this->boundingbox.position + this->boundingbox.size / 2.0); Fillrectangle_TCW(this->boundingbox.position - this->boundingbox.size / 2.0, this->boundingbox.position + this->boundingbox.size / 2.0); if (size_button.x >= size_text.x && size_button.y >= size_text.y) // 字數沒超 { switch (state) { case TCW_GUI::State::general: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str()); break; case TCW_GUI::State::touch: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str()); break; case TCW_GUI::State::press: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0 + Vec2(2, 2), buttontext.c_str()); break; case TCW_GUI::State::release: break; case TCW_GUI::State::forbidden: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str()); break; default: break; } } else // 字數超了 { int wordnum = size_button.x / textwidth(buttontext.c_str()) * buttontext.size() - 2; STRING realstr = buttontext.substr(0, wordnum); realstr += TEXT("..."); Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str()); switch (state) { case TCW_GUI::State::general: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str()); break; case TCW_GUI::State::touch: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str()); break; case TCW_GUI::State::press: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0 + Vec2(2, 2), realstr.c_str()); break; case TCW_GUI::State::release: break; case TCW_GUI::State::forbidden: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, realstr.c_str()); break; default: break; } } } else // 比最小值小 { Rectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0, this->boundingbox.position + this->defaultsize / 2.0); Fillrectangle_TCW(this->boundingbox.position - this->defaultsize / 2.0, this->boundingbox.position + this->defaultsize / 2.0); if (defaulttext.x >= size_text.x && defaulttext.y >= size_text.y) // 字寬比三個點小 { switch (state) { case TCW_GUI::State::general: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str()); break; case TCW_GUI::State::touch: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str()); break; case TCW_GUI::State::press: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0 + Vec2(2, 2), buttontext.c_str()); break; case TCW_GUI::State::release: break; case TCW_GUI::State::forbidden: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0, buttontext.c_str()); break; default: break; } } else // 字寬比三個點大 { switch (state) { case TCW_GUI::State::general: Outtextxy_TCW(this->boundingbox.position - defaulttext / 2.0, TEXT("...")); break; case TCW_GUI::State::touch: Outtextxy_TCW(this->boundingbox.position - defaulttext / 2.0, TEXT("...")); break; case TCW_GUI::State::press: Outtextxy_TCW(this->boundingbox.position - size_text / 2.0 + Vec2(2, 2), TEXT("...")); break; case TCW_GUI::State::release: break; case TCW_GUI::State::forbidden: Outtextxy_TCW(this->boundingbox.position - defaulttext / 2.0, TEXT("...")); break; default: break; } } } settextstyle(&log); settextcolor(textcol); setbkmode(bkmode); setlinecolor(linecol); setfillcolor(fillcol); } void Button::DrawButton_Graph(State state) { IMAGE img; switch (state) { case TCW_GUI::State::general: loadimage(&img, (this->graphsrc_normal).c_str()); break; case TCW_GUI::State::touch: loadimage(&img, (this->graphsrc_touch).c_str()); break; case TCW_GUI::State::press: loadimage(&img, (this->graphsrc_press).c_str()); break; case TCW_GUI::State::release: break; case TCW_GUI::State::forbidden: loadimage(&img, (this->graphsrc_normal).c_str()); break; default: break; } IMAGE* srcimg = &img; HDC dstDC = GetImageHDC(NULL); HDC srcDC = GetImageHDC(srcimg); int w = srcimg->getwidth(); int h = srcimg->getheight(); // 結構體的第三個成員表示額外的透明度,0 表示全透明,255 表示不透明。 BLENDFUNCTION bf = { AC_SRC_OVER, 0, 255, AC_SRC_ALPHA }; // 使用 Windows GDI 函數實現半透明位圖 Vec2 left_top = this->boundingbox.position - this->boundingbox.size / 2.0; AlphaBlend(dstDC, left_top.x, left_top.y, boundingbox.size.x, boundingbox.size.y, srcDC, 0, 0, w, h, bf); } void Button::DrawButton_General() { switch (this->drawdecision) { case TCW_GUI::DrawDecision::text:DrawButton_Text(State::general); break; case TCW_GUI::DrawDecision::graph:DrawButton_Graph(State::general); break; default: break; } } void Button::DrawButton_Touch() { switch (this->drawdecision) { case TCW_GUI::DrawDecision::text:DrawButton_Text(State::touch); break; case TCW_GUI::DrawDecision::graph:DrawButton_Graph(State::touch); break; default: break; } } void Button::DrawButton_Press() { switch (this->drawdecision) { case TCW_GUI::DrawDecision::text:DrawButton_Text(State::press); break; case TCW_GUI::DrawDecision::graph:DrawButton_Graph(State::press); break; default: break; } } void Button::DrawButton_Forbidden() { switch (drawdecision) { case TCW_GUI::DrawDecision::text:DrawButton_Text(State::forbidden); break; case TCW_GUI::DrawDecision::graph:DrawButton_Graph(State::forbidden); break; default: break; } } void Button::DrawButton() { switch (this->nowstate) { case State::general: DrawButton_General(); break; case State::touch: DrawButton_Touch(); break; case State::press: DrawButton_Press(); break; case State::release: DrawButton_Touch(); if (releaseFunc != nullptr) { if (releaseParam == TCW_GUI_BUTTON_MYSELF)releaseFunc(this); else releaseFunc(releaseParam); } this->nowstate = State::touch; break; case State::forbidden: DrawButton_Forbidden(); break; default: break; } } void Button::receiver(ExMessage* msg) { if (this->nowstate == State::forbidden)return; // 先 general 后 touch 再 press 一個 release 后重新 general if (!isPress && !this->boundingbox.isInRect(Vec2(msg->x, msg->y))) { this->nowstate = State::general; } else if (!isPress && this->boundingbox.isInRect(Vec2(msg->x, msg->y))) { if (!msg->lbutton) this->nowstate = State::touch; else if (this->nowstate == State::touch) { isPress = true; this->nowstate = State::press; } } else if (isPress && this->boundingbox.isInRect(Vec2(msg->x, msg->y))) { if (!msg->lbutton) { isPress = false; this->nowstate = State::release; } else this->nowstate = State::press; } else if (isPress && !this->boundingbox.isInRect(Vec2(msg->x, msg->y))) { if (!msg->lbutton) { isPress = false; this->nowstate = State::general; } else this->nowstate = State::press; } } Button* ButtonManager::AddButton(Button button) { this->buttonlist.push_back(button); return &buttonlist.back(); } void ButtonManager::ReceiveMessage(ExMessage* msg) { for (Button& button : this->buttonlist) { button.receiver(msg); } } void ButtonManager::DrawButton() { for (Button& button : this->buttonlist) { button.DrawButton(); } } }
main.cpp
// 程序:C語言數獨 // 編譯環境:Visual Studio 2019,EasyX_20211109 #include"TCW_GUI.h" #include<time.h> #define WIDTH 640 #define HEIGHT 480 class Vec2 { public: double xx, yy; Vec2(double xx = 0, double yy = 0) :xx(xx), yy(yy) {} Vec2 operator+(Vec2 ano) { return Vec2(xx + ano.xx, yy + ano.yy); } Vec2 operator-(Vec2 ano) { return Vec2(xx - ano.xx, yy - ano.yy); } Vec2 operator/(double num) { return Vec2(xx / num, yy / num); } }; class BoundingBox { public: Vec2 size, position; BoundingBox(Vec2 size, Vec2 position) :size(size), position(position) {} BoundingBox() = default; Vec2 GetLeftTop() { return position - size / 2.0; } bool isInBoundingBox(Vec2 point) { return (point.xx > position.xx - size.xx / 2.0 && point.xx < position.xx + size.xx / 2.0 && point.yy>position.yy - size.yy / 2.0 && point.yy < position.yy + size.yy / 2.0); } }; template<typename T> void WashCard(T* map, int len) { for (int i = len; i > 0; i--) { int exchange = rand() % i; T temp = map[i - 1]; map[i - 1] = map[exchange]; map[exchange] = temp; } } bool isvalid(char(* const map)[9][9], char c, int row_i, int col_i) { // 尚未放入,判斷能否放入 for (int i = 0; i < 9; ++i) { if (abs((*map)[row_i][i]) == c) return false; else if (abs((*map)[i][col_i]) == c) return false; else if (abs((*map)[3 * (row_i / 3) + i / 3][3 * (col_i / 3) + i % 3]) == c) return false; } return true; } // 遞歸回溯算法 yyds bool solver(char(* const map)[9][9], int rstart) { for (int row = rstart; row < 9; ++row) { for (int col = 0; col < 9; ++col) { if ((*map)[row][col] == 0) { for (char c = 1; c <= 9; ++c) { if (isvalid(map, c, row, col)) { (*map)[row][col] = c; if (solver(map, row)) return true; else (*map)[row][col] = 0; } } return false; } } } return true; } void GenerateSudoku(char(* const map)[9][9]) { memset(*map, 0, sizeof(*map)); char arr[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; WashCard(arr, 9); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { (*map)[i][j] = arr[i * 3 + j]; } } WashCard(arr, 9); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { (*map)[3 + i][3 + j] = arr[i * 3 + j]; } } WashCard(arr, 9); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { (*map)[6 + i][6 + j] = arr[i * 3 + j]; } } solver(map, 0); } void GetShowMap(const char(*map)[9][9], char(* const ShowMap)[9][9], bool(* const Auxiliary)[9][9], int showNum) { memset(*Auxiliary, 0, sizeof(bool) * 81); memset(*ShowMap, 0, sizeof(char) * 81); char arr[81]; for (int i = 0; i < 81; i++)arr[i] = i; WashCard(arr, 81); for (int i = 0; i < showNum; i++) { (*ShowMap)[arr[i] / 9][arr[i] % 9] = (*map)[arr[i] / 9][arr[i] % 9]; (*Auxiliary)[arr[i] / 9][arr[i] % 9] = true; } } void Rectangle_MR(Vec2 left_top, Vec2 right_bottom) { rectangle((int)(left_top.xx + 0.5), (int)(left_top.yy + 0.5), (int)(right_bottom.xx + 0.5), (int)(right_bottom.yy + 0.5)); } void Fillrectangle_MF(Vec2 left_top, Vec2 right_bottom) { fillrectangle((int)(left_top.xx + 0.5), (int)(left_top.yy + 0.5), (int)(right_bottom.xx + 0.5), (int)(right_bottom.yy + 0.5)); } void Outtextxy_MO(Vec2 pericenter, LPCTSTR str) { int width = textwidth(str); int height = textheight(str); outtextxy((int)(pericenter.xx - width / 2.0 + 0.5), (int)(pericenter.yy - height / 2.0 + 0.5), str); } void DrawMap(const char(*showMap)[9][9], const bool(*Auxiliary)[9][9], bool isSelected, int indexX, int indexY, BoundingBox boundingbox) { Vec2 grid = Vec2(boundingbox.size.xx / 9.0, boundingbox.size.yy / 9.0); Vec2 beginPoint = boundingbox.GetLeftTop(); settextstyle(grid.yy * 0.8, 0, TEXT("consolas")); settextcolor(BLACK); setlinestyle(PS_SOLID, 2); setlinecolor(BLACK); setfillcolor(WHITE); setbkmode(TRANSPARENT); for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (isSelected && i == indexY && j == indexX)setfillcolor(RED); else if ((*Auxiliary)[i][j])setfillcolor(WHITE); else setfillcolor(RGB(127, 127, 127)); Fillrectangle_MF(beginPoint + Vec2(j * grid.xx, i * grid.yy), beginPoint + Vec2((j + 1) * grid.xx, (i + 1) * grid.yy)); if ((*showMap)[i][j] != 0) { TCHAR arr[16]; if ((*showMap)[i][j] < 0)settextcolor(LIGHTRED); else settextcolor(BLACK); SPRINTF(arr, TEXT("%d"), abs((*showMap)[i][j])); Outtextxy_MO(beginPoint + Vec2((j + 0.5) * grid.xx, (i + 0.5) * grid.yy), arr); } } } setlinestyle(PS_SOLID, 3); for (int i = 0; i < 3; i++) { for (int j = 0; j < 3; j++) { Rectangle_MR(beginPoint + Vec2(j * 3 * grid.xx, i * 3 * grid.yy), beginPoint + Vec2((j + 1) * 3 * grid.xx, (i + 1) * 3 * grid.yy)); } } } bool DetectedSudoku(const char(*map)[9][9]) { bool nightHash[9][9] = { false }; bool rowHash[9][9] = { false }; bool colHash[9][9] = { false }; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if ((*map)[i][j] == 0)continue; else if ((*map)[i][j] < 0)return false; if (nightHash[i / 3 * 3 + j / 3][(*map)[i][j] - 1] == true)return false; else nightHash[i / 3 * 3 + j / 3][(*map)[i][j] - 1] = true; if (rowHash[i][(*map)[i][j] - 1] == true)return false; else rowHash[i][(*map)[i][j] - 1] = true; if (colHash[j][(*map)[i][j] - 1] == true)return false; else colHash[j][(*map)[i][j] - 1] = true; } } return true; } void StartScene(); void RandomScene(); void CustomMode(); int main() { initgraph(WIDTH, HEIGHT); BeginBatchDraw(); srand((unsigned int)time(NULL)); StartScene(); closegraph(); return 0; } void StartScene() { cleardevice(); ExMessage msg; bool isExit = false; TCW_GUI::ButtonManager manager; double buttonheight = (HEIGHT * 3 / 4.0 - 40) / 3.0; double buttonwidth = WIDTH / 3; manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH / 2, HEIGHT / 4 + 10 + buttonheight / 2), TCW_GUI::Vec2(buttonwidth, 50)), TEXT("自定義模式"), [](void*) {CustomMode(); return 0; }, nullptr)); manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH / 2, HEIGHT / 4 + 20 + buttonheight * 1.5), TCW_GUI::Vec2(buttonwidth, 50)), TEXT("隨機模式"), [](void*) { RandomScene(); return 0; }, nullptr)); manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH / 2, HEIGHT / 4 + 40 + buttonheight * 2.5), TCW_GUI::Vec2(buttonwidth, 50)), TEXT("退出游戲"), [](void* param) {*(bool*)param = true; return 0; }, &isExit)); Vec2 pericenter(WIDTH / 2, HEIGHT / 8); while (!isExit) { if (peekmessage(&msg, EM_MOUSE)) { manager.ReceiveMessage(&msg); manager.DrawButton(); } settextstyle((int)(HEIGHT / 4.0 * 0.8 + 0.5), 0, TEXT("楷體")); settextcolor(WHITE); Outtextxy_MO(pericenter, TEXT("數獨")); FlushBatchDraw(); } cleardevice(); } void RandomScene() { cleardevice(); char map[9][9]; memset(map, 0, sizeof(map)); GenerateSudoku(&map); char showMap[9][9] = { 0 }; bool Auxiliary[9][9] = { false }; int CountOfNum = 27; int CanFillNum = 81 - CountOfNum; GetShowMap(&map, &showMap, &Auxiliary, CountOfNum); ExMessage msg; bool isExit = false; bool isSelected = false; bool isWin = false; int indexX, indexY; TCW_GUI::ButtonManager command; command.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(60, 50), TCW_GUI::Vec2(100, 40)), TEXT("返回"), [](void* param) {*(bool*)param = true; return 0; }, &isExit)); command.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(60, 100), TCW_GUI::Vec2(100, 40)), TEXT("設置數字數量"), [](void* param) { TCHAR temp[3]; SPRINTF(temp, TEXT("%d"), *(int*)param); InputBox(temp, 3, TEXT("請輸入要設置的數字數量:"), TEXT("輸入框"), temp); int tempNum; SSCANF(temp, TEXT("%d"), &tempNum); if (tempNum >= 17 && tempNum < 81)*(int*)param = tempNum; return 0; }, &CountOfNum)); command.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(60, 150), TCW_GUI::Vec2(100, 40)), TEXT("重置"), [&](void* param) { GenerateSudoku(&map); GetShowMap(&map, &showMap, &Auxiliary, CountOfNum); CanFillNum = 81 - CountOfNum; isWin = false; return 0; }, nullptr)); TCW_GUI::ButtonManager manager; BoundingBox Rect(Vec2(300, 300), Vec2(WIDTH / 2.0, HEIGHT / 2.0)); char Answer[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; for (int i = 0; i < 9; i++) { TCHAR arr[16]; SPRINTF(arr, TEXT("%d"), i + 1); manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH - HEIGHT / 10, HEIGHT / 10 * (i + 1)), TCW_GUI::Vec2(HEIGHT / 11, HEIGHT / 11)), arr, [&](void* param) { if (isSelected) { // 檢查是否正確 if (showMap[indexY][indexX] > 0)CanFillNum++; showMap[indexY][indexX] = 0; char tempNum = *(char*)param; if (!isvalid(&showMap, tempNum, indexY, indexX))tempNum = -tempNum; else CanFillNum--; showMap[indexY][indexX] = tempNum; isSelected = false; if (CanFillNum == 0) { isWin = true; } else isWin = false; } return 0; }, Answer + i)); } while (!isExit) { if (peekmessage(&msg, EM_MOUSE)) { command.ReceiveMessage(&msg); manager.ReceiveMessage(&msg); if (msg.lbutton && Rect.isInBoundingBox(Vec2(msg.x, msg.y))) { Vec2 direct = Vec2(msg.x, msg.y) - Rect.GetLeftTop(); Vec2 Grid = Rect.size / 9.0; indexX = direct.xx / Grid.xx; indexY = direct.yy / Grid.yy; if (Auxiliary[indexY][indexX] == false)isSelected = true; else isSelected = false; } else if (msg.rbutton && Rect.isInBoundingBox(Vec2(msg.x, msg.y))) { Vec2 direct = Vec2(msg.x, msg.y) - Rect.GetLeftTop(); Vec2 Grid = Rect.size / 9.0; indexX = direct.xx / Grid.xx; indexY = direct.yy / Grid.yy; if (Auxiliary[indexY][indexX] == false) { if (showMap[indexY][indexX] > 0) { CanFillNum++; isWin = false; } showMap[indexY][indexX] = 0; } } } cleardevice(); manager.DrawButton(); command.DrawButton(); DrawMap(&showMap, &Auxiliary, isSelected, indexX, indexY, Rect); if (isWin) { settextcolor(YELLOW); Outtextxy_MO(Vec2(WIDTH / 2, 50), TEXT("恭喜你,勝利了")); } FlushBatchDraw(); } cleardevice(); } void CustomMode() { cleardevice(); char map[9][9] = { 0 }; char showMap[9][9] = { 0 }; bool Auxiliary[9][9] = { false }; int CanFillNum = 81; ExMessage msg; bool isExit = false; bool isSelected = false; bool isWin = false; int indexX, indexY; bool isGamePlay = false; TCW_GUI::ButtonManager command; command.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(90, 50), TCW_GUI::Vec2(150, 40)), TEXT("返回"), [](void* param) {*(bool*)param = true; return 0; }, &isExit)); command.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(90, 100), TCW_GUI::Vec2(150, 40)), TEXT("開始解數獨"), [&](void* param) { // 判斷是否安全忘了!!! if (!DetectedSudoku(&map)) { settextcolor(LIGHTGRAY); Outtextxy_MO(Vec2(WIDTH / 2, HEIGHT / 2), TEXT("這個數獨不成立")); FlushBatchDraw(); Sleep(500); return 0; } else { memcpy(showMap, map, sizeof(map)); if (!solver(&showMap, 0)) { settextcolor(LIGHTGRAY); Outtextxy_MO(Vec2(WIDTH / 2, HEIGHT / 2), TEXT("這個數獨無解")); FlushBatchDraw(); Sleep(500); return 0; } } isGamePlay = true; for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if (map[i][j] != 0)Auxiliary[i][j] = true; showMap[i][j] = map[i][j]; } } return 0; }, nullptr)); command.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(90, 150), TCW_GUI::Vec2(150, 40)), TEXT("重置"), [&](void* param) { memset(Auxiliary, 0, sizeof(Auxiliary)); memset(showMap, 0, sizeof(showMap)); memset(map, 0, sizeof(map)); CanFillNum = 81; isWin = false; isGamePlay = false; return 0; }, nullptr)); command.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(90, 200), TCW_GUI::Vec2(150, 40)), TEXT("展示其中一種答案"), [&](void* param) { memcpy(showMap, map, sizeof(map)); if (!solver(&showMap, 0)) { settextcolor(LIGHTGRAY); Outtextxy_MO(Vec2(WIDTH / 2, HEIGHT / 2), TEXT("這個數獨無解")); FlushBatchDraw(); Sleep(500); } else { memset(Auxiliary, true, sizeof(Auxiliary)); CanFillNum = 0; isWin = false; isGamePlay = true; } return 0; }, nullptr)); TCW_GUI::ButtonManager manager; BoundingBox Rect(Vec2(300, 300), Vec2(WIDTH / 2.0, HEIGHT / 2.0)); char Answer[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; for (int i = 0; i < 9; i++) { TCHAR arr[16]; SPRINTF(arr, TEXT("%d"), i + 1); manager.AddButton(TCW_GUI::Button(TCW_GUI::Rect(TCW_GUI::Vec2(WIDTH - HEIGHT / 10, HEIGHT / 10 * (i + 1)), TCW_GUI::Vec2(HEIGHT / 11, HEIGHT / 11)), arr, [&](void* param) { if (isSelected) { if (!isGamePlay) { if (map[indexY][indexX] > 0)CanFillNum++; map[indexY][indexX] = 0; char tempNum = *(char*)param; if (!isvalid(&map, tempNum, indexY, indexX))tempNum = -tempNum; else CanFillNum--; map[indexY][indexX] = tempNum; isSelected = false; } else { // 檢查是否正確 if (showMap[indexY][indexX] > 0)CanFillNum++; showMap[indexY][indexX] = 0; char tempNum = *(char*)param; if (!isvalid(&showMap, tempNum, indexY, indexX))tempNum = -tempNum; else CanFillNum--; showMap[indexY][indexX] = tempNum; isSelected = false; if (CanFillNum == 0) { isWin = true; } else isWin = false; } } return 0; }, Answer + i)); } while (!isExit) { if (peekmessage(&msg, EM_MOUSE)) { command.ReceiveMessage(&msg); manager.ReceiveMessage(&msg); if (msg.lbutton && Rect.isInBoundingBox(Vec2(msg.x, msg.y))) { Vec2 direct = Vec2(msg.x, msg.y) - Rect.GetLeftTop(); Vec2 Grid = Rect.size / 9.0; indexX = direct.xx / Grid.xx; indexY = direct.yy / Grid.yy; if (Auxiliary[indexY][indexX] == false)isSelected = true; else isSelected = false; } else if (msg.rbutton && Rect.isInBoundingBox(Vec2(msg.x, msg.y))) { Vec2 direct = Vec2(msg.x, msg.y) - Rect.GetLeftTop(); Vec2 Grid = Rect.size / 9.0; indexX = direct.xx / Grid.xx; indexY = direct.yy / Grid.yy; if (Auxiliary[indexY][indexX] == false) { if (isGamePlay) { if (showMap[indexY][indexX] > 0) { CanFillNum++; isWin = false; } showMap[indexY][indexX] = 0; } else { if (map[indexY][indexX] > 0)CanFillNum++; map[indexY][indexX] = 0; } } } } cleardevice(); manager.DrawButton(); command.DrawButton(); if (!isGamePlay)DrawMap(&map, &Auxiliary, isSelected, indexX, indexY, Rect); else DrawMap(&showMap, &Auxiliary, isSelected, indexX, indexY, Rect); if (isWin) { settextcolor(YELLOW); Outtextxy_MO(Vec2(WIDTH / 2, 50), TEXT("恭喜你,勝利了")); } FlushBatchDraw(); } cleardevice(); }
到此,關于“C語言如何實現數獨程序”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。