Java实现简单井字棋小游戏代码实例
然后就想能不能聪明一点,可以判断出走哪一步棋;然后只能做到不会输,还是不够聪明,只能呆板地堵住用户,smartRobot的第三个判断逻辑找不到最佳位置,赢得概率比较小;而且我没事干时,想玩玩这个小游戏找找成就感,但每次都会赢了机器人,所以删删改改了四五次,最后才成。
可以选择谁先开始,但startGame里的代码更加冗余了。看着就很乱,但没想到好的办法。
smartRobot里的代码全部重写了,比原来更聪明一点了:下在四个角的位置时,能优先选择最佳位置;然后没有最佳位置时,再随便找一空的(随便找空四角位置使用for代替了,比原来更简短)。
然后smartRobot的第一个和第三个判断逻辑,也更聪明一点了。原来判断机器人和判断用户的逻辑,是放在一个for循环里的,但无法找到最佳位置,现在分开了。
机器人先开始时,才能发挥出来新添加的机器人的“小聪明”;但机器人原来的能力发挥不回来,只有用户先开始时才能发挥出原来的能力。所以各有利弊,无论谁先开始都能适应。如果机器人先开始,并且用户第一步棋不是下在四角的位置,那么用户就必输了。其他的情况一般都是平局了。
想到一个因为可以选择谁先开始而导致startGame代码冗余的问题的解决方法,就是使用局部内部类。内部类能访问到方法的局部对象。
主逻辑startGame:
1.用一个3X3的二维数组,存储棋盘;
2.用户输入1~9下棋;
3.判断是否合法,不合法则重新输入;
4.将1~9转换成二维的坐标x=(pos-1)/3,y=(pos-1)%3,再令二维数组相应位置为'O';
5.判断用户是否胜利,是则退出;再判断是否平局,是则退出;
6.机器人下棋(根据输入等级,调用不同函数);
7.打印棋盘显示出用户和机器人下的棋子;
8.判断机器人是否胜利,是则退出;再判断是否平局,是则退出;都不是返回第1步。
isSuccessful判断成功的逻辑:
判断所有行、列、对角线是否有连成一条线的,用字符相加的和判断即可
willBeSuccessful判断是否将要成功:
这里判断的是是否有行、列有两个相同棋子和一个空白,用字符相加的和判断。
calculate计算行列对角线:
使用枚举类,来判断是计算行,还是计算列,还是计算左右对角线;计算行列时,传入一个1~3的数字表示是哪一行那一列。
smartRobot的第一个判断逻辑:
如果棋子下在箭头指向的那个位置,那么一步棋就可胜利。
机器人先判断自己是否有这样一个位置,有则下在哪个地方,胜利;
方法是尝试填入所有空白地方,每填一次,判断一次isSuccessful;
如果没有,再判断对方是否有这样一个位置,有则堵住这个地方。
smartRobot的第三个判断逻辑:
如果棋子下在箭头指向的位置,那么再下一步必会胜利,因为下在了那个地方,第三列、第三行都是两个棋子了,无论对方堵哪里,都会失败。
也是机器人先判断自己是否有这样一个位置,有则下;
调用willBeSuccessful判断是否有这样的位置。
没有则再判断对方是否有这样的位置,有则堵住。
smartRobot的第零个和第二个判断逻辑:
处理四个角和中心的位置,如果用户下在了中心,那么机器人必须至少有两个棋子下在四角位置才能保证不输。
更改了无数次的代码:
importjava.util.Arrays; importjava.util.Scanner; publicclassExperiment_1{ publicstaticvoidmain(String[]args){ ThreeChessgame=newThreeChess(); game.startGame(); } } classThreeChess{ privatechar[][]chessBoard=newchar[3][3]; privateintsize=0;//已经下的棋数 privatefinalintCAPACITY=9;//总共可下的棋数 ThreeChess(){ for(char[]line:chessBoard){//初始化棋盘 Arrays.fill(line,''); } } //【游戏开始】 publicvoidstartGame(){ System.out.println("┌───┬───┬───┐"); System.out.println("│1│2│3│"); System.out.println("├───┼───┼───┤"); System.out.println("│4│5│6│"); System.out.println("├───┼───┼───┤"); System.out.println("│7│8│9│"); System.out.println("└───┴───┴───┘"); System.out.println("输入1~9表示要下棋的位置"); System.out.println("O是你的棋子,*是电脑的棋子"); Scannerin=newScanner(System.in); System.out.print("选择谁先开始:\n\t1.用户\n\t2.机器人\nInput:"); intwhoFirst=in.nextInt(); System.out.print("选择机器人智商:\n\t1.999+\n\t2.250\nInput:"); intlevel=in.nextInt(); classPlay{//代码重用 //方法返回-1表示退出 introbotPlay(){ if(level==1) smartRobot(); else sillyRobot(); printChessBroad(); if(isSuccessful()==-1){ System.out.println("机器人胜(/□\\)"); return-1; }elseif(size==CAPACITY){ System.out.println("==游戏平局=="); return-1; } return0; } intuserPlay(){ intpos; while(true){ System.out.print("下棋位置:"); pos=in.nextInt(); if(pos<1 ||pos>9 ||chessBoard[(pos-1)/3][(pos-1)%3]!=''){ System.out.println("输入错误,重新输入!"); continue; }else{ chessBoard[(pos-1)/3][(pos-1)%3]='O'; size++; break; } } if(isSuccessful()==1){ printChessBroad(); System.out.println("恭喜,你胜了╰(*°▽°*)╯"); return-1; }elseif(size==CAPACITY){ printChessBroad(); System.out.println("==游戏平局=="); return-1; } return0; } } Playplay=newPlay(); if(whoFirst==2){ while(true){ //1.机器人下棋 if(play.robotPlay()==-1) return; //2.用户下棋 if(play.userPlay()==-1) return; } }else{ while(true){ //1.用户下棋 if(play.userPlay()==-1) return; //2.机器人下棋 if(play.robotPlay()==-1) return; } } } //【机器人下棋】 privatevoidsillyRobot(){//笨机器人 intl,c; while(true){ l=(int)(Math.random()*3); c=(int)(Math.random()*3); if(chessBoard[l][c]==''){ chessBoard[l][c]='*'; break; } } size++; } privateintcorner=2; privatevoidsmartRobot(){//无法战胜的机器人 if(chessBoard[1][1]==''){//抢占中心位置 chessBoard[1][1]='*'; size++; return; } //1.判断是否可以下一个棋子就胜利(不能放在一起同时判断,否则有可能错误最佳位置) for(inti=0;i<3;i++){ for(intj=0;j<3;j++){ if(chessBoard[i][j]==''){//【1】如果这个位置没有棋子,就尝试下载这个地方,看看是否可以胜; chessBoard[i][j]='*'; if(isSuccessful()==-1){//【1】如果胜的话,就下在这个地方了,返回即可; size++; return; } else chessBoard[i][j]=''; } } } for(inti=0;i<3;i++){ for(intj=0;j<3;j++){ //【2】逻辑同【1】 if(chessBoard[i][j]==''){ chessBoard[i][j]='O';//【2】否则尝试用户下在这个位置 if(isSuccessful()==1){//【2】如果用户下在这个位置会胜利,就占领它。 chessBoard[i][j]='*'; size++; return; }else chessBoard[i][j]=''; } } } //2.如果用户下在了中间的话,就赶紧占两个四角的位置,才能保证不输。优先级要比第一个低。用户没下在中间也可抢占。 if(corner>0){ corner--; for(inti=0;i<3;i++){//优先找四边中没有用户棋子的地方下 if(i==1) continue; booleanNoBigO=true; for(intj=0;j<3;j++){ if(chessBoard[i][j]=='O') NoBigO=false; } for(intj=0;j<3&&NoBigO;j++){ if(chessBoard[i][j]==''){ chessBoard[i][j]='*'; size++; return; } } } for(inti=0;i<3;i++){ for(intj=0;j<3;j++){ if(j==1||i==1) continue; if(chessBoard[i][j]==''){ chessBoard[i][j]='*'; size++; return; } } } }//endif //3.判断是否可以下一个棋子,从而再下一步可以胜利(不能放在一起判断) for(inti=0;i<3;i++){ for(intj=0;j<3;j++){ if(chessBoard[i][j]==''){ chessBoard[i][j]='*'; if(willBeSuccessful(-1)){ size++; return; }else chessBoard[i][j]=''; } } } for(inti=0;i<3;i++){ for(intj=0;j<3;j++){ if(chessBoard[i][j]==''){ chessBoard[i][j]='O'; if(willBeSuccessful(1)){ chessBoard[i][j]='*'; size++; return; }else chessBoard[i][j]=''; } } } sillyRobot(); } //【打印棋盘】 privatevoidprintChessBroad(){ System.out.println("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");//模拟清屏 System.out.println("┌───┬───┬───┐"); System.out.println("│"+chessBoard[0][0]+"│"+chessBoard[0][1]+"│"+chessBoard[0][2]+"│"); System.out.println("├───┼───┼───┤"); System.out.println("│"+chessBoard[1][0]+"│"+chessBoard[1][1]+"│"+chessBoard[1][2]+"│"); System.out.println("├───┼───┼───┤"); System.out.println("│"+chessBoard[2][0]+"│"+chessBoard[2][1]+"│"+chessBoard[2][2]+"│"); System.out.println("└───┴───┴───┘"); } //【判断成功逻辑】 privateenumChoice{ LINE,//行 COLUMN,//列 RIGHT_DIAGONAL,//右对角线 LEFT_DIAGONAL;//左对角线 } privateintcalculate(Choicechoice,inti){//计算行、列、对角线是否连成一条线 switch(choice){ caseLINE: returnchessBoard[i][0]+chessBoard[i][1]+chessBoard[i][2]; caseCOLUMN: returnchessBoard[0][i]+chessBoard[1][i]+chessBoard[2][i]; caseRIGHT_DIAGONAL: returnchessBoard[0][0]+chessBoard[1][1]+chessBoard[2][2]; caseLEFT_DIAGONAL: returnchessBoard[0][2]+chessBoard[1][1]+chessBoard[2][0]; } return0; } privateintisSuccessful(){ /* 返回-1系统胜;返回1用户胜;返回0表示继续下棋。 系统胜:126=='*'+'*'+'*' 用户胜:237=='O'+'O'+'O' */ for(inti=0;i<3;i++){ if(calculate(Choice.LINE,i)==237||calculate(Choice.COLUMN,i)==237) return1; if(calculate(Choice.LINE,i)==126||calculate(Choice.COLUMN,i)==126) return-1; } if(calculate(Choice.LEFT_DIAGONAL,0)==237||calculate(Choice.RIGHT_DIAGONAL,0)==237) return1; if(calculate(Choice.LEFT_DIAGONAL,0)==126||calculate(Choice.RIGHT_DIAGONAL,0)==126) return-1; return0;//继续下棋 } privatebooleanwillBeSuccessful(intwho){//who:-1表示判断机器人的,+1表示判断用户的。 //如果行、列、对角线有2个相同棋子的个数,则将会胜, //190==2*'O'+'' //116==2*'*'+'' intn=0; ints=(who==1)?190:116;//用户or机器人要计算的值 for(inti=0;i<3;i++){ if(calculate(Choice.LINE,i)==s) n++; if(calculate(Choice.COLUMN,i)==s) n++; } //因为中心一定会被占的,所以就不用判断对角线了 returnn>1; } }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。