Cette fois, dans une classe universitaire, j'avais la tâche de créer quelque chose en Java via la communication entre le serveur et le client, alors quand j'étais lycéen, j'ai décidé de faire un jeu Numer0n auquel je jouais pendant les cours. Quand j'étais lycéen, j'étais tellement accro au jeu Numer0n que j'aimais calculer manuellement la probabilité de devenir 〇EAT〇BITE dès le premier coup. .. ..
Si vous lisez cet article, je pense que vous connaissez les règles de base de Numer0n, je vais donc omettre cette partie. Numeron Wikipedia
Java:version 7 Eclipse: Juno 4.2 OS: windows10
Ce que je veux implémenter dans ce système est
Si vous mettez tout le code, ce sera long, donc cette fois je ne posterai que la classe Channel qui est en charge de l'envoi et de la réception côté serveur et la classe Numer0nAI qui implémente l'algorithme informatique. Tous les cours et supports de présentation (powerpo) sont publiés sur GitHub, alors jetez un œil si vous le souhaitez! Numeron AI est également implémenté en python, donc si vous utilisez souvent python, faites-le aussi! Numer0n (GitHub) réalisé avec Java python Numer0nAI (GitHub)
Lors de la confirmation de l'entrée du client, le serveur crée un canal et le canal et le client interagissent l'un avec l'autre. Grâce à cela, même si une exception involontaire se produit sur le client, le serveur d'origine ne s'arrêtera pas et la connexion des autres clients sera maintenue.
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";//Première prédiction de l'IA
String ca ="0123456789";//numéro de candidat: 0-9 au début
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<>();//Une liste qui reçoit et stocke les entrées des clients
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 ou GUEST en attente d'entrée
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]Numéro de chambre: "+s);
break;
}else if(playertype.equals("GUEST")){
write("[GUEST]Veuillez saisir le numéro de la chambre");
s = input.readLine();
write("[GUEST]Numéro de chambre: "+s);
break;
}else if(playertype.equals("AI")){
write("[vs mode AI]");
Random rnd = new Random();
s = String.valueOf(rnd.nextInt(100)+100);
write("[HOST]Numéro de chambre: "+s);
break;
}else{
write("Erreur lors de la saisie du numéro de chambre");
}
}
roomnumber = s; //Déterminer le numéro de chambre
System.out.println(roomnumber);
write("En attendant un adversaire");
if(playertype.equals("AI")){
//Jouez contre l'IA
write("Choisissez votre propre numéro (*Numéro à 3 chiffres*De 0 à 9*Pas de couverture de numéro)");
boolean firstnum = false;
while(firstnum == false){//Mon premier numéro remplit-il les conditions ci-dessus?
mynumber = input.readLine();
firstnum = judge.isNumber(mynumber);
}
write("Mon numéro: "+ mynumber);
write(handle + "Commencer à partir de");
tekinumber="864";
NumeronAI numeron = new NumeronAI();
while(true){
//Début du jeu
boolean finish = false;
s = input.readLine();
if(s == null){
close();
}else{
System.out.println(s);
boolean numsuccess = judge.isNumber(s);//Le nombre est en définition
if (numsuccess) {
JUDGE eatbite = judge.EatBite(s, tekinumber);
finish = judge.Finish(eatbite.eat);//Que ce soit devenu 3eat
write("["+ s +"] eat: " +String.valueOf(eatbite.eat) +" bite: "+ String.valueOf(eatbite.bite));
//L'IA tourne à partir d'ici
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("Nombre de candidats restants: " + String.valueOf(old_list.size()));
write("Valeur de prédiction IA:" + ex + " [Nombre de candidats restants: " + String.valueOf(old_list.size())+"Pièces]");
//System.out.println("Valeur de prédiction IA: "+ ex);
if(mynumber.equals(ex)){
write("#################you lose#################");
}
ex = ex_number;
//C'est le tour de l'IA
} else {
write(" did not send such a number");
}
}
if(finish){
write("#################you win#################");
}
}
}else{//vs humain
while(opponent == null){//En attendant un adversaire
opponent = server.findopponent(handle,roomnumber);
}
//write("L'adversaire a été décidé");
write("Choisissez votre propre numéro (*Numéro à 3 chiffres*De 0 à 9*Pas de couverture de numéro)");
boolean firstnum = false;
while(firstnum == false){//Mon premier numéro remplit-il les conditions ci-dessus?
mynumber = input.readLine();
firstnum = judge.isNumber(mynumber);
}
write("Mon numéro: "+ mynumber);
while(tekinumber == null){//Attendez d'avoir le numéro de l'ennemi
tekinumber = server.findopponentnumber(handle, roomnumber);
}
if(playertype.equals("HOST")){
turn = true;
}else{
turn =false;
}
write("Commencer à partir du lecteur HOST");
while(true){
//Début du jeu
boolean finish = false;
while(true){
//Confirmation de virage
s_list.add(input.readLine());//Entrez l'entrée
turn = server.isTurn(handle);//Confirmation de virage
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);//Le nombre est en définition
if (numsuccess) {
//write("judge ok");
boolean connectsuccess = server.singleSend(opponent,"[Prédiction de l'autre partie] "+s);//Il y a un partenaire
if(connectsuccess){
//write("Il y a un partenaire");
JUDGE eatbite = judge.EatBite(s, tekinumber);
finish = judge.Finish(eatbite.eat);//Que ce soit devenu 3eat
write(" [Ma prediction]"+ s +" eat: " +String.valueOf(eatbite.eat) +" bite: "+ String.valueOf(eatbite.bite));
server.ChangeTurn(handle, opponent);//Changer de tour
}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("Déconnexion de ligne: " + handle);
}catch(IOException e){
System.out.println("Close Err");
}
}
}
La classe Numeron AI est une classe qui implémente la partie prédiction de l'ordinateur. La prédiction consiste en la méthode Squeeze qui réduit les candidats possibles à partir des informations EAT-BITE obtenues, la méthode Choice qui sélectionne un bon coup parmi les candidats et la méthode count_cand qui calcule un bon coup. Une main qui semble bonne est celle avec le plus petit nombre de candidats de réponse correcte attendus parmi toutes les combinaisons de EAT-BITE qui sont renvoyées lorsqu'une certaine main est sélectionnée. Pour plus de détails, consultez Réflexion sur la façon de gagner numer0n. J'implémente quelque chose de proche de cette théorie! Au fait, je pense que le nombre moyen d'appels est d'environ 5 ou 6 (expérience).
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
//Réduisez au nombre de candidats possibles
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;
}
//Calculez le nombre attendu de candidats
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;
}
//Sélectionnez le nombre avec le plus petit nombre attendu de candidats
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("Choix Miss:" + e);
return "111";
}
}
}
Cette fois, j'ai été touché en 6 tours.
Je n'ai pas beaucoup écrit sur Java, mais je pense avoir fait ce que je voulais faire. Cependant, je n'ai pas encore atteint le niveau de connaissance pratique des modèles de conception, alors j'ai réalisé que je devais étudier. (Le modèle de conception est difficile ...) Écrire l'IA de Numer0n (je ne veux pas l'appeler AI) par moi-même est recommandé pour ceux qui connaissent Numer0n et veulent faire quelque chose car les règles sont faciles à comprendre!
De plus, j'ai créé uniquement la partie Numeron AI en python, donc je n'ai pas écrit Java, mais si vous pouvez le comprendre avec python, veuillez vous y référer.
C'est la première fois que je publie Qiita, donc si vous avez des améliorations concernant cet article, veuillez laisser un commentaire <(_ _)>
Je ferai de mon mieux pour sortir petit à petit désormais!
Recommended Posts