亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

連接4檢查獲勝算法

連接4檢查獲勝算法

我知道有很多關于Connect 4 Check獲勝的問題。問題在于大多數其他算法使我的程序出現運行時錯誤,因為它們嘗試訪問數組之外的索引。我的算法是這樣的:private int checkWin(int[][] gridTable,int rowNum,int colNum, int maxRow, int maxCol) {//  For checking whether any win or lose condition is reached. Returns 1 if win or lose is reached. else returns 0//  gridTable[][] is the game matrix(can be any number of rows and columns between 4 and 40)//  colNum is the column number where the last token was placed//  rowNum is the row number where the last token was placed//  maxRow is the number of rows in my grid//  maxCol is the number of columns in my gridint player = gridTable[rowNum][colNum]; //player IDint count=0;// Horizontal checkfor (int i=0;i<maxCol;i++){    if (gridTable[rowNum][i]==player)        count++;    else        count=0;    if (count>=4)        return 1;}//Vertical checkfor (int i=0;i<maxRow;i++){    if (gridTable[i][colNum]==player)        count++;    else        count=0;    if (count>=4)        return 1;} count=0;// 4 in a row diagonallyfor(int i=colNum+1,j=rowNum+1;i<maxRow && j<maxCol;i++,j++) {     if(gridTable[j][i]!=player)    {        count=1;        break;            }    count++;}// 4 in a row diagonallyfor(int i=colNum-1,j=rowNum-1;i>=0 && j>=0;i--,j--) {     if(gridTable[j][i]!=player)    {        count=1;        break;            }    count++;}// 4 in a row diagonallyfor(int i=colNum+1,j=rowNum-1;i<maxRow && j>=0;i++,j--) {     if(gridTable[j][i]!=player)    {        count=1;        break;            }    count++;}for(int i=colNum-1,j=rowNum+1;i>=0 && j<maxCol;i--,j++) { // 4 in a row diagonally    if(gridTable[j][i]!=player)    {        count=1;        break;            }    count++;}if(count>=4)    return 1;return 0;}count是用于檢查是否等于或大于4的勝利的變量,這意味著它們應為同一玩家的4個或更多連續標記。問題:有時該方法檢查獲勝的順序是否為4個令牌,而有時不檢查獲勝的順序為4個令牌。
查看完整描述

3 回答

?
鳳凰求蠱

TA貢獻1825條經驗 獲得超4個贊

看起來您的代碼對于水平和垂直情況都是正確的。棘手的部分是對角線情況。


讓我們嘗試一下圖片:


在此處輸入圖片說明


對于綠線,您的起始行位置為0 ... maxRow-4。該列將為0 ... startingRow-


偽代碼:


// top-left to bottom-right - green diagonals

for( rowStart = 0; rowStart < rowMax - 4; rowStart++){

    count = 0;

    int row, col;

    for( row = rowStart, col = 0; row < rowMax && col < colMax; row++, col++ ){

        if(gridTable[row][col] == player){

            count++;

            if(count >= 4) return 1;

        }

        else {

            count = 0;

        }

    }

}


// top-left to bottom-right - red diagonals

for( colStart = 1; colStart < colMax - 4; rowStart++){

    count = 0;

    int row, col;

    for( row = 0, col = colStart; row < rowMax && col < colMax; row++, col++ ){

        if(gridTable[row][col] == player){

            count++;

            if(count >= 4) return 1;

        }

        else {

            count = 0;

        }

    }

}

對于對角線的另一種方式(從左下到右上),您可以執行類似的操作。


查看完整回答
反對 回復 2019-10-21
?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

由于某種原因,我不喜歡計數器,所以我這樣做(它適用于不同尺寸的電路板)。


public boolean areFourConnected(int player){


    // horizontalCheck 

    for (int j = 0; j<getHeight()-3 ; j++ ){

        for (int i = 0; i<getWidth(); i++){

            if (this.board[i][j] == player && this.board[i][j+1] == player && this.board[i][j+2] == player && this.board[i][j+3] == player){

                return true;

            }           

        }

    }

    // verticalCheck

    for (int i = 0; i<getWidth()-3 ; i++ ){

        for (int j = 0; j<this.getHeight(); j++){

            if (this.board[i][j] == player && this.board[i+1][j] == player && this.board[i+2][j] == player && this.board[i+3][j] == player){

                return true;

            }           

        }

    }

    // ascendingDiagonalCheck 

    for (int i=3; i<getWidth(); i++){

        for (int j=0; j<getHeight()-3; j++){

            if (this.board[i][j] == player && this.board[i-1][j+1] == player && this.board[i-2][j+2] == player && this.board[i-3][j+3] == player)

                return true;

        }

    }

    // descendingDiagonalCheck

    for (int i=3; i<getWidth(); i++){

        for (int j=3; j<getHeight(); j++){

            if (this.board[i][j] == player && this.board[i-1][j-1] == player && this.board[i-2][j-2] == player && this.board[i-3][j-3] == player)

                return true;

        }

    }

    return false;

}


查看完整回答
反對 回復 2019-10-21
?
Helenr

TA貢獻1780條經驗 獲得超4個贊

因此,瀏覽完您的代碼后,似乎對角線檢查只能在一個方向上獲勝(如果我在最低行和最低列中添加標記,會發生什么情況?)


而是,基本檢查算法始終是相同的過程,而不管您要檢查的方向是什么。


您需要一個起點(x / y)和x / y增量(運動方向)。您可以將其歸納為一個方法...


public boolean didWin(int[][] grid, int check, int row, int col, int rowDelta, int colDelta) {


    boolean win = true;

    for (int count = 0; count < 4; count++) {

        if (row < ROWS && row >= 0 && col < COLUMNS && col >= 0) {

            int test = grid[row][col];

            if (test != check) {

                win = false;

                break;

            }

        }

        row += rowDelta;

        col += colDelta;

    }

    return win;


}

基本上,您可以從四個方向檢查,也可以向后檢查


所以,如果我們要使用類似...


int[][] gridTable = new int[ROWS][COLUMNS];


gridTable[ROWS - 1][3] = 1;

gridTable[ROWS - 2][3] = 1;

gridTable[ROWS - 3][3] = 1;

gridTable[ROWS - 4][3] = 1;


System.out.println("Vertical");


System.out.println(didWin(gridTable, 1, ROWS - 4, 3, 1, 0) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, ROWS - 1, 3, -1, 0) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, 0, 3, 1, 0) ? "Win" : "Lose");


