### 瀏覽

- 索引
- 模組 |
- 下一頁 |
- 上一頁 |
- SudokuStudyLib 1.0 documentation »

# 如何在 Python 中製作一個解數獨的模擬環境?

我們認為, 類別定義, 是在OOP程式設計中最困難的部分. 所以在這些課程中, 我們不準備詳細地解釋如何設計類別, 屬性與方法. 我們只會解說在這個程式庫中既有的類別, 屬性與方法. 所以我們可以類比這些類別, 屬性與方法所構成的資料結構是一個解決數獨的模擬環境, 以便讓學習者以人的思考模式來學習如何解開一個數獨.

首先, 我們可以想像在一個美麗的山谷中, 有 9x9 間方方正正的房子, 它們排列如下:

一個假想的聯合王國

這裡有 9 個國家, 每一個國家有 9 個人, 他們決定一起定居在這個美麗的山谷. 而這個山谷共有 9x9 間房子. 他們決定每一排(x-way line), 每一列(y-way line), 及每一個 3x3 區塊都包含了每一個國家的人. 如此, 他們才會認為他們這個團體才是一個真正的聯合王國, 可以永久和平地生活在一起. 你可以幫助他們達到這個目的嗎?

接著, 我們就可以開始協助這些人來促成這一個美好的世界...

## 甚麼是類別? 甚麼是物件?

在OOP中，類別(class)的定義是主角。它就如同人類j為了探索、溝通或者紀錄等目的，會將有同樣行為、特性與外表的事物歸類一樣。如同我們會將動物當作一類，而大象就是動物類別的一個子類別，一隻大象就是同屬於動物及大象這兩類的一個物件。

雖然在自然上，一隻大象這個物件同時隸屬於大象類及動物類，但看目標的需要，也可以直接將一隻大象當做動物類別的一個物件即可。所以我們可以說在 OOP 所說的物件(Object)就是我們現實世界的一個實體，就如同人類若是一個類別，那你就是隸屬此類別的一個唯一獨立的物件。

依據我們設定的範圍與需要，我們可能設計出不同的類別，而讓同一個物件同時隸屬於它們。如我們想要研究城市生態時，我們可能會設計一個 animal 類別，而這個類別中的物件包括一些人，一些寵物等等...但當我們想要製作一個電話簿程式時，那我們就會設計一個 person 類別，一些人會成為此類別的物件，但不會包括寵物，除非這些寵物也都擁有手機。

在這個專案中，我們設計的主要類別有:

- Number Class:

  > 我們可以視數獨遊戲中每個數字是一個人。而整個數獨世界中有 9 個國家，每個國家有 9 個人。如此，這個 Number Class 就可以視為是一個國家類別。每一個國家都有一個識別代碼(ID)，在這裡是 1-9，而每個國家都會紀錄它的人民住在這山谷中的位置。

- Point Class:

  > Point 物件就是一間房子。 每間房子都會標註它是否已住人，如果已住人，那是哪個國家的人民；如果是空的，那可以讓哪些國家的人民來申請入住？

- GroupBase Class:

  > GroupBase是一種群組類別，也就是它的物件不是一個實體，而是一群實體的組合。在這裡的 GroupBase 包含了三種群組，X 與 Y 軸方向的房子群組及區塊房子群組。 每個物件都將指出它包含了哪些房子，已經住了多少人，還有哪些國家的人民還沒住進來？

- Box Class:

  > 它是GroupBase的子類別，為區塊群組。在數獨世界中總共有 9 個區塊物件，從左到右，從上到下，被標註其區塊代碼如下:

- lineX Class:

  > 這是 GroupBase 子類別，為 X 軸的房子群組。在數獨世界中共有 9 個物件，從左到右被標註 1-9，如下圖:

- lineY Class:

  > 這是 GroupBase 子類別，為 Y 軸的房子群組。在數獨世界中共有 9 個物件，從上到下被標註 1-9，如下圖:

- Matrix Class:

  > Matrix class定義了數獨遊戲的整個世界。它是一個美麗的山谷，包含了 9 個國家的人民，每一個國家有 9 個人，山谷中建造了 9x9 間房子以提供給這些人民來居住，以組成一個永遠和平的聯合王國。

## 甚麼是屬性(Property)？

屬性(Property)是在類別(Class)的定義裡面，類別用它來定義成員，特徵及紀錄狀況。如在一個人的類別裡面可能會包含以下一些屬性: 這人擁有多少錢、他有幾個小孩子、第一個小孩是男或是女、每個小孩各是幾歲?

以下是這個專案中幾個主要類別的主要屬性定義:

- Number class:

  > - v: 這個國家的代碼, 1-9

  > - p: 這個國家每一個人民所居住的房子列表

  > - filled: 有多少人已經住進房子了

- Point class:

  > - x: 這個房子的 x 軸座標

  > - y: 這個房子的 y 軸座標

  > - v: 這個房子居住了哪個國家的人民，如果是空的，那它的值就是 0

  > - b: 這個房子隸屬哪個區塊

