Dieses Mal hatte ich in einer Universitätsklasse die Aufgabe, über die Kommunikation zwischen Server und Client etwas in Java zu erstellen. Als Schüler entschied ich mich, ein Numer0n-Spiel zu entwickeln, das ich während des Unterrichts spielte. Als ich ein Gymnasiast war, war ich so süchtig nach dem Numer0n-Spiel, dass ich es genoss, die Wahrscheinlichkeit, im ersten Zug 〇EAT〇BITE zu werden, manuell zu berechnen. .. ..
Wenn Sie diesen Artikel lesen, kennen Sie wahrscheinlich die Grundregeln von Numer0n, daher werde ich diesen Teil weglassen. Numeron Wikipedia
Java:version 7 Eclipse: Juno 4.2 OS: windows10
Was ich in diesem System implementieren möchte, ist
Wenn Sie den gesamten Code eingeben, wird er lang sein. Dieses Mal werde ich nur die Channel-Klasse veröffentlichen, die für das Senden und Empfangen auf der Serverseite zuständig ist, sowie die Numer0nAI-Klasse, die den Computeralgorithmus implementiert. Alle Kurse und Präsentationsmaterialien (powerpo) sind auf GitHub veröffentlicht. Schauen Sie also bitte vorbei, wenn Sie möchten! Numeron AI ist auch in Python implementiert. Wenn Sie also Python häufig verwenden, tun Sie dies bitte auch! Numer0n (GitHub) erstellt mit Java Python Numer0nAI (GitHub)
Nach Bestätigung der Eingabe vom Client erstellt der Server einen Kanal, und der Kanal und der Client interagieren miteinander. Selbst wenn eine unbeabsichtigte Ausnahme beim Client auftritt, fällt der ursprüngliche Server nicht aus und die Verbindung anderer Clients bleibt erhalten.
Channel.java
package server;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Channel extends Thread {
JUDGE judge = new JUDGE();
Server server;
Socket socket = null;
BufferedReader input;
OutputStreamWriter output;
String handle;
String playertype;
String roomnumber;
String mynumber;
String tekinumber;
boolean turn;
String ex = "926";//Erste Vorhersage der KI
String ca ="0123456789";//Kandidatennummer: 0-0 zuerst
String ex_number;
List<String> old_list = new ArrayList<>();
final char controlChar = (char)05;
final char separateChar = (char)06;
Channel(Socket s,Server cs){
this.server = cs;
this.socket = s;
this.start();
}
synchronized void write(String s){
try{
output.write(s + "\r\n");
output.flush();
}catch(IOException e){
System.out.println("Write Err");
close();
}
}
public void run(){
List<String> s_list = new ArrayList<>();//Eine Liste, die Eingaben von Clients empfängt und speichert
String s;
String opponent = null;
try{
input = new BufferedReader(
new InputStreamReader(socket.getInputStream()));
output = new OutputStreamWriter(socket.getOutputStream());
write("# Welcome to Numr0n Game");
write("# Please input your name");
handle = input.readLine();
System.out.println("new user: "+ handle);
while(true){//Host oder Gast warten auf Eingabe
write("INPUT YOUR TYPE(HOST or GUEST or AI)");
playertype = input.readLine();
if(playertype.equals("HOST")){
Random rnd = new Random();
s = String.valueOf(rnd.nextInt(100)+100);
write("[HOST]Zimmernummer: "+s);
break;
}else if(playertype.equals("GUEST")){
write("[GUEST]Bitte geben Sie die Zimmernummer ein");
s = input.readLine();
write("[GUEST]Zimmernummer: "+s);
break;
}else if(playertype.equals("AI")){
write("[vs AI-Modus]");
Random rnd = new Random();
s = String.valueOf(rnd.nextInt(100)+100);
write("[HOST]Zimmernummer: "+s);
break;
}else{
write("Fehler bei der Eingabe der Zimmernummer");
}
}
roomnumber = s; //Raumnummer bestimmen
System.out.println(roomnumber);
write("Warten auf einen Gegner");
if(playertype.equals("AI")){
//Spiele gegen AI
write("Entscheide dich für deine eigene Nummer (*3-stellige Nummer*Von 0 bis 9*Keine Nummernabdeckung)");
boolean firstnum = false;
while(firstnum == false){//Erfüllt meine erste Nummer die oben genannten Bedingungen?
mynumber = input.readLine();
firstnum = judge.isNumber(mynumber);
}
write("Meine Nummer: "+ mynumber);
write(handle + "Beginne am");
tekinumber="864";
NumeronAI numeron = new NumeronAI();
while(true){
//Spielbeginn
boolean finish = false;
s = input.readLine();
if(s == null){
close();
}else{
System.out.println(s);
boolean numsuccess = judge.isNumber(s);//Nummer ist in Definition
if (numsuccess) {
JUDGE eatbite = judge.EatBite(s, tekinumber);
finish = judge.Finish(eatbite.eat);//Ob es 3eat wurde
write("["+ s +"] eat: " +String.valueOf(eatbite.eat) +" bite: "+ String.valueOf(eatbite.bite));
//Ich drehe mich von hier aus
JUDGE AIeatbite = judge.EatBite(ex, mynumber);
NumeronAI squeeze = numeron.Squeeze(AIeatbite.eat,AIeatbite.bite,ex,ca,old_list);
if(squeeze.new_can_list.size()<300){
//System.out.println(Arrays.toString(squeeze.new_can_list.toArray()));
//System.out.println(squeeze.can_num);
ex_number = numeron.choice(squeeze.new_can_list,squeeze.can_num);
}else{
Random rnd = new Random();
int index = rnd.nextInt(100);
ex_number = squeeze.new_can_list.get(index);
}
old_list = new ArrayList<>(squeeze.new_can_list);
//System.out.println("Anzahl der verbleibenden Kandidaten: " + String.valueOf(old_list.size()));
write("AI-Vorhersagewert:" + ex + " [Anzahl der verbleibenden Kandidaten: " + String.valueOf(old_list.size())+"Stücke]");
//System.out.println("AI-Vorhersagewert: "+ ex);
if(mynumber.equals(ex)){
write("#################you lose#################");
}
ex = ex_number;
//Dies ist die KI-Runde
} else {
write(" did not send such a number");
}
}
if(finish){
write("#################you win#################");
}
}
}else{//gegen Menschen
while(opponent == null){//Warten auf einen Gegner
opponent = server.findopponent(handle,roomnumber);
}
//write("Der Gegner wurde entschieden");
write("Entscheide dich für deine eigene Nummer (*3-stellige Nummer*Von 0 bis 9*Keine Nummernabdeckung)");
boolean firstnum = false;
while(firstnum == false){//Erfüllt meine erste Nummer die oben genannten Bedingungen?
mynumber = input.readLine();
firstnum = judge.isNumber(mynumber);
}
write("Meine Nummer: "+ mynumber);
while(tekinumber == null){//Warten Sie, bis Sie die Nummer des Feindes erhalten
tekinumber = server.findopponentnumber(handle, roomnumber);
}
if(playertype.equals("HOST")){
turn = true;
}else{
turn =false;
}
write("Starten Sie vom HOST-Spieler");
while(true){
//Spielbeginn
boolean finish = false;
while(true){
//Bestätigung der Wende
s_list.add(input.readLine());//Geben Sie die Eingabe ein
turn = server.isTurn(handle);//Bestätigung der Wende
if(turn == true){
break;
}
}
s = s_list.get(s_list.size()-1);
s_list.clear();
if(s == null){
close();
}else{
System.out.println(s);
boolean numsuccess = judge.isNumber(s);//Nummer ist in Definition
if (numsuccess) {
//write("judge ok");
boolean connectsuccess = server.singleSend(opponent,"[Vorhersage der anderen Partei] "+s);//Es gibt einen Partner
if(connectsuccess){
//write("Es gibt einen Partner");
JUDGE eatbite = judge.EatBite(s, tekinumber);
finish = judge.Finish(eatbite.eat);//Ob es 3eat wurde
write(" [Meine Vorhersage]"+ s +" eat: " +String.valueOf(eatbite.eat) +" bite: "+ String.valueOf(eatbite.bite));
server.ChangeTurn(handle, opponent);//Schalter drehen
}else{
write("did not find opponent");
}
} else {
write(" did not send such a number");
}
}
if(finish){
write("#################you win#################");
server.singleSend(opponent, "#################you lose#################");
}
}
}
}catch(IOException e){
System.out.println("Exception occurs in Channel: "+handle);
}
}
public void close(){
try{
input.close();
output.close();
socket.close();
socket = null;
//server.broadcast("Leitungstrennung: " + handle);
}catch(IOException e){
System.out.println("Close Err");
}
}
}
Die Numeron AI-Klasse ist eine Klasse, die den Vorhersage-Teil des Computers implementiert. Die Vorhersage besteht aus der Squeeze-Methode, die die möglichen Kandidaten aus den erhaltenen EAT-BITE-Informationen eingrenzt, der Choice-Methode, die einen guten Zug aus den Kandidaten auswählt, und der count_cand-Methode, die einen guten Zug berechnet. Eine Hand, die gut aussieht, ist die mit der geringsten Anzahl erwarteter korrekter Antwortkandidaten aus allen Kombinationen von EAT-BITE, die zurückgegeben werden, wenn eine bestimmte Hand ausgewählt wird. Weitere Informationen finden Sie unter Überlegen, wie Sie numer0n gewinnen können. Ich implementiere etwas in der Nähe dieser Theorie! Ich denke übrigens, die durchschnittliche Anzahl der Anrufe liegt bei 5 oder 6 (Erfahrung).
NumeronAI.java
package server;
import java.util.ArrayList;
import java.util.List;
public class NumeronAI {
List<String> new_can_list = new ArrayList<>();//candidate list
String can_num;//candidate number
//Grenzen Sie die Anzahl der möglichen Kandidaten ein
public NumeronAI Squeeze(int eat,int bite,String pred_num,String ca_num,List<String> old_list){
NumeronAI squeeze = new NumeronAI();
List<String> can_list = new ArrayList<>();
List<String> li = new ArrayList<>();
if(eat == 0 && bite == 0){
//System.out.println("--------" + String.valueOf(ca_num.length()));
for(int i = 0; i<ca_num.length();i++){
if(ca_num.charAt(i) != pred_num.charAt(0) && ca_num.charAt(i) != pred_num.charAt(1) && ca_num.charAt(i) != pred_num.charAt(2)){
li.add(String.valueOf(ca_num.charAt(i)));
}
}
ca_num ="";
StringBuilder builder = new StringBuilder();
for(String num : li){
builder.append(num);
}
ca_num = builder.substring(0,builder.length());
for(int i = 0;i<ca_num.length();i++){
for(int j = 0;j<ca_num.length();j++){
for(int k = 0;k<ca_num.length();k++){
if(ca_num.charAt(i)!=ca_num.charAt(j) && ca_num.charAt(i)!=ca_num.charAt(k) && ca_num.charAt(j)!=ca_num.charAt(k)){
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(ca_num.charAt(j))+String.valueOf(ca_num.charAt(k)));
}
}
}
}
}else if(eat ==0 && bite ==1){
for(int i = 0;i<ca_num.length();i++){
for(int j = 0;j<ca_num.length();j++){
if(ca_num.charAt(i) != ca_num.charAt(j) && ca_num.charAt(i)!=pred_num.charAt(0) && ca_num.charAt(i)!=pred_num.charAt(1) && ca_num.charAt(i)!=pred_num.charAt(2)){
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(0))+String.valueOf(ca_num.charAt(j)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(ca_num.charAt(j))+String.valueOf(pred_num.charAt(0)));
can_list.add(String.valueOf(pred_num.charAt(1))+String.valueOf(ca_num.charAt(i))+String.valueOf(ca_num.charAt(j)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(ca_num.charAt(j))+String.valueOf(pred_num.charAt(1)));
can_list.add(String.valueOf(pred_num.charAt(2))+String.valueOf(ca_num.charAt(i))+String.valueOf(ca_num.charAt(j)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(2))+String.valueOf(ca_num.charAt(j)));
}
}
}
}else if(eat ==0 && bite ==2){
for(int i = 0;i<ca_num.length();i++){
if(ca_num.charAt(i)!=pred_num.charAt(0) && ca_num.charAt(i)!=pred_num.charAt(1) && ca_num.charAt(i)!=pred_num.charAt(2)){
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(0))+String.valueOf(pred_num.charAt(1)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(0)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(1)));
can_list.add(String.valueOf(pred_num.charAt(1))+String.valueOf(pred_num.charAt(0))+String.valueOf(ca_num.charAt(i)));
can_list.add(String.valueOf(pred_num.charAt(1))+String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(0)));
can_list.add(String.valueOf(pred_num.charAt(1))+String.valueOf(pred_num.charAt(2))+String.valueOf(ca_num.charAt(i)));
can_list.add(String.valueOf(pred_num.charAt(2))+String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(0)));
can_list.add(String.valueOf(pred_num.charAt(2))+String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(1)));
can_list.add(String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(0))+String.valueOf(ca_num.charAt(i)));
}
}
}else if(eat == 0 && bite ==3){
can_list.add(String.valueOf(pred_num.charAt(1))+String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(0)));
can_list.add(String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(0))+String.valueOf(pred_num.charAt(1)));
}else if(eat == 1 && bite ==0){
for(int i = 0;i<ca_num.length();i++){
for(int j = 0;j<ca_num.length();j++){
if(ca_num.charAt(i)!=ca_num.charAt(j) && ca_num.charAt(i)!=pred_num.charAt(0) && ca_num.charAt(i)!=pred_num.charAt(1) &&
ca_num.charAt(i)!=pred_num.charAt(2) && ca_num.charAt(j)!=pred_num.charAt(0) &&
ca_num.charAt(j)!=pred_num.charAt(1) && ca_num.charAt(j)!=pred_num.charAt(2)){
can_list.add(String.valueOf(pred_num.charAt(0))+String.valueOf(ca_num.charAt(i))+String.valueOf(ca_num.charAt(j)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(1))+String.valueOf(ca_num.charAt(j)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(ca_num.charAt(j))+String.valueOf(pred_num.charAt(2)));
}
}
}
}else if(eat ==1 && bite ==1){
for(int i = 0;i<ca_num.length();i++){
if(ca_num.charAt(i)!=pred_num.charAt(0) && ca_num.charAt(i)!=pred_num.charAt(1) && ca_num.charAt(i)!=pred_num.charAt(2)){
can_list.add(String.valueOf(pred_num.charAt(0))+String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(1)));
can_list.add(String.valueOf(pred_num.charAt(0))+String.valueOf(pred_num.charAt(2))+String.valueOf(ca_num.charAt(i)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(1))+String.valueOf(pred_num.charAt(0)));
can_list.add(String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(1))+String.valueOf(ca_num.charAt(i)));
can_list.add(String.valueOf(pred_num.charAt(1))+String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(2)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(0))+String.valueOf(pred_num.charAt(2)));
}
}
}else if(eat ==1 && bite ==2){
for(int i = 0;i<ca_num.length();i++){
can_list.add(String.valueOf(pred_num.charAt(0))+String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(1)));
can_list.add(String.valueOf(pred_num.charAt(2))+String.valueOf(pred_num.charAt(1))+String.valueOf(pred_num.charAt(0)));
can_list.add(String.valueOf(pred_num.charAt(1))+String.valueOf(pred_num.charAt(0))+String.valueOf(pred_num.charAt(2)));
}
}else if(eat ==2 && bite ==0){
for(int i = 0;i<ca_num.length();i++){
if(ca_num.charAt(i)!=pred_num.charAt(0) && ca_num.charAt(i)!=pred_num.charAt(1) && ca_num.charAt(i)!=pred_num.charAt(2)){
can_list.add(String.valueOf(pred_num.charAt(0))+String.valueOf(pred_num.charAt(1))+String.valueOf(ca_num.charAt(i)));
can_list.add(String.valueOf(pred_num.charAt(0))+String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(2)));
can_list.add(String.valueOf(ca_num.charAt(i))+String.valueOf(pred_num.charAt(1))+String.valueOf(pred_num.charAt(2)));
}
}
}else if(eat ==3 && bite ==0){
can_list.add(pred_num);
}
if(old_list.size()!=0){
for(String num : can_list){
if(old_list.contains(num)){
squeeze.new_can_list.add(num);
squeeze.can_num =ca_num;
}
}
}else{
squeeze.new_can_list = can_list;
squeeze.can_num = ca_num;
}
//System.out.println(can_num);
return squeeze;
}
//Berechnen Sie die erwartete Anzahl von Kandidaten
public double count_cand(String pred_num,String ca_num,List<String> ca_list){
double ave_ca = 0;
int[][] info_list = {{0,0},{0,1},{0,2},{0,3},{1,0},{1,1},{1,2},{2,1},{3,0}};
int sum_ex = 0;
int sum_ex2 = 0;
List<String> old_count_list = new ArrayList<>(ca_list);
String ca_count_num = ca_num;
NumeronAI squeeze2 = new NumeronAI();
for(int[] info :info_list){
squeeze2 = Squeeze(info[0],info[1],pred_num,ca_count_num,old_count_list);
sum_ex=sum_ex+squeeze2.new_can_list.size();
sum_ex2=sum_ex2+squeeze2.new_can_list.size()^2;
}
if(sum_ex!=0){
ave_ca=sum_ex2/sum_ex;
}
return ave_ca;
}
//Wählen Sie die Nummer mit der kleinsten erwarteten Anzahl von Kandidaten
public String choice(List<String> ca_list,String ca_num){
List<Double> ave_list = new ArrayList<>();
int min_index =0;
try{
for(String num :ca_list){
double ave_ca = count_cand(num,ca_num,ca_list);
ave_list.add(ave_ca);
}
double min =ave_list.get(0);
for(int i =0;i<ave_list.size();i++){
double val = ave_list.get(i);
if(min > val){
min = val;
min_index = i;
}
}
return ca_list.get(min_index);
}catch(Exception e){
System.out.println("Wahl Fräulein:" + e);
return "111";
}
}
}
Dieses Mal wurde ich in 6 Runden getroffen.
Ich habe nicht viel über Java geschrieben, aber ich glaube, ich habe getan, was ich machen wollte. Da ich jedoch noch nicht das Niveau des Übens von Kenntnissen über Entwurfsmuster erreicht habe, wurde mir klar, dass ich studieren muss. (Designmuster ist schwierig ...) Das Schreiben von Numer0ns KI (ich möchte es nicht KI nennen) selbst wird für diejenigen empfohlen, die Numer0n kennen und etwas machen möchten, da die Regeln leicht zu verstehen sind!
Außerdem habe ich nur den Numeron AI-Teil in Python erstellt, daher habe ich kein Java geschrieben. Wenn Sie ihn jedoch mit Python verstehen können, lesen Sie ihn bitte.
Ich poste Qiita zum ersten Mal. Wenn Sie also Verbesserungen in Bezug auf diesen Artikel haben, hinterlassen Sie bitte einen Kommentar <(_ _)>
Ich werde mein Bestes tun, um von nun an nach und nach auszugeben!
Recommended Posts