gridTable = new int[ROWS][COLUMNS];

gridTable[3][1] = 1;

gridTable[3][2] = 1;

gridTable[3][3] = 1;

gridTable[3][4] = 1;


System.out.println("");

System.out.println("Horizontal");

System.out.println(didWin(gridTable, 1, 3, 1, 0, 1) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, 3, 4, 0, -1) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, 3, 0, 0, 1) ? "Win" : "Lose");


gridTable = new int[ROWS][COLUMNS];

gridTable[0][1] = 1;

gridTable[1][2] = 1;

gridTable[2][3] = 1;

gridTable[3][4] = 1;


System.out.println("");

System.out.println("Diag");

System.out.println(didWin(gridTable, 1, 0, 1, 1, 1) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, 3, 4, -1, -1) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, 1, 2, 1, 1) ? "Win" : "Lose");

哪個輸出...


Vertical

Win

Win

Lose


Horizontal

Win

Win

Lose


Diag

Win

Win

Lose

現在,您可以將其總結為...


public boolean didWin(int[][] grid, int check, int row, int col) {

    return didWin(grid, check, row, col, 1, 0) ||

                    didWin(grid, check, row, col, -1, 0) ||

                    didWin(grid, check, row, col, 0, 1) ||

                    didWin(grid, check, row, col, 0, -1) ||

                    didWin(grid, check, row, col, 1, 1) ||

                    didWin(grid, check, row, col, -1, -1) ||

                    didWin(grid, check, row, col, -1, 1) ||

                    didWin(grid, check, row, col, 1, -1);

}

因此,使用類似...


int[][] gridTable = new int[ROWS][COLUMNS];


gridTable[ROWS - 1][3] = 1;

gridTable[ROWS - 2][3] = 1;

gridTable[ROWS - 3][3] = 1;

gridTable[ROWS - 4][3] = 1;


System.out.println("Vertical");


System.out.println(didWin(gridTable, 1, ROWS - 1, 3) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, ROWS - 4, 3) ? "Win" : "Lose");


gridTable = new int[ROWS][COLUMNS];

gridTable[3][1] = 1;

gridTable[3][2] = 1;

gridTable[3][3] = 1;

gridTable[3][4] = 1;


System.out.println("");

System.out.println("Horizontal");

System.out.println(didWin(gridTable, 1, 3, 1) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, 3, 4) ? "Win" : "Lose");


gridTable = new int[ROWS][COLUMNS];

gridTable[0][1] = 1;

gridTable[1][2] = 1;

gridTable[2][3] = 1;

gridTable[3][4] = 1;


System.out.println("");

System.out.println("Diag");

System.out.println(didWin(gridTable, 1, 0, 1) ? "Win" : "Lose");

System.out.println(didWin(gridTable, 1, 3, 4) ? "Win" : "Lose");

哪個打印出類似...


Vertical

Win

Win


Horizontal

Win

Win


Diag

Win

Win

我要補充一點,這種方法僅在您連續提供4個芯片的正確開始時才有效。例如didWin(gridTable,1,3,3)將為水平檢查提供false而不是true,因為循環只能檢查一個方向。


這樣做的目的不是提供“完整的,即裝即用的”解決方案,而是提供一個可以開發更廣泛的解決方案的概念(我是說,我討厭人們實際上不得不思考;)。我還基于以下想法設計了解決方案:OP將知道最后一塊放置在哪里,即起點;)


通過didWin稍微修改一下方法,就可以從任何點檢查n逐個n網格...


public boolean didWin(int[][] grid, int check, int row, int col, int rowDelta, int colDelta) {

    boolean match = false;

    int matches = 0;

    while (row < ROWS && row >= 0 && col < COLUMNS && col >= 0) {

        int test = grid[row][col];

        if (test != check && match) {

            break;

        } else if (test == check) {

            match = true;

            matches++;

        }

        row += rowDelta;

        col += colDelta;

    }

    return matches == 4;

}

所以,我用...


public static final int ROWS = 8;

public static final int COLUMNS = 8;

//...

int[][] gridTable = new int[ROWS][COLUMNS];


gridTable[ROWS - 1][3] = 1;

gridTable[ROWS - 2][3] = 1;

gridTable[ROWS - 3][3] = 1;

gridTable[ROWS - 4][3] = 1;

for (int[] row : gridTable) {

    StringJoiner sj = new StringJoiner("|", "|", "|");

    for (int col : row) {

        sj.add(Integer.toString(col));

    }

    System.out.println(sj);

}

System.out.println(didWin(gridTable, 1, 3, 3));

并能夠使其正常工作。有時答案不是一個完整的解決方案,而是將某人帶到新地方的想法的種子;)


我將進一步增強功能,包括提供預期的連接件數量,但是我很確定這是我真的不需要演示的增強功能;)


查看完整回答
反對 回復 2019-10-21
  • 3 回答
  • 0 關注
  • 652 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號