|
|
1) Memory Server starten Memory Server starten (TcpMemory.java) |
||
Memory Plaer starten (TcpMemory.java) In der ersten Dialogbox muss die gleiche SessionID, wie beim Memory Server eingegeben werden.
|
||
In der zweiten Dialogbox gibt jeder Spieler sein Namen ein. Sobald die TCP/IP-Verbindung aufgebaut wurde, kann das Spiel beginnen.
Zum Testn kann die Applikation auch zweimal auf dem gleichen Computer gestartet werden. |
4. Spielregeln Das Spiel besteht aus 8 Kartenpaare. Die Rückseiten der Karten sind grau. Der aktive Spieler kehrt jeweils mit einem Mausklick zwei Karten um. Wenn sie gleich sind, erhält er 1 Punkt und kann noch einmal spielen, sonst kommt der zweite Spieler zu Zug. Wer am Schluss mehr Punkte hat, gewinnt. |
Programmcode für lokale Bearbeitung downloaden: TcpMemory.zip
Erklärungen zum Programmcode finden Sie unter www.aplu.ch/TcpJLib
// TcpMemoryServer.java import ch.aplu.tcp.*; import ch.aplu.util.*; import java.util.*; public class TcpMemoryServer extends TcpBridge implements TcpBridgeListener { private static String sessionID; private final static String myName = "MemoryServer"; private Vector<String> players = new Vector<String>(); private int nbCells = 16; // Must be even private int[] state = new int[nbCells]; private static Console c = new Console(); static { c.print("Enter a unique session ID: "); sessionID = c.readLine(); } // Protocol tags private interface Command { int STATUS = 0; int INIT = 1; int SHOW = 2; int HIDE = 3; int SCORE = 4; int NAME_IN_USE = 5; int TOO_MANY_PLAYERS = 6; int PLAYER_NAMES = 7; int WAIT_REMOTE_CONNECT = 8; int REMOTE_MOVE = 9; int LOCAL_MOVE = 10; int END_OF_GAME = 11; } public TcpMemoryServer() { super(sessionID, myName); addTcpBridgeListener(this); c.println("Connecting to relay"); ArrayList<String> connectList = connectToRelay(6000); if (connectList.isEmpty()) errorQuit("Connection failed"); if (!connectList.get(0).equals(myName)) errorQuit("Only one instance of server allowed"); c.println("Connection established. Service enabled."); } private void errorQuit(String msg) { c.println(msg); System.exit(1); } private void dealingOut() { ArrayList<Integer> numbers = new ArrayList<Integer>(); for (int i = 0; i < nbCells; i++) numbers.add(i); // Now take out one by one at arbitrary location and put it into state int k = 0; while (!numbers.isEmpty()) { int index = (int)(Math.random() * numbers.size()); state[k] = numbers.get(index); numbers.remove(index); k++; } } public void notifyRelayConnection(boolean connected) { } public void notifyAgentConnection(String agentName, boolean connected) { if (connected) { c.println("Agent connecting. Name: " + agentName); if (players.size() < 2) players.add(agentName); else { c.println("Reporting 'Too many players'"); send(myName, agentName, Command.TOO_MANY_PLAYERS); return; } } else // disconnect { c.println("Remove player. Name: " + agentName); if (!players.contains(agentName)) return; else players.remove(agentName); } if (players.isEmpty()) c.println("No players in game."); if (players.size() == 1) { c.println("One player in game. Name: " + players.get(0)); send(myName, players.get(0), Command.WAIT_REMOTE_CONNECT); } if (players.size() == 2) { // Game may start now... c.println("Second player arrived. Name: " + agentName); // We transmit names of players String player0 = players.get(0); String player1 = players.get(1); c.println("Transmitting names of players:"); c.println("First player: " + player0); c.println("Second player: " + player1); String text = player0 + "-->" + player1; sendCommand(myName, player0, Command.PLAYER_NAMES, TcpTools.stringToIntAry(text)); text = player1 + "-->" + player0; sendCommand(myName, player1, Command.PLAYER_NAMES, TcpTools.stringToIntAry(text)); // We transmit who begins send(myName, player1, Command.LOCAL_MOVE); // Second player begins send(myName, player0, Command.REMOTE_MOVE); // Now we transmit new game state c.println("Dealing out now."); dealingOut(); sendGameState(); } } private void sendGameState() { int[] data = new int[17]; data[0] = Command.INIT; for (int i = 0; i < 16; i++) data[i + 1] = state[i]; send(myName, players.get(0), data); send(myName, players.get(1), data); } public void pipeRequest(String source, String destination, int[] indata) { if (indata[0] == Command.END_OF_GAME) { int winnerIndex = players.indexOf(source); int loserIndex = (winnerIndex + 1) % 2; String winner = source; String loser = players.get(loserIndex); c.println("Winner: " + source + "; loser: " + loser); // Next game will start in 10 s TcpTools.delay(10000); dealingOut(); sendGameState(); send(myName, loser, Command.LOCAL_MOVE); // loser begins send(myName, winner, Command.REMOTE_MOVE); return; } // destination is empty, we decide that the data goes to the partner String target = ""; if (players.get(0).equals(source)) target = players.get(1); if (players.get(1).equals(source)) target = players.get(0); send(source, target, indata); reportPipeAction(source, target, indata); } private void reportPipeAction(String source, String destination, int[] data) { c.println("pipe: " + source + "-->" + destination); c.print("data: ["); for (int i = 0; i < data.length; i++) { c.print(data[i]); if (i < data.length - 1) c.print(", "); } c.println("]"); } public static void main(String[] args) { new TcpMemoryServer(); } } |
// TcpMemory.java import javax.swing.JOptionPane; import ch.aplu.jgamegrid.*; import ch.aplu.tcp.*; import java.awt.Color; import ch.aplu.util.*; public class TcpMemory extends GameGrid implements GGMouseListener { private final String VERSION = "1.1"; private final String serverName = "MemoryServer"; private String sessionID; private TcpAgent tcpAgent; private MemoryCard firstCard; private MemoryCard secondCard; private boolean isFirstMove; private int myScore; private int rivalScore; private String playerNames; private static final int horzCells = 4; private static final int vertCells = 4; private static final int nbCells = horzCells * vertCells; // Must be even private MemoryCard[] cards = new MemoryCard[nbCells]; // Protocol tags private interface Command { int STATUS = 0; int INIT = 1; int SHOW = 2; int HIDE = 3; int SCORE = 4; int NAME_IN_USE = 5; int TOO_MANY_PLAYERS = 6; int PLAYER_NAMES = 7; int WAIT_REMOTE_CONNECT = 8; int REMOTE_MOVE = 9; int LOCAL_MOVE = 10; int END_OF_GAME = 11; } public TcpMemory() { super(horzCells, vertCells, 115, Color.red, null, false); setTitle("Memory Game (V" + VERSION + ")"); setBgColor(Color.white); for (int i = 0; i < nbCells; i++) { if (i < nbCells / 2) cards[i] = new MemoryCard(i); else cards[i] = new MemoryCard(i - nbCells / 2); } addMouseListener(this, GGMouse.lPress); setMouseEnabled(false); // Will be enabled when we get the move show(); connect(); // Main thread is responsible to turn back cards on a bad move while (true) { Monitor.putSleep(); // Wait until there is something to do delay(2000); // Sleep awhile firstCard.show(1); secondCard.show(1); refresh(); tcpAgent.send("", Command.HIDE, firstCard.getLocation().x, firstCard.getLocation().y); tcpAgent.send("", Command.HIDE, secondCard.getLocation().x, secondCard.getLocation().y); tcpAgent.send("", Command.LOCAL_MOVE); } } public boolean mouseEvent(GGMouse mouse) { Location location = toLocation(mouse.getX(), mouse.getY()); MemoryCard card = (MemoryCard)getOneActorAt(location); if (card.getIdVisible() == 0) // Card already flipped return true; card.show(0); // Show picture refresh(); // Report to rival tcpAgent.send("", Command.SHOW, location.x, location.y); if (isFirstMove) { isFirstMove = false; firstCard = card; } else { isFirstMove = true; secondCard = card; if (firstCard.getId() == secondCard.getId()) // Successful move { myScore++; tcpAgent.send("", Command.SCORE, myScore); setTitle(playerNames + ". Score: " + myScore + "/" + rivalScore); if (isGameOver()) { setMouseEnabled(false); tcpAgent.send("", Command.END_OF_GAME); showFinalScore(); return true; } } else // Bad move { setMouseEnabled(false); // Disable mouse events until remote // gives move back setTitle(playerNames + ". Wait for remote player's move..."); Monitor.wakeUp(); } } return true; } private boolean isGameOver() { for (int i = 0; i < nbCells; i++) { if (cards[i].getIdVisible() == 1) return false; } return true; } private String requestEntry(String prompt) { String entry = ""; while (entry.length() < 3) { entry = JOptionPane.showInputDialog(null, prompt, ""); if (entry == null) System.exit(0); } return entry.trim(); } private void connect() { String sessionID = requestEntry("Enter the session ID (ASCII >3 chars):"); String localName = requestEntry("Enter your name (ASCII >3 chars):"); tcpAgent = new TcpAgent(sessionID, serverName); tcpAgent.addTcpAgentListener(new TcpAgentAdapter() { public void dataReceived(String source, int[] data) { switch (data[0]) { case Command.TOO_MANY_PLAYERS: setTitle("Connected. But too many players."); break; case Command.WAIT_REMOTE_CONNECT: clear(); setTitle("Wait until remote player connects..."); break; case Command.PLAYER_NAMES: playerNames = TcpTools.intAryToString(data, 1); break; case Command.REMOTE_MOVE: setTitle(playerNames + ". Wait for remote player's move..."); break; case Command.LOCAL_MOVE: isFirstMove = true; setTitle(playerNames + ". Please click on two cards!"); setMouseEnabled(true); break; case Command.INIT: init(data); break; case Command.SHOW: showCard(data[1], data[2], true); break; case Command.HIDE: showCard(data[1], data[2], false); break; case Command.SCORE: rivalScore = data[1]; if (isGameOver()) showFinalScore(); else setTitle(playerNames + ". Score: " + myScore + "/" + rivalScore); break; } } }); setTitle("Connecting to relay..."); if (tcpAgent.connectToRelay(localName, 6000).isEmpty()) { setTitle("Connection to relay failed"); return; } setTitle("Connection to relay established"); if (!tcpAgent.isBridgeConnected()) { setTitle("Game server not found."); return; } } private void showFinalScore() { String s = ""; if (myScore > rivalScore) s = " (Winner)"; if (myScore < rivalScore) s = " (Loser)"; if (myScore == rivalScore) s = " (Tie)"; setTitle(playerNames + ". Game over. Score: " + myScore + "/" + rivalScore + s + ". Wait..."); } private void showCard(int x, int y, boolean show) { if (show) getOneActorAt(new Location(x, y)).show(0); else getOneActorAt(new Location(x, y)).show(1); refresh(); } private void clear() { removeAllActors(); refresh(); } private void init(int[] data) { myScore = 0; rivalScore = 0; isFirstMove = true; removeAllActors(); int k = 1; for (int i = 0; i < nbCells; i++) cards[i].show(1); // show back for (int x = 0; x < nbHorzCells; x++) for (int y = 0; y < nbVertCells; y++) addActor(cards[data[k++]], new Location(x, y)); } public static void main(String[] args) { new TcpMemory(); } } // -------------------- class MemoryCard-------------------------- class MemoryCard extends Actor { private int id; public MemoryCard(int id) { super("sprites/card" + id + ".gif", "sprites/cardback.gif"); this.id = id; } public int getId() { return id; } } |