- GroupBase class:

  > - idx: 這個群組的代碼

  > - p: 隸屬這個群組的房子列表

  > - filled: 在這個群組裡面已經居住了多少人

  > - possilbe: 在這個群組裡面還有哪些國家還沒住進來，值為這些國家的代碼列表

- Box class:

  > - 包含所有 GroupBase 的屬性

  > - effects: 這個區塊的所有鄰居區塊

  > - effectsX: 這個區塊的 x 軸方相鄰居

  > - effectsY: 這個區塊的 y 軸方相鄰居

- lineX class:

  > - 與 GroupBase 的屬性相同

- lineY class:

  > - 與 GroupBase 的屬性相同

- Matrix class:

  > - p: 一個二階陣列的房子列表，從 p[0][0] 到 p[8][8]，代表這個山谷的所有房子。

  > - lineX: x 軸方向房子群組的列表

  > - lineY: y 軸方向房子群組的列表

  > - b: 區塊房子群組的列表

  > - n: 所有國家的列表

  > - filled: 紀錄已經有多少人入住在這個山谷了

## 甚麼是方法(Method)？

方法(methods)是一個類別及其物件的一些特定行為。舉個例子，如果我們定義了一個收音機類別，它將包含一些按鈕的屬性，而當我們按下這些按鈕時，我們就必須定義一些方法來執行這個動作。這些動作有可能是開始接收某個電台的節目、或者是錄製節目到CD等等...

以下是這個專案中的類別中使用道的主要方法:

- Number class:

  > - setit(p1): 當有人找到屬於自己的房子時，就會啟動這個方法

- Point class:

  > - can_see(p1): 測試一個房子是否能夠**看到**另外一個房子(p1)?

  > - can_see_those(posList): 測試一個房子能否**看見** posList 所列的房子，並將所有能看見的房子列表傳回。

  > 註解

  > 甚麼是「看見」？

  > 對一個房子而言，與它同一排、同一列、或者同在一個區塊的其他房子，都是它能夠**看見**的房子。

- GroupBase class:

  > - allow(v): 測試一個房子群組能否讓標記為 v 的國家人民來居住？

  > - get_num_pos(v): 在這個房子群組中，取得 v 國人民居住的房子物件，如果該國尚未有人入住，則以None來回應。

  > - count_num_possible(count): 在一個房子群組中，取得國家的id及可供該國人民居住的房子列表，如果有參數 count，則表示要取得的可供居住的房子數要等於 count 才取回。

  > - get_all_pos(method): 如果 method = “a”， 取得一個房子群組的所有房屋物件列表；如果 method=”u”，則取得所有空房列表；如果 method=”s”，則取得所有已住人的房子列表。

- Box class:

  > - 所有 GroupBase 類別的方法

  > - get_group_number(num): 測試這個國家代碼 num 在一個房子區塊中能否形成一個 虛擬國民？

  > 註解

  > 甚麼是「虛擬國民」？

  > 虛擬國民存在於一個房子區塊群組中。在一個區塊中尚未有人入住的房子中，如果所有可能讓某個國家居住的房子在同一個方向時(無論是 x 軸或 y 軸)，那我們就可以稱這些房子形成了一個**虛擬國民**。雖然我還不曉得在這個區塊中，這個國家的人民最後將居住在哪裡，但我們從虛擬國民中知道，在與它同個方向的其他區域的房子，都將不允許居住這個國家的人民了。

- lineX class:

  > - 與 GroupBase 有相同的方法

- lineY class:

  > - 與 GroupBase 有相同的方法

- Matrix class:

  > - get_all_pos(method): 如果 method = “a”， 取得所有房屋物件列表；如果 method=”u”，則取得所有空房列表；如果 method=”s”，則取得所有已住人的房子列表。

  > - sort_unassigned_pos_by_possibles(possibles): 取得所有的空房列表，而這些空房數必須僅能夠讓 possibles 個國家的人入住，如果 possibles == 0, 將取得全部空房。回應回來時將以可居住國家數 ，從小排到大。

  > - can_see(p0, method=”u”, num=0): 取得能夠看見某一房子(p0)的房子列表，如國 num!=0，表示僅取得可讓國家代碼為 num 者居住的房子。

  > - setit(x, y, v): 讓國家代碼為 v 的人民安住在座標為(x, y)的房子。

  > - reduce(x, y, v): 當一個房子(x, y)被入住時，任何能夠看見此房子的其他空房，都可用此方法來減掉已入住這個國家人民(v)的可能性。

  > - allow(x, y, v): 測試這個國家(v)的人民是否能夠居住於座標(x, y)的房子？

  > - read(file): 從一個定義檔(file)中讀入最初到此山谷的國家、人民與居住位置。

## 數獨遊戲定義檔案

你能夠定義數獨遊戲的最初狀況。在文字檔中一行定義一個房子的座標及居住者，格式為x, y, v，如下圖，此專案附有一些已定義好的數獨，置於 [安裝的目錄]/sudoku/data/ 目錄裡。

一個定義範例、最初的外觀以及解出來的外觀
m3.data | 起始的數獨外觀 | 已解的數獨外觀
--- | --- | ---

### 瀏覽

- 索引
- 模組 |
- 下一頁 |
- 上一頁 |
- SudokuStudyLib 1.0 documentation »