自己学習体験として、3x3 TicTacToe ゲームを作成しました。今度は、そのゲームを N x N サイズのボードに拡張したいと考えています。これは、勝利条件を決定する際に問題になります。
元のゲームでは、配列を使用して勝利条件を探しました。
private final int[][] win = new int[][] {
{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, //horizontal
{0, 3, 6}, {1, 4, 7}, {2, 5, 8}, //vertical
{0, 4, 8}, {2, 4, 6} //diagonal
};
そして ActionListener で:
// Check the win array for 3-in-a-line condition.
for(int i = 0; i<=7; i++){
if( b[win[i][0]].getText().equals( b[win[i][1]].getText() ) && // A == B
b[win[i][1]].getText().equals( b[win[i][2]].getText() ) && // B == C
!b[win[i][0]].getText().equals("")){ // Not empty
b[win[i][0]].setBackground(Color.GREEN);
b[win[i][1]].setBackground(Color.GREEN);
b[win[i][2]].setBackground(Color.GREEN);
gameOver = true;
System.out.println("WIN WIN WIN");
ゲームが N x N のサイズに拡大すると、勝利条件を決定するための固定配列を使用できなくなります。
3 つ (またはそれ以上) 並んでいるかどうかを判断するには、何らかの手順が必要です。では、これにどのようにアプローチしますか?配置された場所に最も近いすべての正方形をチェックするよりも、これを行うよりスマートな方法はありますか? (North+South、East+West、N+N、E+E、S+S、W+W、NE+SW、NW+SE、NE+NE、NW+NW、SE+SE、SW+SW) およびすべての PointerExceptions を除外してみてください。
毎回ボード全体をチェックし、for ループのインデックスが範囲外にならないように制御しますか?
どちらのソリューションも、コーディングにとって悪夢のように感じられます。誰でもこの問題に対してよりスマートなアプローチを持っていますか?
参照用にプログラム全体を追加します。
package heniv181;
import javax.swing.JFrame;
import java.awt.GridLayout;
import java.awt.event.*;
import javax.swing.JButton;
import javax.swing.JOptionPane;
/**
* @author Henrik
* Also code by John (john@codecall.net) http://forum.codecall.net/topic/36472-javatutorial-tic-tac-toe/
*
*/
public class TicTacToeBig extends JFrame
implements ActionListener {
private int size = 5;
private JButton[] b = new JButton[size*size];
private int turn = 0;
private final int[][] win = new int[][] {
{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, //horizontal
{0, 3, 6}, {1, 4, 7}, {2, 5, 8}, //virticle
{0, 4, 8}, {2, 4, 6} //diagonal
};
// Constructor
public TicTacToeBig(){
setTitle("Tic-Tac-Toe");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(300, 300);
setLocation(200, 200);
setVisible(true);
setLayout(new GridLayout(size,size));
for(int i=0; i < size*size; i++){
b[i] = new JButton();
b[i].setText("");
b[i].addActionListener(this);
b[i].setActionCommand( Integer.toString(i));
add(b[i]);
}
}
public static void main(String args[]){
TicTacToeBig t = new TicTacToeBig();
}
@Override
public void actionPerformed(ActionEvent ae) {
String sign;
boolean gameOver = false;
// Whos turn is it? X's or O's?
turn++;
if(turn % 2 == 0)
sign="X";
else
sign="O";
// Set X or O on the button pressed.
JButton press = (JButton)ae.getSource();
press.setText(sign);
press.setEnabled(false);
gameOver = checkWin(press);
/* Check the win array for 3-in-a-line condition.
for(int i = 0; i<=7; i++){
if( b[win[i][0]].getText().equals( b[win[i][1]].getText() ) && // A == B
b[win[i][1]].getText().equals( b[win[i][2]].getText() ) && // B == C
!b[win[i][0]].getText().equals("")){ // Not empty
b[win[i][0]].setBackground(Color.GREEN);
b[win[i][1]].setBackground(Color.GREEN);
b[win[i][2]].setBackground(Color.GREEN);
gameOver = true;
System.out.println("WIN WIN WIN");
}
}*/
//End game if winning conditon is true or no more turns.
if(gameOver){
JOptionPane.showMessageDialog(null, "Congratulation!\n" + sign + " have won!");
System.exit(0);
}
else if(turn>=(size*size) ){
JOptionPane.showMessageDialog(null, "To bad!\n No winners. ");
System.exit(0);
}
}
public boolean checkWin(JButton j){
//HHmmmm..........
int index = Integer.valueOf( j.getActionCommand() );
System.out.println(index);
if((index+1) % size == 0 || (index+1) % size == 1)
System.out.println("R or L Edge.");
if(index-size < 0 || index+size > b.length-1)
System.out.println("U or D Edge");
//check right and left
//check if point is on right or left edge
//compare index-1 L
//compare index+1 R
//check up and down
//check if point is on top or bottom edge
//compare index - size D
//compare index + size U
//check diagonals
//check if point is on edge
//compare index - size -1 UL
//compare index - size +1 UR
//compare index + size -1 DL
//compare index + size +1 DR
return false;
}
}