240 likes | 383 Views
Java 網路程式設計. 第 18 章 完整的實例探討. Java 網路應用開發. Java 網路程式設計可以用來開發各種應用系統 在練習開發實例的過程中,會對於各種語法與 API 有比較深刻的認識,所以盡可能地自己運用前面所學到的方法來進行開發,解決困難,這樣應該就能跨過初學者的門檻. BestMove.java. // 記錄最佳的下棋位置,包括對應的欄 (column) 與列 (row) // final class BestMove { int row; int column; int val;
E N D
Java網路程式設計 第18章 完整的實例探討
Java網路應用開發 • Java網路程式設計可以用來開發各種應用系統 • 在練習開發實例的過程中,會對於各種語法與API有比較深刻的認識,所以盡可能地自己運用前面所學到的方法來進行開發,解決困難,這樣應該就能跨過初學者的門檻
BestMove.java // 記錄最佳的下棋位置,包括對應的欄(column)與列(row) // final class BestMove { int row; int column; int val; // val代表目前的盤勢 public BestMove( int v ) { this( v, 0, 0 ); } public BestMove( int v, int r, int c ) { val = v; row = r; column = c; } }
TicTacToe.java class TicTacToe { // 用一些常數值的名稱讓程式碼更容易閱讀 public static final int HUMANOPP = 0; public static final int COMPUTER = 1; public static final int NOLABEL = 2; // 棋盤位置是空的,可以下 public static final int HUMANOPP_WIN = 0; public static final int DRAW = 1; // 平手 public static final int UNKNOWN = 2; // 還未知勝負 public static final int COMPUTER_WIN = 3; public TicTacToe( ) { clearBoard( ); } public int [ ] [ ] getBoard( ) { return board; } // 決定下一步該圈(O)或叉(X) public BestMove TryOneMove( int YouKnowMe ) { int opp; // 敵方 BestMove GiveItATry; // 敵方的最佳對策 int CurrentResult; int bestRow = 0; int bestColumn = 0; int value; // 呼叫CheckResult()看目前的盤勢,假如還未知勝負,才繼續往下執行 if( ( CurrentResult = CheckResult( ) ) != UNKNOWN ) return new BestMove( CurrentResult ); if( YouKnowMe == COMPUTER ) { // 以下棋的人來說,我們會假設他會設法贏 opp = HUMANOPP; value = HUMANOPP_WIN; } else { // 以電腦來說,當然也是會設法贏 opp = COMPUTER; value = COMPUTER_WIN; } // 每一步可能下的棋步都要考慮到 for( int row = 0; row < 3; row++ ) for( int column = 0; column < 3; column++ ) if( squareIsNOLABEL( row, column ) ) // 只有空棋才能下 { // 目前呼叫TryOneMove的那一邊先下一步 place( row, column, YouKnowMe ); // 對手呼叫TryOneMove選擇一步好棋步 GiveItATry = TryOneMove( opp ); // 因為只是預測,假設情況下的棋步要還原 place( row, column, NOLABEL ); // 不管是那一邊,只要呼叫TryOneMove,就要選最佳的棋步 if( YouKnowMe == COMPUTER && GiveItATry.val > value || YouKnowMe == HUMANOPP && GiveItATry.val < value ) { value = GiveItATry.val; bestRow = row; bestColumn = column; } } return new BestMove( value, bestRow, bestColumn ); } // 下手, 同時檢查下的位置是否還是空位, 或是否有超出棋盤範圍 public boolean recordMoveInArray( int YouKnowMe, int row, int column ) { if( row < 0 || row >= 3 || column < 0 || column >= 3 || board[ row ][ column ] != NOLABEL ) return false; board[ row ][ column ] = YouKnowMe; return true; } // 其他相關的有用程序 public void clearBoard( ) { for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) board[ i ][ j ] = NOLABEL; } public boolean boardIsFull( ) { for( int row = 0; row < 3; row++ ) for( int column = 0; column < 3; column++ ) if( board[ row ][ column ] == NOLABEL ) return false; return true; } boolean ResultIsWin( int YouKnowMe ) { int row, column; // 查看是否有整列排成的情況 for( row = 0; row < 3; row++ ) { for( column = 0; column < 3; column++ ) if( board[ row ][ column ] != YouKnowMe ) break; if( column >= 3 ) return true; } // 查看是否有整行排成的情況 for( column = 0; column < 3; column++ ) { for( row = 0; row < 3; row++ ) if( board[ row ][ column ] != YouKnowMe ) break; if( row >= 3 ) return true; } // 查看是否有對角線排成的情況 if( board[ 1 ][ 1 ] == YouKnowMe && board[ 2 ][ 2 ] == YouKnowMe && board[ 0 ][ 0 ] == YouKnowMe ) return true; if( board[ 0 ][ 2 ] == YouKnowMe && board[ 1 ][ 1 ] == YouKnowMe && board[ 2 ][ 0 ] == YouKnowMe ) return true; return false; } private int [ ] [ ] board = new int[ 3 ][ 3 ]; // 下手 private void place( int row, int column, int piece ) { board[ row ][ column ] = piece; } private boolean squareIsNOLABEL( int row, int column ) { return board[ row ][ column ] == NOLABEL; } // 確認目前的戰況 private int CheckResult( ) { return ResultIsWin( COMPUTER ) ? COMPUTER_WIN : ResultIsWin( HUMANOPP ) ? HUMANOPP_WIN : boardIsFull( )? DRAW : UNKNOWN; } }
TestTicTacToe.java import java.awt.*; import java.awt.event.*; public class TestTicTacToe extends Frame implements WindowListener, ActionListener { // 啟動棋盤, 等待使用者點按 public void init( ) { setLayout( new GridLayout( 3, 3 ) ); for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) { BookKeepArray[ i ][ j ] = new Button( ); add( BookKeepArray[ i ][ j ] ); BookKeepArray[ i ][ j ].addActionListener( this ); BookKeepArray[ i ][ j ].setFont(new Font("Serif", Font.BOLD, 72)); } addWindowListener( this ); newBoard( ); } public TestTicTacToe( ) { init( ); } // 重玩 ! 新建一個TicTacToe的案例, 清除按鈕上的標籤 public void newBoard( ) { t = new TicTacToe( ); for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) { BookKeepArray[ i ][ j ].setLabel( "" ); // 無標籤 BookKeepArray[ i ][ j ].setEnabled( true ); // 可點按下棋步 } } private int KeepGameInteresting = 0; // 為電腦選一個棋步 // 若是電腦先下,利用KeepGameInteresting隨機選擇棋步,增加遊戲的變化 // 否則就要呼叫TryOneMove來選個好棋步 public void doComputerMove( boolean predictToWin ) { BestMove ComputerMove; if( predictToWin ) ComputerMove = t.TryOneMove( TicTacToe.COMPUTER ); else { ComputerMove = new BestMove( 0, KeepGameInteresting % 3, KeepGameInteresting / 3 ); KeepGameInteresting = ( KeepGameInteresting + 1 ) % 9; } System.out.println( " 電腦選的列的位置 = " + ComputerMove.row + " 電腦選的行的位置 = " + ComputerMove.column ); BookKeepArray[ ComputerMove.row ][ ComputerMove.column ].setLabel( computerYouKnowMe ); BookKeepArray[ ComputerMove.row ][ ComputerMove.column ].setEnabled( false ); t.recordMoveInArray( TicTacToe.COMPUTER, ComputerMove.row, ComputerMove.column ); } // 遊戲結束時(注意結束的條件), 開始另一盤, 圈叉對調 public boolean GameOverRest( boolean condition, String message, boolean ComputerMoves ) { if( condition ) { System.out.println( message ); System.out.println( "重新開始新的一盤遊戲!" ); newBoard( ); if( ComputerMoves ) { System.out.println( "電腦先下囉!" ); computerYouKnowMe = "X"; HUMANOPPYouKnowMe = "O"; doComputerMove( false ); } else { HUMANOPPYouKnowMe = "X"; computerYouKnowMe = "O"; System.out.println( "您先下吧!" ); } } return condition; } // WindowListener介面的實作 public void windowClosing( WindowEvent event ) { System.exit( 0 ); } public void windowClosed( WindowEvent event ) { } public void windowDeiconified( WindowEvent event ) { } public void windowIconified( WindowEvent event ) { } public void windowActivated( WindowEvent event ) { } public void windowDeactivated( WindowEvent event ) { } public void windowOpened( WindowEvent event ) { } // 處理按鈕點選(button click)事件,注意按錯時的處理方式 public void actionPerformed( ActionEvent evt ) { if( evt.getSource( ) instanceof Button ) { // 棋手每按一下棋盤,就要進行處理 ( (Button)evt.getSource( ) ).setLabel( HUMANOPPYouKnowMe ); // 外觀改變 ( (Button)evt.getSource( ) ).setEnabled( false ); // 已下棋步,不能再按 for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) if( evt.getSource( ) == BookKeepArray[ i ][ j ] ) // 在陣列資料結構上記載棋步 t.recordMoveInArray( TicTacToe.HUMANOPP, i, j ); // 在棋手下完後,檢查勝負,棋盤滿而無勝負就是平手(Draw) if( GameOverRest( t.boardIsFull( ), "DRAW", true ) ) return; // 換電腦下 doComputerMove( true ); // 檢查勝負 GameOverRest( t.ResultIsWin( TicTacToe.COMPUTER ), "嘿!我贏了", true ); // 檢查是否平手(Draw) GameOverRest( t.boardIsFull( ), "DRAW", false ); return; // 等棋手下棋 } } // 主程式, 建立新棋盤,開始玩! public static void main( String [ ] args ) { Frame f = new TestTicTacToe( ); f.pack( ); f.show( ); // 啟始之後,等棋手下棋 } private Button [ ][ ] BookKeepArray = new Button[ 3 ][ 3 ];//開始時棋盤是空的 private TicTacToe t; private String computerYouKnowMe = "O"; private String HUMANOPPYouKnowMe = "X"; }
網路遊戲 • 圈圈叉叉(Tic Tac Toe)的遊戲 • 單機版的設計 • 網路版的設計
TicTacToe類別裡定義的TryOneMove • 在目前的盤勢下找出最佳的棋步 • 預測與思考
網路版設計上要注意的事項 • 注意TestTicTacToe與TestTicTacToe1兩個程式在通訊時所使用的host address與port number的分配。 • 棋步的傳送與處理細節。 • 發現平手或是分出勝負時重新開始的處理方式。
網路版TicTacToe.java class TicTacToe { // 用一些常數值的名稱讓程式碼更容易閱讀 public static final int HUMANOPP = 0; public static final int COMPUTER = 1; public static final int NOLABEL = 2; // 棋盤位置是空的,可以下 public static final int HUMANOPP_WIN = 0; public static final int DRAW = 1; // 平手 public static final int UNKNOWN = 2; // 還未知勝負 public static final int COMPUTER_WIN = 3; public TicTacToe( ) { clearBoard( ); } public int [ ] [ ] getBoard( ) { return board; } // 下手, 同時檢查下的位置是否還是空位, 或是否有超出棋盤範圍 public boolean recordMoveInArray( int YouKnowMe, int row, int column ) { if( row < 0 || row >= 3 || column < 0 || column >= 3 || board[ row ][ column ] != NOLABEL ) return false; board[ row ][ column ] = YouKnowMe; return true; } // 其他相關的有用程序 public void clearBoard( ) { for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) board[ i ][ j ] = NOLABEL; } public boolean boardIsFull( ) { for( int row = 0; row < 3; row++ ) for( int column = 0; column < 3; column++ ) if( board[ row ][ column ] == NOLABEL ) return false; return true; } boolean ResultIsWin( int YouKnowMe ) { int row, column; // 查看是否有整列排成的情況 for( row = 0; row < 3; row++ ) { for( column = 0; column < 3; column++ ) if( board[ row ][ column ] != YouKnowMe ) break; if( column >= 3 ) return true; } // 查看是否有整行排成的情況 for( column = 0; column < 3; column++ ) { for( row = 0; row < 3; row++ ) if( board[ row ][ column ] != YouKnowMe ) break; if( row >= 3 ) return true; } // 查看是否有對角線排成的情況 if( board[ 1 ][ 1 ] == YouKnowMe && board[ 2 ][ 2 ] == YouKnowMe && board[ 0 ][ 0 ] == YouKnowMe ) return true; if( board[ 0 ][ 2 ] == YouKnowMe && board[ 1 ][ 1 ] == YouKnowMe && board[ 2 ][ 0 ] == YouKnowMe ) return true; return false; } private int [ ] [ ] board = new int[ 3 ][ 3 ]; // 下手 private void place( int row, int column, int piece ) { board[ row ][ column ] = piece; } private boolean squareIsNOLABEL( int row, int column ) { return board[ row ][ column ] == NOLABEL; } // 確認目前的戰況 private int CheckResult( ) { return ResultIsWin( COMPUTER ) ? COMPUTER_WIN : ResultIsWin( HUMANOPP ) ? HUMANOPP_WIN : boardIsFull( )? DRAW : UNKNOWN; } }
TestTicTacToe .java import java.awt.*; import java.awt.event.*; import java.io.*; // new import java.net.*; // new import java.util.StringTokenizer; // new // 我們先把TestTicTacToe當成Human這一邊的 public class TestTicTacToe extends Frame implements WindowListener, ActionListener { int portNo; InetAddress addr; DatagramSocket ssocket; DatagramSocket rsocket; // 啟動棋盤, 等待使用者點按 public void init( ) { this.portNo =5555; System.out.print("Please input the IP address of destination :"); BufferedReader uip= new BufferedReader(new InputStreamReader(System.in)); try{ String ServerIP=uip.readLine(); this.addr=InetAddress.getByName(ServerIP); this.ssocket=new DatagramSocket(1700); this.rsocket=new DatagramSocket(1800); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } setLayout( new GridLayout( 3, 3 ) ); for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) { BookKeepArray[ i ][ j ] = new Button( ); add( BookKeepArray[ i ][ j ] ); BookKeepArray[ i ][ j ].addActionListener( this ); BookKeepArray[ i ][ j ].setFont(new Font("Serif", Font.BOLD, 100)); } addWindowListener( this ); newBoard( ); } public TestTicTacToe(String whoami ) { super("TestTicTacToe (was human): "+whoami); init( ); } // 重玩 ! 新建一個TicTacToe的案例, 清除按鈕上的標籤 public void newBoard( ) { t = new TicTacToe( ); for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) { BookKeepArray[ i ][ j ].setLabel( "" ); // 無標籤 BookKeepArray[ i ][ j ].setEnabled( true ); // 可點按下棋步 } } private int KeepGameInteresting = 0; // 遊戲結束時(注意結束的條件), 開始另一盤, 圈叉不對調 public boolean GameOverRest( boolean condition, String message, boolean ComputerMoves ) { if( condition ) { System.out.println( message ); System.out.println( "重新開始新的一盤遊戲!" ); newBoard( ); if( ComputerMoves ) { System.out.println( "先下囉!" ); } else { System.out.println( "等對方下吧!" ); byte buffer1[]=new byte[100]; try { DatagramPacket packet1=new DatagramPacket(buffer1,100,this.addr,1600); System.out.println("wait on receiving ...等對方下!"); this.rsocket.receive(packet1); String msg1=new String(buffer1,0,packet1.getLength()); System.out.println("收到下面的訊息 : " + msg1); StringTokenizer stok1 = new StringTokenizer(msg1,","); int dontcare = Integer.parseInt(stok1.nextToken()); int x1=Integer.parseInt(stok1.nextToken()); int y1=Integer.parseInt(stok1.nextToken()); BookKeepArray[x1][y1].setLabel(computerYouKnowMe); BookKeepArray[x1][y1].setEnabled(false); t.recordMoveInArray( TicTacToe.COMPUTER, x1, y1 ); }catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }// end } } return condition; } // WindowListener介面的實作 public void windowClosing( WindowEvent event ) { System.exit( 0 ); } public void windowClosed( WindowEvent event ) { } public void windowDeiconified( WindowEvent event ) { } public void windowIconified( WindowEvent event ) { } public void windowActivated( WindowEvent event ) { } public void windowDeactivated( WindowEvent event ) { } public void windowOpened( WindowEvent event ) { } // 處理按鈕點選(button click)事件,注意按錯時的處理方式 public void actionPerformed( ActionEvent evt ) { if( evt.getSource( ) instanceof Button ) { // 棋手每按一下棋盤,就要進行處理 ( (Button)evt.getSource( ) ).setLabel( HUMANOPPYouKnowMe ); // 外觀改變 ( (Button)evt.getSource( ) ).setEnabled( false ); // 已下棋步,不能再按 int i=0; int j=0; int ii=0, jj=0; for( i = 0; i < 3; i++ ) for( j = 0; j < 3; j++ ) if( evt.getSource( ) == BookKeepArray[ i ][ j ] ) // 在陣列資料結構上記載棋步 { t.recordMoveInArray( TicTacToe.HUMANOPP, i, j ); ii=i; jj=j; }; System.out.println("TestTicTacToe : (i,j) "+ii+" "+jj); // 開始準備傳送棋步 Integer oi = new Integer(ii); Integer oj = new Integer(jj); Integer oid = new Integer(TicTacToe.HUMANOPP); String dataOut = oid.toString()+","+oi.toString()+","+oj.toString(); int oLength=dataOut.length(); byte buffer[]=new byte[oLength]; System.out.println(dataOut); buffer=dataOut.getBytes(); try { DatagramPacket packet=new DatagramPacket(buffer,oLength,this.addr,1600); System.out.println(this.portNo); this.ssocket.send(packet); System.out.println("sent ..., check!"); // 在棋手下完後,檢查勝負,棋盤滿而無勝負就是平手(Draw) if (GameOverRest( t.ResultIsWin( TicTacToe.HUMANOPP ), "嘿!我贏了", true )) return; if( GameOverRest( t.boardIsFull( ), "DRAW", true ) ) return; // 換對方下(即之前的computer) System.out.println("human wait on receiving ..."); DatagramPacket packet1=new DatagramPacket(buffer,oLength,this.addr,1800); this.rsocket.receive(packet1); String msg=new String(buffer,0,packet1.getLength()); System.out.println("收到下面的訊息 : " + msg); StringTokenizer stok = new StringTokenizer(msg,","); int dontcare = Integer.parseInt(stok.nextToken()); int x=Integer.parseInt(stok.nextToken()); int y=Integer.parseInt(stok.nextToken()); BookKeepArray[x][y].setLabel(computerYouKnowMe); BookKeepArray[x][y].setEnabled(false); t.recordMoveInArray( TicTacToe.COMPUTER, x, y ); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 檢查勝負 GameOverRest( t.ResultIsWin( TicTacToe.COMPUTER ), "嘿!我輸了", false ); // 檢查是否平手(Draw) GameOverRest( t.boardIsFull( ), "DRAW", true ); return; // 等棋手下棋 } } // 主程式, 建立新棋盤,開始玩! public static void main( String [ ] args ) { Frame f = new TestTicTacToe("使用X"); f.pack( ); f.show( ); // 啟始之後,等棋手下棋 } private Button [ ][ ] BookKeepArray = new Button[ 3 ][ 3 ];//開始時棋盤是空的 private TicTacToe t; private String computerYouKnowMe = "O"; private String HUMANOPPYouKnowMe = "X"; }
TestTicTacToe1.java import java.awt.*; import java.awt.event.*; import java.io.*; // new import java.net.*; // new import java.util.StringTokenizer; // new // 我們先把TestTicTacToe1當成Computer這一邊的 public class TestTicTacToe1 extends Frame implements WindowListener, ActionListener { int portNo; InetAddress addr; DatagramSocket ssocket; DatagramSocket rsocket; // 啟動棋盤, 等待使用者點按 public void init( ) { this.portNo =5556; System.out.print("Please input the IP address of destination :"); BufferedReader uip= new BufferedReader(new InputStreamReader(System.in)); try{ String ServerIP=uip.readLine(); this.addr=InetAddress.getByName(ServerIP); this.ssocket=new DatagramSocket(1500); this.rsocket=new DatagramSocket(1600); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } setLayout( new GridLayout( 3, 3 ) ); for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) { BookKeepArray[ i ][ j ] = new Button( ); add( BookKeepArray[ i ][ j ] ); BookKeepArray[ i ][ j ].addActionListener( this ); BookKeepArray[ i ][ j ].setFont(new Font("Serif", Font.BOLD, 100)); } addWindowListener( this ); newBoard( ); //_____________________________________________________ // Computer這一邊一開始先等human下! byte buffer1[]=new byte[100]; try { DatagramPacket packet1=new DatagramPacket(buffer1,100,this.addr,1600); System.out.println("wait on receiving ...等對方下!"); this.rsocket.receive(packet1); String msg1=new String(buffer1,0,packet1.getLength()); System.out.println("收到下面的訊息 : " + msg1); StringTokenizer stok1 = new StringTokenizer(msg1,","); int dontcare = Integer.parseInt(stok1.nextToken()); int x1=Integer.parseInt(stok1.nextToken()); int y1=Integer.parseInt(stok1.nextToken()); BookKeepArray[x1][y1].setLabel(HUMANOPPYouKnowMe); BookKeepArray[x1][y1].setEnabled(false); t.recordMoveInArray( TicTacToe.HUMANOPP, x1, y1 ); }catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } //_____________________________________________________ } public TestTicTacToe1( String whoami) { super("TestTicTacToe1 (was computer: " +whoami); init( ); } // 重玩 ! 新建一個TicTacToe的案例, 清除按鈕上的標籤 public void newBoard( ) { t = new TicTacToe( ); for( int i = 0; i < 3; i++ ) for( int j = 0; j < 3; j++ ) { BookKeepArray[ i ][ j ].setLabel( "" ); // 無標籤 BookKeepArray[ i ][ j ].setEnabled( true ); // 可點按下棋步 } } private int KeepGameInteresting = 0; // 遊戲結束時(注意結束的條件), 開始另一盤, 圈叉不對調 // 平手時由human先下, 否則由贏的先下 public boolean GameOverRest( boolean condition, String message, boolean ComputerMoves ) { if( condition ) { System.out.println( message ); System.out.println( "重新開始新的一盤遊戲!" ); newBoard( ); if( ComputerMoves ) { System.out.println( "先下囉!" ); } else { System.out.println( "等對方先下吧!" ); byte buffer2[]=new byte[100]; try { DatagramPacket packet2=new DatagramPacket(buffer2,100,this.addr,1600); System.out.println("wait on receiving ...等對方下!"); this.rsocket.receive(packet2); String msg2=new String(buffer2,0,packet2.getLength()); System.out.println("收到下面的訊息 : " + msg2); StringTokenizer stok2 = new StringTokenizer(msg2,","); int dontcare2 = Integer.parseInt(stok2.nextToken()); int x2=Integer.parseInt(stok2.nextToken()); int y2=Integer.parseInt(stok2.nextToken()); BookKeepArray[x2][y2].setLabel(HUMANOPPYouKnowMe); BookKeepArray[x2][y2].setEnabled(false); t.recordMoveInArray( TicTacToe.HUMANOPP, x2, y2 ); }catch (SocketException ex) { ex.printStackTrace(); } catch (IOException ex) { ex.printStackTrace(); } } } return condition; } // WindowListener介面的實作 public void windowClosing( WindowEvent event ) { System.exit( 0 ); } public void windowClosed( WindowEvent event ) { } public void windowDeiconified( WindowEvent event ) { } public void windowIconified( WindowEvent event ) { } public void windowActivated( WindowEvent event ) { } public void windowDeactivated( WindowEvent event ) { } public void windowOpened( WindowEvent event ) { } // 處理按鈕點選(button click)事件,注意按錯時的處理方式 public void actionPerformed( ActionEvent evt ) { if( evt.getSource( ) instanceof Button ) { // 棋手每按一下棋盤,就要進行處理 ( (Button)evt.getSource( ) ).setLabel( computerYouKnowMe ); // 外觀改變 ( (Button)evt.getSource( ) ).setEnabled( false ); // 已下棋步,不能再按 int i=0; int j=0; int ii=0, jj=0; for( i = 0; i < 3; i++ ) for( j = 0; j < 3; j++ ) if( evt.getSource( ) == BookKeepArray[ i ][ j ] ) // 在陣列資料結構上記載棋步 { t.recordMoveInArray( TicTacToe.COMPUTER, i, j ); ii=i; jj=j;}; System.out.println("TestTicTacToe1 : (i,j) "+ii+" "+jj); Integer oi = new Integer(ii); Integer oj = new Integer(jj); Integer oid = new Integer(TicTacToe.COMPUTER); String dataOut = oid.toString()+","+oi.toString()+","+oj.toString(); int oLength=dataOut.length(); byte buffer[]=new byte[oLength]; System.out.println(dataOut); buffer=dataOut.getBytes(); try { DatagramPacket packet=new DatagramPacket(buffer,oLength,this.addr,1800); System.out.println(this.portNo); this.ssocket.send(packet); System.out.println("sent ..., check!"); // 在棋手下完後,檢查勝負,棋盤滿而無勝負就是平手(Draw) if (GameOverRest( t.ResultIsWin( TicTacToe.COMPUTER ), "嘿!我贏了", true )) return; if( GameOverRest( t.boardIsFull( ), "DRAW", false ) ) return; // 換Human下 DatagramPacket packet1=new DatagramPacket(buffer,oLength,this.addr,1600); System.out.println("comp wait receiving ..."); this.rsocket.receive(packet1); String msg=new String(buffer,0,packet1.getLength()); System.out.println("收到下面的訊息 : " + msg); StringTokenizer stok = new StringTokenizer(msg,","); int dontcare = Integer.parseInt(stok.nextToken()); int x=Integer.parseInt(stok.nextToken()); int y=Integer.parseInt(stok.nextToken()); BookKeepArray[x][y].setLabel(HUMANOPPYouKnowMe); BookKeepArray[x][y].setEnabled(false); t.recordMoveInArray( TicTacToe.HUMANOPP, x, y ); } catch (SocketException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } // 檢查勝負 GameOverRest( t.ResultIsWin( TicTacToe.HUMANOPP ), "嘿!我輸了", false ); // 檢查是否平手(Draw) GameOverRest( t.boardIsFull( ), "DRAW", false ); return; // 等棋手下棋 } } // 主程式, 建立新棋盤,開始玩! public static void main( String [ ] args ) { Frame f = new TestTicTacToe1("使用O" ); f.pack( ); f.show( ); // 啟始之後,等棋手下棋 } private Button [ ][ ] BookKeepArray = new Button[ 3 ][ 3 ];//開始時棋盤是空的 private TicTacToe t; private String computerYouKnowMe = "O"; private String HUMANOPPYouKnowMe = "X"; }
Hypercube • Hypercube是一種交換式的多電腦(Switched multi-computer)架構 • 各頂點代表一個CPU,兩個立方體對應的頂點彼此相連,CPU有運算的能力,連接的頂點之間則可互相交換訊息
d維度(d-dimensional)的hypercube • 在d維度(d-dimensional)的hypercube network中,每個節點會連上每個維度中的一個節點,通常會以d個二進位元來表示一個d維度hypercube中的節點 • 以3-dimensional的hypercube為例,含有8個節點
導入平行演算法(parallel algorithms)的概念 • 在hypercube中執行quicksort運算的方式 • divide-and-conquer類型的排序演算法 • quicksort(list, start, end) • { • if (start<end) { • partition(list, start, end, pivotIndex); • quicksort(list, start, pivotIndex-1); // 遞迴呼叫 • quicksort(list, pivotIndex+1, end); // 遞迴呼叫 • } • }
hypercube中進行paralle quicksort時各階段的運算與溝通