朋友們和未來的同事們大家好! 最近,我參加了一個真實專案的測試,並通過了,但只是因為個人原因無法參加RP本身。在像 RP 測驗這樣有趣的問題之後,通常的課程問題就不再那麼有吸引力了,尤其是因為我已經解決了大部分問題。因此,為了不讓自己的才華浪費在繼續學習上,我決定製作一款多人網頁遊戲。其他遊戲連結:
對我來說,井字棋似乎是最簡單的遊戲,因此我決定將任務分解為多個子任務:
第一個演算法是檢查整個字段
- 用於測試遊戲邏輯的控制台應用程式
- 多人遊戲
- 將玩家資料庫附加到控制台應用程式
- 創建前端設計、編寫頁面模板、遊戲介面
- 把它們放在一起
- 場地
- 兩名玩家輪流,一名打十字,第二名打零。這很簡單。
String[][] strings = {{"O", "O", "_"},
{"_", "X", "O"},
{"X", "X", "X"},
for (String [] ss : strings){
for (String s : ss) System.out.print(s + " ");
System.out.println(); //для перевода строки
}
螢幕將顯示:
O O _
_ X O
X X X
但除了顯示之外,我們還有數值的比較,這裡的選擇已經是可能的。你可以比較字串,你可以創建一個特殊的枚舉類別(enum
),但我更喜歡比較數字,只有在螢幕上顯示時才用“X”和“O”替換它們。例如,1 - “X”、2 - “O”、0 - “_”。那麼,如何檢查字段是否存在三重 X 或 O 匹配?
第一個演算法是檢查整個字段
int[][] canvas = {{00, 01, 02},
{10, 11, 12},
{20, 21, 22}}
獲勝組合:
00-01-02, 10-11-12, 20-21-22, 00-10-20, 01-11-21, 02-12-22, 00-11-22, 20-11-02 — всего 8.
透過比較數字進行檢查,但事實證明您每次都需要檢查整個字段,所有 8 種組合。當然,這並不多,這不是搜尋 0 到 10 億範圍內的阿姆斯壯數,這裡幾乎沒有計算,但你仍然想要比檢查整個欄位更優化的東西。我想到的第二個想法是只檢查上一步中標記的單元格,這樣我們仍然可以確定獲勝者,因為我們會知道誰做了這一步。因此,我們不是得到全部 8 種組合,而是只得到 2、3 或 4 種組合,這取決於單元格,請參見圖片: 現在我們需要弄清楚如何確定需要啟動哪種組合?這是我意識到使用二維數組不是很方便。我決定考慮其他選擇。起初我想到了這個字段可以保留為九位數字,例如我們在屏幕上顯示的同一個字段可以這樣寫:220012111,我會用手指解釋它是什麼是...代碼是相同的,1 - “X ”,2 - “O”,0 - “”,這意味著220012111 = “OO__XOXXX”,或者如果在每三個數字之後插入一個換行符並添加空格明晰:
О О _
_ Х О
Х Х Х
又這裡,為了方便儲存,發明了一種展示的裝置,但不方便比較!當我將單元格編號為1-9時,找到了解決方案,然後我想,因為在編程時倒數計時是從0開始並如圖所示編號的。您 沒有註意到任何特殊情況嗎?如果你看上圖,你會清楚地看到,有 2 個組合的解決方案有一個奇數序號,有 4 個組合的解有序號 4,有 3 個組合的解有其餘的。所以我得出的結論是,您需要將競爭環境保持在規則的數字數組中:數字之間的簡單迭代,根據所選演算法進行比較的能力,簡單的輸出到螢幕。至於比較演算法本身。讓我們按順序進行:在所有選項中都會檢查行和列,我們只檢查它們。如果搜尋沒有結果,我們檢查單元格編號是否為偶數/奇數,如果是奇數,那麼我們返回遊戲,進一步檢查沒有意義,如果是偶數,我們檢查該單元格是否位於左對角線,該對角線的數字除以4 餘數為0。如果是,則檢查是否匹配,如果沒有找到匹配,則檢查數字4,如果沒有,則返回遊戲,如果是的,我們進一步檢查代碼並返回檢查最後一個對角線的結果。可能,對於一個沒有準備的人來說,讀完上面這組字母後很難理解,但有人可能會說程式碼本身有很多字母,可以更簡單,我很樂意討論這一點。我們已經整理好了字段,現在我們需要處理兩個輪流的用戶,每個人都有自己的符號,X或O。在第一階段,我們沒有任何多用戶功能,所以最簡單的方法是逐一使用圖標。X 總是先走第一步,O 總是先走第二步,然後 X 再走,依此類推。它要求被檢查(true/false),如果true – 那麼當前玩家是 X,如果false – 那麼 O 並且在每次移動開始時 flag=!flag 它仍然以某種方式從玩家那裡接收關於哪個玩家的信號他們選擇的細胞。在這裡,我們將需要我們難忘的BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
玩家將手機號碼輸入控制台,然後按 Enter 鍵將進行移動。與輸入的數字相對應的儲存格會將其值從 0 變更為 1 或 2,具體取決於複選框的當前狀態,這已在上面的段落中討論過。這就是驗證輸入很重要的地方,這樣當單元格已填滿時,沒有人可以將 X 更改為 O :) 玩家可以在控制台中輸入什麼?
- 空行
- 字母、標點符號、括號...在一個單字中,非數字
- 錯誤的數字 - 負數或超出陣列大小、佔用的儲存格。
Integer.parseInt("2");
它會拋出異常。我們可以透過攔截此異常來提供前兩點的保護。NumberFormatException
對於第三點,我將創建另一個方法來檢查輸入的值,但最正確的方法是將字串請求移動到將執行驗證的單獨方法中,並且它將只傳回一個數字。總而言之,我們創建了一個字段,創建了一個顯示它的方法,創建了一個檢查「該玩家是否贏了一個小時?」的方法,並驗證了輸入的數字。剩下的事情就很少了,檢查平局 - 一個單獨的方法,它運行數組並查找 0,並顯示遊戲結果。就這樣,程式碼已經準備好了,遊戲結果很小,只有一個類,所以強悍的複製貼上者可以在不理解的情況下,將所有內容複製到他們的專案中並自己運行,我自己就是這樣,但現在我盡量不這樣做,也不向任何人推薦它:)祝大家學習JAVA好運!ps 其餘的要點 - 多人遊戲和資料庫稍後會出現,我已經開始學習材料了:)
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
public class GameField {
static int [] canvas = {0,0,0,
0,0,0,
0,0,0};
//012, 345, 678, 036, 147, 258, 048, 246
public static void main(String[] args){
boolean b;
boolean isCurrentX = false;
do {
isCurrentX = !isCurrentX;
drawCanvas();
System.out.println("mark " + (isCurrentX ? "X" : "O"));
int n = getNumber();
canvas[n] = isCurrentX ? 1 : 2;
b = !isGameOver(n);
if (isDraw()){
System.out.println("Draw");
return;
}
} while (b);
drawCanvas();
System.out.println();
System.out.println("The winner is " + (isCurrentX ? "X" : "O") + "!");
}
static int getNumber(){
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
while (true){
try {
int n = Integer.parseInt(reader.readLine());
if (n >= 0 && n < canvas.length && canvas[n]==0){
return n;
}
System.out.println("Choose free cell and enter its number");
} catch (NumberFormatException e) {
System.out.println("Please enter the number");
} catch (IOException e) {
}
}
}
static boolean isGameOver(int n){
// 0 1 2
// 3 4 5
// 6 7 8
//поиск совпадений по горизонтали
int row = n-n%3; //номер строки - проверяем только её
if (canvas[row]==canvas[row+1] &&
canvas[row]==canvas[row+2]) return true;
//поиск совпадений по вертикали
int column = n%3; //номер столбца - проверяем только его
if (canvas[column]==canvas[column+3])
if (canvas[column]==canvas[column+6]) return true;
//мы здесь, значит, первый поиск не положительного результата
//если meaning n находится на одной из граней - возвращаем false
if (n%2!=0) return false;
//проверяем принадлежит ли к левой диагонали meaning
if (n%4==0){
//проверяем есть ли совпадения на левой диагонали
if (canvas[0] == canvas[4] &&
canvas[0] == canvas[8]) return true;
if (n!=4) return false;
}
return canvas[2] == canvas[4] &&
canvas[2] == canvas[6];
}
static void drawCanvas(){
System.out.println(" | | ");
for (int i = 0; i < canvas.length; i++) {
if (i!=0){
if (i%3==0) {
System.out.println();
System.out.println("_____|_____|_____");
System.out.println(" | | ");
}
else
System.out.print("|");
}
if (canvas[i]==0) System.out.print(" " + i + " ");
if (canvas[i]==1) System.out.print(" X ");
if (canvas[i]==2) System.out.print(" O ");
}
System.out.println();
System.out.println(" | | ");
}
public static boolean isDraw() {
for (int n : canvas) if (n==0) return false;
return true;
}
}
GO TO FULL VERSION